// ServeHTTP implements an http.Handler that answers RPC requests. func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { if r.URL.Path != rpc.DefaultRPCPath { if s.handler != nil { s.handler.ServeHTTP(w, r) return } http.NotFound(w, r) return } // Note: this code was adapted from net/rpc.Server.ServeHTTP. if r.Method != "CONNECT" { http.Error(w, "405 must CONNECT", http.StatusMethodNotAllowed) return } // Construct an authentication hook for this security mode and TLS state. authHook, err := security.AuthenticationHook(s.context.Insecure, r.TLS) if err != nil { http.Error(w, err.Error(), http.StatusUnauthorized) return } conn, _, err := w.(http.Hijacker).Hijack() if err != nil { log.Infof("rpc hijacking %s: %s", r.RemoteAddr, err) return } if log.V(3) { security.LogTLSState("RPC", r.TLS) } if _, err := io.WriteString(conn, "HTTP/1.0 "+codec.Connected+"\n\n"); err != nil { http.Error(w, err.Error(), http.StatusUnauthorized) return } codec := codec.NewServerCodec(conn) responses := make(chan serverResponse) var wg sync.WaitGroup wg.Add(1) go func() { s.sendResponses(codec, responses) wg.Done() }() s.readRequests(codec, authHook, responses) wg.Wait() codec.Close() s.mu.Lock() if s.closeCallbacks != nil { for _, cb := range s.closeCallbacks { cb(conn) } } s.mu.Unlock() conn.Close() }
// serveConn synchronously serves a single connection. When the // connection is closed, close callbacks are invoked. func (s *Server) serveConn(conn net.Conn, authHook func(proto.Message) error) { s.ServeCodec(codec.NewServerCodec(conn, authHook)) s.mu.Lock() if s.closeCallbacks != nil { for _, cb := range s.closeCallbacks { cb(conn) } } s.mu.Unlock() conn.Close() }
// ServeHTTP implements an http.Handler that answers RPC requests. func (s *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) { // Note: this code was adapted from net/rpc.Server.ServeHTTP. if req.Method != "CONNECT" { http.Error(w, "405 must CONNECT", http.StatusMethodNotAllowed) return } // Construct an authentication hook for this security mode and TLS state. authHook, err := security.ProtoAuthHook(s.insecure, req.TLS) if err != nil { http.Error(w, err.Error(), http.StatusUnauthorized) return } conn, _, err := w.(http.Hijacker).Hijack() if err != nil { log.Infof("rpc hijacking ", req.RemoteAddr, ": ", err) return } if log.V(3) { security.LogTLSState("RPC", req.TLS) } if _, err := io.WriteString(conn, "HTTP/1.0 "+codec.Connected+"\n\n"); err != nil { http.Error(w, err.Error(), http.StatusUnauthorized) return } // Run open callbacks. s.runOpenCallbacks(conn) codec := codec.NewServerCodec(conn) responses := make(chan serverResponse) go func() { s.sendResponses(codec, responses) }() go func() { s.readRequests(conn, codec, authHook, responses) codec.Close() conn.Close() }() }