dirty functional implementation, some tests broken, some commented out

This commit is contained in:
renaynay 2020-03-24 20:24:22 +01:00
parent 991237abdb
commit e13d78db52
No known key found for this signature in database
GPG key ID: 731E44FAAFCD0274
7 changed files with 52 additions and 23 deletions

View file

@ -895,7 +895,7 @@ func retesteth(ctx *cli.Context) error {
IdleTimeout: 120 * time.Second, IdleTimeout: 120 * time.Second,
} }
httpEndpoint := fmt.Sprintf("%s:%d", ctx.GlobalString(utils.RPCListenAddrFlag.Name), ctx.Int(rpcPortFlag.Name)) httpEndpoint := fmt.Sprintf("%s:%d", ctx.GlobalString(utils.RPCListenAddrFlag.Name), ctx.Int(rpcPortFlag.Name))
listener, _, err := rpc.StartHTTPEndpoint(httpEndpoint, rpcAPI, []string{"test", "eth", "debug", "web3"}, cors, vhosts, RetestethHTTPTimeouts) listener, _, err := rpc.StartHTTPEndpoint(httpEndpoint, rpcAPI, []string{"test", "eth", "debug", "web3"}, cors, vhosts, RetestethHTTPTimeouts, []string{})
if err != nil { if err != nil {
utils.Fatalf("Could not start RPC api: %v", err) utils.Fatalf("Could not start RPC api: %v", err)
} }

View file

@ -60,16 +60,16 @@ func (s *Service) APIs() []rpc.API { return nil }
// Start is called after all services have been constructed and the networking // Start is called after all services have been constructed and the networking
// layer was also initialized to spawn any goroutines required by the service. // layer was also initialized to spawn any goroutines required by the service.
func (s *Service) Start(server *p2p.Server) error { func (s *Service) Start(server *p2p.Server) error {
var err error //var err error
s.handler, err = newHandler(s.backend) //s.handler, err = newHandler(s.backend)
if err != nil { //if err != nil {
return err // return err
} //}
if s.listener, err = net.Listen("tcp", s.endpoint); err != nil { //if s.listener, err = net.Listen("tcp", s.endpoint); err != nil {
return err // return err
} //}
go rpc.NewHTTPServer(s.cors, s.vhosts, s.timeouts, s.handler).Serve(s.listener) //go rpc.NewHTTPServer(s.cors, s.vhosts, s.timeouts, s.handler, []string{}).Serve(s.listener)
log.Info("GraphQL endpoint opened", "url", fmt.Sprintf("http://%s", s.endpoint)) //log.Info("GraphQL endpoint opened", "url", fmt.Sprintf("http://%s", s.endpoint))
return nil return nil
} }

View file

@ -186,7 +186,7 @@ func (api *PrivateAdminAPI) StartRPC(host *string, port *int, cors *string, apis
} }
} }
if err := api.node.startHTTP(fmt.Sprintf("%s:%d", *host, *port), api.node.rpcAPIs, modules, allowedOrigins, allowedVHosts, api.node.config.HTTPTimeouts); err != nil { if err := api.node.startHTTP(fmt.Sprintf("%s:%d", *host, *port), api.node.rpcAPIs, modules, allowedOrigins, allowedVHosts, api.node.config.HTTPTimeouts, api.node.config.WSOrigins); err != nil {
return false, err return false, err
} }
return true, nil return true, nil

View file

