// Parse a client connection to a streamz server and push StreamzSample's onto // provided channel. On error, will close the channel. func Channelify(conn net.Conn) chan StreamzSample { ch := make(chan StreamzSample) bio := bufio.NewReader(conn) go func() { defer func() { close(ch) }() for { line, isprefix, err := bio.ReadLine() if err != nil { log.Println("streamz: error reading line") return } if isprefix { log.Println("streamz: line too long, dying") return } parts := bytes.Split(line, []byte("=")) if len(parts) != 2 { log.Println("streamz: malformed entry:", line) return } ch <- StreamzSample{Key: string(parts[0]), Value: string(parts[1])} } }() return ch }
func DispatchForever(connch <-chan net.Conn, srv *rpc.Server, clientch chan<- *rpc.Client) { for conn := range connch { muxed, err := muxconn.Split(conn, 2) if err != nil { log.Println("birpc: Failed to mux incoming connection from", conn.RemoteAddr().String(), "to", conn.LocalAddr().String(), ", dropping") continue } // Server on first muxed conn, client on second go srv.ServeConn(muxed[0]) clientch <- rpc.NewClient(muxed[1]) } }
// Serve on a given port // // The server will log to the default logger and will gracefully terminate on // receipt of an interrupt or kill signal. // // The following URLs are defined: // / // /healthz // /varz // /streamz // /birpc // /debug/pprof // func ServeForever(port int) error { addr := ":" + fmt.Sprint(port) l, err := net.Listen("tcp", addr) if err != nil { log.Errorln("govtil/net/server: Failed to listen on", port, err) return err } // Close listen port on signals (causes http.Serve() to return) sigch := make(chan os.Signal) signal.Notify(sigch, []os.Signal{ syscall.SIGABRT, syscall.SIGHUP, syscall.SIGINT, syscall.SIGKILL, syscall.SIGPWR, syscall.SIGQUIT, syscall.SIGSTOP, syscall.SIGTERM, }...) go func() { sig := <-sigch log.Println("govtil/net/server: Closing listen port", l.Addr().String(), "due to signal", sig) l.Close() }() logginghandler := logginghandler.New(http.DefaultServeMux, log.NORMAL) err = http.Serve(l, logginghandler) if err != nil { if vnet.SocketClosed(err) { err = nil // closed due to signal, no error } else { log.Errorln("govtil/net/server:", err) } } log.Println("govtil/net/server: Terminating") return err }
// ServeListenerForever is the same as ServeForever except it uses the specified // listener. This is useful in testing when an ephemeral port should be used. func ServeListenerForever(l net.Listener) error { // Wrap with logger handler := logginghandler.New(http.DefaultServeMux, log.GetVerbosity()) _, aps, err := net.SplitHostPort(l.Addr().String()) if err != nil { log.Errorf("govtil/net/server: failed to get port - %v", err) } log.Printf("govtil/net/server: starting on port %v", aps) // Serve err = http.Serve(l, handler) if err != nil { if vnet.SocketClosed(err) { err = nil // closed due to signal, no error } else { log.Errorf("govtil/net/server: %v", err) } } log.Println("govtil/net/server: Terminating") return err }
// Serve an HTTP request (do not call this, it is exported so net/http can // access it) func (hh *healthzHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { repch := make(chan bool) for _, handler := range hh.handlers { go func(h *subHealthzHandler) { healthy := h.HealthzFunc() if healthy { repch <- healthy } else { log.Println("healthz failed:", h.string) } }(handler) } ret := true for _ = range hh.handlers { if !<-repch { ret = false } } if ret { w.Write([]byte("OK\n")) } else { w.WriteHeader(http.StatusInternalServerError) } }