github.com/neatlab/neatio@v1.7.3-0.20220425043230-d903e92fcc75/utilities/utils/server.go (about)

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