github.com/intfoundation/intchain@v0.0.0-20220727031208-4316ad31ca73/cmd/utils/server.go (about) 1 package utils 2 3 import ( 4 "fmt" 5 "github.com/intfoundation/intchain/log" 6 "github.com/intfoundation/intchain/node" 7 "github.com/intfoundation/intchain/rpc" 8 "gopkg.in/urfave/cli.v1" 9 "net" 10 "net/http" 11 "strings" 12 ) 13 14 var ( 15 httpListener net.Listener 16 httpMux *http.ServeMux 17 httpHandlerMapping map[string]*rpc.Server 18 19 wsListener net.Listener 20 wsMux *http.ServeMux 21 wsOrigins []string 22 wsHandlerMapping map[string]*rpc.Server 23 ) 24 25 func StartRPC(ctx *cli.Context) error { 26 27 // Use Default Config 28 rpcConfig := node.DefaultConfig 29 30 // Setup the config from context 31 SetHTTP(ctx, &rpcConfig) 32 SetWS(ctx, &rpcConfig) 33 wsOrigins = rpcConfig.WSOrigins 34 35 httperr := startHTTP(rpcConfig.HTTPEndpoint(), rpcConfig.HTTPCors, rpcConfig.HTTPVirtualHosts, rpcConfig.HTTPTimeouts) 36 if httperr != nil { 37 return httperr 38 } 39 40 wserr := startWS(rpcConfig.WSEndpoint()) 41 if wserr != nil { 42 return wserr 43 } 44 45 return nil 46 } 47 48 func StopRPC() { 49 // Stop HTTP Listener 50 if httpListener != nil { 51 httpAddr := httpListener.Addr().String() 52 httpListener.Close() 53 httpListener = nil 54 log.Info("HTTP endpoint closed", "url", fmt.Sprintf("http://%s", httpAddr)) 55 } 56 if httpMux != nil { 57 for _, httpHandler := range httpHandlerMapping { 58 httpHandler.Stop() 59 } 60 } 61 62 // Stop WS Listener 63 if wsListener != nil { 64 wsAddr := wsListener.Addr().String() 65 wsListener.Close() 66 wsListener = nil 67 log.Info("WebSocket endpoint closed", "url", fmt.Sprintf("ws://%s", wsAddr)) 68 } 69 if wsMux != nil { 70 for _, wsHandler := range wsHandlerMapping { 71 wsHandler.Stop() 72 } 73 } 74 } 75 76 func IsHTTPRunning() bool { 77 return httpListener != nil && httpMux != nil 78 } 79 80 func IsWSRunning() bool { 81 return wsListener != nil && wsMux != nil 82 } 83 84 func HookupHTTP(chainId string, httpHandler *rpc.Server) error { 85 if httpMux != nil { 86 log.Infof("Hookup HTTP for (chainId, http Handler): (%v, %v)", chainId, httpHandler) 87 if httpHandler != nil { 88 httpMux.Handle("/", httpHandler) 89 httpHandlerMapping[chainId] = httpHandler 90 } 91 } 92 return nil 93 } 94 95 func HookupWS(chainId string, wsHandler *rpc.Server) error { 96 if wsMux != nil { 97 log.Infof("Hookup WS for (chainId, ws Handler): (%v, %v)", chainId, wsHandler) 98 if wsHandler != nil { 99 wsMux.Handle("/", wsHandler.WebsocketHandler(wsOrigins)) 100 wsHandlerMapping[chainId] = wsHandler 101 } 102 } 103 return nil 104 } 105 106 func startHTTP(endpoint string, cors []string, vhosts []string, timeouts rpc.HTTPTimeouts) error { 107 // Short circuit if the HTTP endpoint isn't being exposed 108 if endpoint == "" { 109 return nil 110 } 111 112 var err error 113 httpListener, httpMux, err = startIntChainHTTPEndpoint(endpoint, cors, vhosts, timeouts) 114 if err != nil { 115 return err 116 } 117 httpHandlerMapping = make(map[string]*rpc.Server) 118 119 log.Info("HTTP endpoint opened", "url", fmt.Sprintf("http://%s", endpoint), "cors", strings.Join(cors, ","), "vhosts", strings.Join(vhosts, ",")) 120 return nil 121 } 122 123 func startIntChainHTTPEndpoint(endpoint string, cors []string, vhosts []string, timeouts rpc.HTTPTimeouts) (net.Listener, *http.ServeMux, error) { 124 var ( 125 listener net.Listener 126 err error 127 ) 128 if listener, err = net.Listen("tcp", endpoint); err != nil { 129 return nil, nil, err 130 } 131 mux := http.NewServeMux() 132 go rpc.NewHTTPServer(cors, vhosts, timeouts, mux).Serve(listener) 133 return listener, mux, err 134 } 135 136 func startWS(endpoint string) error { 137 // Short circuit if the WS endpoint isn't being exposed 138 if endpoint == "" { 139 return nil 140 } 141 142 var err error 143 wsListener, wsMux, err = startIntChainWSEndpoint(endpoint) 144 if err != nil { 145 return err 146 } 147 wsHandlerMapping = make(map[string]*rpc.Server) 148 149 log.Info("WebSocket endpoint opened", "url", fmt.Sprintf("ws://%s", wsListener.Addr())) 150 return nil 151 } 152 153 func startIntChainWSEndpoint(endpoint string) (net.Listener, *http.ServeMux, error) { 154 var ( 155 listener net.Listener 156 err error 157 ) 158 if listener, err = net.Listen("tcp", endpoint); err != nil { 159 return nil, nil, err 160 } 161 mux := http.NewServeMux() 162 wsServer := &http.Server{Handler: mux} 163 go wsServer.Serve(listener) 164 return listener, mux, err 165 }