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  }