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