@ -291,17 +291,21 @@ func (n *Node) startRPC(services map[reflect.Type]Service) error {
n.stopInProc() n.stopInProc()
return err return err
} }
if err := n.startHTTP(n.httpEndpoint, apis, n.config.HTTPModules, n.config.HTTPCors, n.config.HTTPVirtualHosts, n.config.HTTPTimeouts); err != nil { if err := n.startHTTP(n.httpEndpoint, apis, n.config.HTTPModules, n.config.HTTPCors, n.config.HTTPVirtualHosts, n.config.HTTPTimeouts, n.config.WSOrigins); err != nil {
n.stopIPC() n.stopIPC()
n.stopInProc() n.stopInProc()
return err return err
} }
if err := n.startWS(n.wsEndpoint, apis, n.config.WSModules, n.config.WSOrigins, n.config.WSExposeAll); err != nil { // if endpoints are not the same, start separate servers
n.stopHTTP() if n.httpEndpoint != n.wsEndpoint {
n.stopIPC() if err := n.startWS(n.wsEndpoint, apis, n.config.WSModules, n.config.WSOrigins, n.config.WSExposeAll); err != nil {
n.stopInProc() n.stopHTTP()
return err n.stopIPC()
n.stopInProc()
return err
}
} }
// All API endpoints started successfully // All API endpoints started successfully
n.rpcAPIs = apis n.rpcAPIs = apis
return nil return nil
@ -359,18 +363,23 @@ func (n *Node) stopIPC() {
} }
// startHTTP initializes and starts the HTTP RPC endpoint. // startHTTP initializes and starts the HTTP RPC endpoint.
func (n *Node) startHTTP(endpoint string, apis []rpc.API, modules []string, cors []string, vhosts []string, timeouts rpc.HTTPTimeouts) error { func (n *Node) startHTTP(endpoint string, apis []rpc.API, modules []string, cors []string, vhosts []string, timeouts rpc.HTTPTimeouts, wsOrigins []string) error {
// Short circuit if the HTTP endpoint isn't being exposed // Short circuit if the HTTP endpoint isn't being exposed
if endpoint == "" { if endpoint == "" {
return nil return nil
} }
listener, handler, err := rpc.StartHTTPEndpoint(endpoint, apis, modules, cors, vhosts, timeouts) listener, handler, err := rpc.StartHTTPEndpoint(endpoint, apis, modules, cors, vhosts, timeouts, wsOrigins)
if err != nil { if err != nil {
return err return err
} }
n.log.Info("HTTP endpoint opened", "url", fmt.Sprintf("http://%v/", listener.Addr()), n.log.Info("HTTP endpoint opened", "url", fmt.Sprintf("http://%v/", listener.Addr()),
"cors", strings.Join(cors, ","), "cors", strings.Join(cors, ","),
"vhosts", strings.Join(vhosts, ",")) "vhosts", strings.Join(vhosts, ","))
if n.httpEndpoint == n.wsEndpoint {
n.log.Info("WebSocket endpoint opened", "url", fmt.Sprintf("ws://%v", listener.Addr()))
}
// All listeners booted successfully // All listeners booted successfully
n.httpEndpoint = endpoint n.httpEndpoint = endpoint
n.httpListener = listener n.httpListener = listener

View file

@ -42,7 +42,7 @@ func checkModuleAvailability(modules []string, apis []API) (bad, available []str
} }
// StartHTTPEndpoint starts the HTTP RPC endpoint, configured with cors/vhosts/modules. // StartHTTPEndpoint starts the HTTP RPC endpoint, configured with cors/vhosts/modules.
func StartHTTPEndpoint(endpoint string, apis []API, modules []string, cors []string, vhosts []string, timeouts HTTPTimeouts) (net.Listener, *Server, error) { func StartHTTPEndpoint(endpoint string, apis []API, modules []string, cors []string, vhosts []string, timeouts HTTPTimeouts, wsOrigins []string) (net.Listener, *Server, error) {
if bad, available := checkModuleAvailability(modules, apis); len(bad) > 0 { if bad, available := checkModuleAvailability(modules, apis); len(bad) > 0 {
log.Error("Unavailable modules in HTTP API list", "unavailable", bad, "available", available) log.Error("Unavailable modules in HTTP API list", "unavailable", bad, "available", available)
} }
@ -69,7 +69,9 @@ func StartHTTPEndpoint(endpoint string, apis []API, modules []string, cors []str
if listener, err = net.Listen("tcp", endpoint); err != nil { if listener, err = net.Listen("tcp", endpoint); err != nil {
return nil, nil, err return nil, nil, err
} }
go NewHTTPServer(cors, vhosts, timeouts, handler).Serve(listener)
go NewHTTPServer(cors, vhosts, timeouts, handler, handler.WebsocketHandler(wsOrigins)).Serve(listener)
return listener, handler, err return listener, handler, err
} }

View file

@ -212,11 +212,12 @@ func (t *httpServerConn) SetWriteDeadline(time.Time) error { return nil }
// NewHTTPServer creates a new HTTP RPC server around an API provider. // NewHTTPServer creates a new HTTP RPC server around an API provider.
// //
// Deprecated: Server implements http.Handler // Deprecated: Server implements http.Handler
func NewHTTPServer(cors []string, vhosts []string, timeouts HTTPTimeouts, srv http.Handler) *http.Server { func NewHTTPServer(cors []string, vhosts []string, timeouts HTTPTimeouts, srv http.Handler, ws http.Handler) *http.Server {
// Wrap the CORS-handler within a host-handler // Wrap the CORS-handler within a host-handler
handler := newCorsHandler(srv, cors) handler := newCorsHandler(srv, cors)
handler = newVHostHandler(vhosts, handler) handler = newVHostHandler(vhosts, handler)
handler = newGzipHandler(handler) handler = newGzipHandler(handler)
handler = newWebsocketUpgradeHandler(handler, ws)
// Make sure timeout values are meaningful // Make sure timeout values are meaningful
if timeouts.ReadTimeout < time.Second { if timeouts.ReadTimeout < time.Second {
@ -357,3 +358,19 @@ func newVHostHandler(vhosts []string, next http.Handler) http.Handler {
} }
return &virtualHostHandler{vhostMap, next} return &virtualHostHandler{vhostMap, next}
} }
func newWebsocketUpgradeHandler(h http.Handler, ws http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if isWebsocket(r) {
ws.ServeHTTP(w, r)
return
}
h.ServeHTTP(w, r)
})
}
func isWebsocket(r *http.Request) bool {
return strings.ToLower(r.Header.Get("Upgrade")) == "websocket" &&
strings.ToLower(r.Header.Get("Connection")) == "upgrade"
}

View file

@ -62,6 +62,7 @@ func (s *Server) WebsocketHandler(allowedOrigins []string) http.Handler {
log.Debug("WebSocket upgrade failed", "err", err) log.Debug("WebSocket upgrade failed", "err", err)
return return
} }
codec := newWebsocketCodec(conn) codec := newWebsocketCodec(conn)
s.ServeCodec(codec, 0) s.ServeCodec(codec, 0)
}) })