github.com/Debrief-BC/go-debrief@v0.0.0-20200420203408-0c26ca968123/rpc/endpoints.go (about)

     1  // Copyright 2018 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package rpc
    18  
    19  import (
    20  	"net"
    21  
    22  	"github.com/Debrief-BC/go-debrief/log"
    23  )
    24  
    25  // checkModuleAvailability checks that all names given in modules are actually
    26  // available API services. It assumes that the MetadataApi module ("rpc") is always available;
    27  // the registration of this "rpc" module happens in NewServer() and is thus common to all endpoints.
    28  func checkModuleAvailability(modules []string, apis []API) (bad, available []string) {
    29  	availableSet := make(map[string]struct{})
    30  	for _, api := range apis {
    31  		if _, ok := availableSet[api.Namespace]; !ok {
    32  			availableSet[api.Namespace] = struct{}{}
    33  			available = append(available, api.Namespace)
    34  		}
    35  	}
    36  	for _, name := range modules {
    37  		if _, ok := availableSet[name]; !ok && name != MetadataApi {
    38  			bad = append(bad, name)
    39  		}
    40  	}
    41  	return bad, available
    42  }
    43  
    44  // StartHTTPEndpoint starts the HTTP RPC endpoint, configured with cors/vhosts/modules.
    45  func StartHTTPEndpoint(endpoint string, apis []API, modules []string, cors []string, vhosts []string, timeouts HTTPTimeouts) (net.Listener, *Server, error) {
    46  	if bad, available := checkModuleAvailability(modules, apis); len(bad) > 0 {
    47  		log.Error("Unavailable modules in HTTP API list", "unavailable", bad, "available", available)
    48  	}
    49  	// Generate the whitelist based on the allowed modules
    50  	whitelist := make(map[string]bool)
    51  	for _, module := range modules {
    52  		whitelist[module] = true
    53  	}
    54  	// Register all the APIs exposed by the services
    55  	handler := NewServer()
    56  	for _, api := range apis {
    57  		if whitelist[api.Namespace] || (len(whitelist) == 0 && api.Public) {
    58  			if err := handler.RegisterName(api.Namespace, api.Service); err != nil {
    59  				return nil, nil, err
    60  			}
    61  			log.Debug("HTTP registered", "namespace", api.Namespace)
    62  		}
    63  	}
    64  	// All APIs registered, start the HTTP listener
    65  	var (
    66  		listener net.Listener
    67  		err      error
    68  	)
    69  	if listener, err = net.Listen("tcp", endpoint); err != nil {
    70  		return nil, nil, err
    71  	}
    72  	go NewHTTPServer(cors, vhosts, timeouts, handler).Serve(listener)
    73  	return listener, handler, err
    74  }
    75  
    76  // StartWSEndpoint starts a websocket endpoint.
    77  func StartWSEndpoint(endpoint string, apis []API, modules []string, wsOrigins []string, exposeAll bool) (net.Listener, *Server, error) {
    78  	if bad, available := checkModuleAvailability(modules, apis); len(bad) > 0 {
    79  		log.Error("Unavailable modules in WS API list", "unavailable", bad, "available", available)
    80  	}
    81  	// Generate the whitelist based on the allowed modules
    82  	whitelist := make(map[string]bool)
    83  	for _, module := range modules {
    84  		whitelist[module] = true
    85  	}
    86  	// Register all the APIs exposed by the services
    87  	handler := NewServer()
    88  	for _, api := range apis {
    89  		if exposeAll || whitelist[api.Namespace] || (len(whitelist) == 0 && api.Public) {
    90  			if err := handler.RegisterName(api.Namespace, api.Service); err != nil {
    91  				return nil, nil, err
    92  			}
    93  			log.Debug("WebSocket registered", "service", api.Service, "namespace", api.Namespace)
    94  		}
    95  	}
    96  	// All APIs registered, start the HTTP listener
    97  	var (
    98  		listener net.Listener
    99  		err      error
   100  	)
   101  	if listener, err = net.Listen("tcp", endpoint); err != nil {
   102  		return nil, nil, err
   103  	}
   104  	go NewWSServer(wsOrigins, handler).Serve(listener)
   105  	return listener, handler, err
   106  }
   107  
   108  // StartIPCEndpoint starts an IPC endpoint.
   109  func StartIPCEndpoint(ipcEndpoint string, apis []API) (net.Listener, *Server, error) {
   110  	// Register all the APIs exposed by the services.
   111  	handler := NewServer()
   112  	for _, api := range apis {
   113  		if err := handler.RegisterName(api.Namespace, api.Service); err != nil {
   114  			return nil, nil, err
   115  		}
   116  		log.Debug("IPC registered", "namespace", api.Namespace)
   117  	}
   118  	// All APIs registered, start the IPC listener.
   119  	listener, err := ipcListen(ipcEndpoint)
   120  	if err != nil {
   121  		return nil, nil, err
   122  	}
   123  	go handler.ServeListener(listener)
   124  	return listener, handler, nil
   125  }