示例#1
0
// 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()
}
示例#2
0
// 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()
}
示例#3
0
// 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()
	}()
}