github.com/ethereumproject/go-ethereum@v5.5.2+incompatible/node/node.go (about)

     1  // Copyright 2015 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 node represents the Ethereum protocol stack container.
    18  package node
    19  
    20  import (
    21  	"errors"
    22  	"github.com/spf13/afero"
    23  	"net"
    24  	"path/filepath"
    25  	"reflect"
    26  	"sync"
    27  	"syscall"
    28  
    29  	"github.com/ethereumproject/go-ethereum/event"
    30  	"github.com/ethereumproject/go-ethereum/logger"
    31  	"github.com/ethereumproject/go-ethereum/logger/glog"
    32  	"github.com/ethereumproject/go-ethereum/p2p"
    33  	"github.com/ethereumproject/go-ethereum/rpc"
    34  )
    35  
    36  var (
    37  	ErrDatadirUsed    = errors.New("datadir already used")
    38  	ErrNodeStopped    = errors.New("node not started")
    39  	ErrNodeRunning    = errors.New("node already running")
    40  	ErrServiceUnknown = errors.New("unknown service")
    41  
    42  	datadirInUseErrnos = map[uint]bool{11: true, 32: true, 35: true}
    43  )
    44  
    45  // Node represents a P2P node into which arbitrary (uniquely typed) services might
    46  // be registered.
    47  type Node struct {
    48  	datadir  string         // Path to the currently used data directory
    49  	eventmux *event.TypeMux // Event multiplexer used between the services of a stack
    50  
    51  	serverConfig p2p.Config
    52  	server       *p2p.Server // Currently running P2P networking layer
    53  
    54  	serviceFuncs []ServiceConstructor     // Service constructors (in dependency order)
    55  	services     map[reflect.Type]Service // Currently running services
    56  
    57  	rpcAPIs       []rpc.API   // List of APIs currently provided by the node
    58  	inprocHandler *rpc.Server // In-process RPC request handler to process the API requests
    59  
    60  	ipcEndpoint string       // IPC endpoint to listen at (empty = IPC disabled)
    61  	ipcListener net.Listener // IPC RPC listener socket to serve API requests
    62  	ipcHandler  *rpc.Server  // IPC RPC request handler to process the API requests
    63  
    64  	httpHost      string       // HTTP hostname
    65  	httpPort      int          // HTTP post
    66  	httpEndpoint  string       // HTTP endpoint (interface + port) to listen at (empty = HTTP disabled)
    67  	httpWhitelist []string     // HTTP RPC modules to allow through this endpoint
    68  	httpCors      string       // HTTP RPC Cross-Origin Resource Sharing header
    69  	httpListener  net.Listener // HTTP RPC listener socket to server API requests
    70  	httpHandler   *rpc.Server  // HTTP RPC request handler to process the API requests
    71  
    72  	wsHost      string       // Websocket host
    73  	wsPort      int          // Websocket post
    74  	wsEndpoint  string       // Websocket endpoint (interface + port) to listen at (empty = websocket disabled)
    75  	wsWhitelist []string     // Websocket RPC modules to allow through this endpoint
    76  	wsOrigins   string       // Websocket RPC allowed origin domains
    77  	wsListener  net.Listener // Websocket RPC listener socket to server API requests
    78  	wsHandler   *rpc.Server  // Websocket RPC request handler to process the API requests
    79  
    80  	stop chan struct{} // Channel to wait for termination notifications
    81  	lock sync.RWMutex
    82  }
    83  
    84  // New creates a new P2P node, ready for protocol registration.
    85  func New(conf *Config) (*Node, error) {
    86  	// initialize default, can be overridden by tests
    87  	if conf.fs == nil {
    88  		conf.fs = &fs{afero.NewOsFs()}
    89  	}
    90  	// Ensure the data directory exists, failing if it cannot be created
    91  	if conf.DataDir != "" {
    92  		if err := conf.fs.MkdirAll(conf.DataDir, 0700); err != nil {
    93  			return nil, err
    94  		}
    95  	}
    96  	// Assemble the networking layer and the node itself
    97  	nodeDbPath := ""
    98  	if conf.DataDir != "" {
    99  		nodeDbPath = filepath.Join(conf.DataDir, datadirNodeDatabase)
   100  	}
   101  	return &Node{
   102  		datadir: conf.DataDir,
   103  		serverConfig: p2p.Config{
   104  			PrivateKey:      conf.NodeKey(),
   105  			Name:            conf.Name,
   106  			Discovery:       !conf.NoDiscovery,
   107  			BootstrapNodes:  conf.BootstrapNodes,
   108  			StaticNodes:     conf.StaticNodes(),
   109  			TrustedNodes:    conf.TrusterNodes(),
   110  			NodeDatabase:    nodeDbPath,
   111  			ListenAddr:      conf.ListenAddr,
   112  			NAT:             conf.NAT,
   113  			Dialer:          conf.Dialer,
   114  			NoDial:          conf.NoDial,
   115  			MaxPeers:        conf.MaxPeers,
   116  			MaxPendingPeers: conf.MaxPendingPeers,
   117  		},
   118  		serviceFuncs:  []ServiceConstructor{},
   119  		ipcEndpoint:   conf.IPCEndpoint(),
   120  		httpHost:      conf.HTTPHost,
   121  		httpPort:      conf.HTTPPort,
   122  		httpEndpoint:  conf.HTTPEndpoint(),
   123  		httpWhitelist: conf.HTTPModules,
   124  		httpCors:      conf.HTTPCors,
   125  		wsHost:        conf.WSHost,
   126  		wsPort:        conf.WSPort,
   127  		wsEndpoint:    conf.WSEndpoint(),
   128  		wsWhitelist:   conf.WSModules,
   129  		wsOrigins:     conf.WSOrigins,
   130  		eventmux:      new(event.TypeMux),
   131  	}, nil
   132  }
   133  
   134  // Register injects a new service into the node's stack. The service created by
   135  // the passed constructor must be unique in its type with regard to sibling ones.
   136  func (n *Node) Register(constructor ServiceConstructor) error {
   137  	n.lock.Lock()
   138  	defer n.lock.Unlock()
   139  
   140  	if n.server != nil {
   141  		return ErrNodeRunning
   142  	}
   143  	n.serviceFuncs = append(n.serviceFuncs, constructor)
   144  	return nil
   145  }
   146  
   147  // Start create a live P2P node and starts running it.
   148  func (n *Node) Start() error {
   149  	n.lock.Lock()
   150  	defer n.lock.Unlock()
   151  
   152  	// Short circuit if the node's already running
   153  	if n.server != nil {
   154  		return ErrNodeRunning
   155  	}
   156  	// Otherwise copy and specialize the P2P configuration
   157  	running := &p2p.Server{Config: n.serverConfig}
   158  	services := make(map[reflect.Type]Service)
   159  	for _, constructor := range n.serviceFuncs {
   160  		// Create a new context for the particular service
   161  		ctx := &ServiceContext{
   162  			datadir:  n.datadir,
   163  			services: make(map[reflect.Type]Service),
   164  			EventMux: n.eventmux,
   165  		}
   166  		for kind, s := range services { // copy needed for threaded access
   167  			ctx.services[kind] = s
   168  		}
   169  		// Construct and save the service
   170  		service, err := constructor(ctx)
   171  		if err != nil {
   172  			return err
   173  		}
   174  		kind := reflect.TypeOf(service)
   175  		if _, exists := services[kind]; exists {
   176  			return &DuplicateServiceError{Kind: kind}
   177  		}
   178  		services[kind] = service
   179  	}
   180  	// Gather the protocols and start the freshly assembled P2P server
   181  	for _, service := range services {
   182  		running.Protocols = append(running.Protocols, service.Protocols()...)
   183  	}
   184  	if err := running.Start(); err != nil {
   185  		if errno, ok := err.(syscall.Errno); ok && datadirInUseErrnos[uint(errno)] {
   186  			return ErrDatadirUsed
   187  		}
   188  		return err
   189  	}
   190  	// Start each of the services
   191  	started := []reflect.Type{}
   192  	for kind, service := range services {
   193  		// Start the next service, stopping all previous upon failure
   194  		if err := service.Start(running); err != nil {
   195  			for _, kind := range started {
   196  				services[kind].Stop()
   197  			}
   198  			running.Stop()
   199  
   200  			return err
   201  		}
   202  		// Mark the service started for potential cleanup
   203  		started = append(started, kind)
   204  	}
   205  	// Lastly start the configured RPC interfaces
   206  	if err := n.startRPC(services); err != nil {
   207  		for _, service := range services {
   208  			service.Stop()
   209  		}
   210  		running.Stop()
   211  		return err
   212  	}
   213  	// Finish initializing the startup
   214  	n.services = services
   215  	n.server = running
   216  	n.stop = make(chan struct{})
   217  
   218  	return nil
   219  }
   220  
   221  // startRPC is a helper method to start all the various RPC endpoint during node
   222  // startup. It's not meant to be called at any time afterwards as it makes certain
   223  // assumptions about the state of the node.
   224  func (n *Node) startRPC(services map[reflect.Type]Service) error {
   225  	// Gather all the possible APIs to surface
   226  	apis := n.apis()
   227  	for _, service := range services {
   228  		apis = append(apis, service.APIs()...)
   229  	}
   230  	// Start the various API endpoints, terminating all in case of errors
   231  	if err := n.startInProc(apis); err != nil {
   232  		return err
   233  	}
   234  	if err := n.startIPC(apis); err != nil {
   235  		n.stopInProc()
   236  		return err
   237  	}
   238  	if err := n.startHTTP(n.httpEndpoint, apis, n.httpWhitelist, n.httpCors); err != nil {
   239  		n.stopIPC()
   240  		n.stopInProc()
   241  		return err
   242  	}
   243  	if err := n.startWS(n.wsEndpoint, apis, n.wsWhitelist, n.wsOrigins); err != nil {
   244  		n.stopHTTP()
   245  		n.stopIPC()
   246  		n.stopInProc()
   247  		return err
   248  	}
   249  	// All API endpoints started successfully
   250  	n.rpcAPIs = apis
   251  	return nil
   252  }
   253  
   254  // startInProc initializes an in-process RPC endpoint.
   255  func (n *Node) startInProc(apis []rpc.API) error {
   256  	// Register all the APIs exposed by the services
   257  	handler := rpc.NewServer()
   258  	for _, api := range apis {
   259  		if err := handler.RegisterName(api.Namespace, api.Service); err != nil {
   260  			return err
   261  		}
   262  		glog.V(logger.Debug).Infof("InProc registered %T under '%s'", api.Service, api.Namespace)
   263  	}
   264  	n.inprocHandler = handler
   265  	return nil
   266  }
   267  
   268  // stopInProc terminates the in-process RPC endpoint.
   269  func (n *Node) stopInProc() {
   270  	if n.inprocHandler != nil {
   271  		n.inprocHandler.Stop()
   272  		n.inprocHandler = nil
   273  	}
   274  }
   275  
   276  // startIPC initializes and starts the IPC RPC endpoint.
   277  func (n *Node) startIPC(apis []rpc.API) error {
   278  	// Short circuit if the IPC endpoint isn't being exposed
   279  	if n.ipcEndpoint == "" {
   280  		return nil
   281  	}
   282  	// Register all the APIs exposed by the services
   283  	handler := rpc.NewServer()
   284  	for _, api := range apis {
   285  		if err := handler.RegisterName(api.Namespace, api.Service); err != nil {
   286  			return err
   287  		}
   288  		glog.V(logger.Debug).Infof("IPC registered %T under '%s'", api.Service, api.Namespace)
   289  	}
   290  	// All APIs registered, start the IPC listener
   291  	var (
   292  		listener net.Listener
   293  		err      error
   294  	)
   295  	if listener, err = rpc.CreateIPCListener(n.ipcEndpoint); err != nil {
   296  		return err
   297  	}
   298  	go func() {
   299  		glog.V(logger.Info).Infof("IPC endpoint opened: %s", n.ipcEndpoint)
   300  		glog.D(logger.Warn).Infof("IPC endpoint opened: %s", logger.ColorGreen(n.ipcEndpoint))
   301  
   302  		for {
   303  			conn, err := listener.Accept()
   304  			if err != nil {
   305  				// Terminate if the listener was closed
   306  				n.lock.RLock()
   307  				closed := n.ipcListener == nil
   308  				n.lock.RUnlock()
   309  				if closed {
   310  					return
   311  				}
   312  				// Not closed, just some error; report and continue
   313  				glog.V(logger.Error).Infof("IPC accept failed: %v", err)
   314  				continue
   315  			}
   316  			go handler.ServeCodec(rpc.NewJSONCodec(conn), rpc.OptionMethodInvocation|rpc.OptionSubscriptions)
   317  		}
   318  	}()
   319  	// All listeners booted successfully
   320  	n.ipcListener = listener
   321  	n.ipcHandler = handler
   322  
   323  	return nil
   324  }
   325  
   326  // stopIPC terminates the IPC RPC endpoint.
   327  func (n *Node) stopIPC() {
   328  	if n.ipcListener != nil {
   329  		n.ipcListener.Close()
   330  		n.ipcListener = nil
   331  
   332  		glog.V(logger.Info).Infof("IPC endpoint closed: %s", n.ipcEndpoint)
   333  		glog.D(logger.Warn).Warnf("IPC endpoint closed: %s", n.ipcEndpoint)
   334  	}
   335  	if n.ipcHandler != nil {
   336  		n.ipcHandler.Stop()
   337  		n.ipcHandler = nil
   338  	}
   339  }
   340  
   341  // startHTTP initializes and starts the HTTP RPC endpoint.
   342  func (n *Node) startHTTP(endpoint string, apis []rpc.API, modules []string, cors string) error {
   343  	// Short circuit if the HTTP endpoint isn't being exposed
   344  	if endpoint == "" {
   345  		return nil
   346  	}
   347  	// Generate the whitelist based on the allowed modules
   348  	whitelist := make(map[string]bool)
   349  	for _, module := range modules {
   350  		whitelist[module] = true
   351  	}
   352  	// Register all the APIs exposed by the services
   353  	handler := rpc.NewServer()
   354  	for _, api := range apis {
   355  		if whitelist[api.Namespace] || (len(whitelist) == 0 && api.Public) {
   356  			if err := handler.RegisterName(api.Namespace, api.Service); err != nil {
   357  				return err
   358  			}
   359  			glog.V(logger.Debug).Infof("HTTP registered %T under '%s'", api.Service, api.Namespace)
   360  		}
   361  	}
   362  	// All APIs registered, start the HTTP listener
   363  	var (
   364  		listener net.Listener
   365  		err      error
   366  	)
   367  	if listener, err = net.Listen("tcp", endpoint); err != nil {
   368  		return err
   369  	}
   370  	go rpc.NewHTTPServer(cors, handler).Serve(listener)
   371  	glog.V(logger.Info).Infof("HTTP endpoint opened: http://%s", endpoint)
   372  	glog.D(logger.Warn).Infof("HTTP endpoint: http://%s", logger.ColorGreen(endpoint))
   373  
   374  	// All listeners booted successfully
   375  	n.httpEndpoint = endpoint
   376  	n.httpListener = listener
   377  	n.httpHandler = handler
   378  	n.httpCors = cors
   379  
   380  	return nil
   381  }
   382  
   383  // stopHTTP terminates the HTTP RPC endpoint.
   384  func (n *Node) stopHTTP() {
   385  	if n.httpListener != nil {
   386  		n.httpListener.Close()
   387  		n.httpListener = nil
   388  
   389  		glog.V(logger.Info).Infof("HTTP endpoint closed: http://%s", n.httpEndpoint)
   390  		glog.D(logger.Warn).Warnf("HTTP endpoint closed: http://%s", n.httpEndpoint)
   391  	}
   392  	if n.httpHandler != nil {
   393  		n.httpHandler.Stop()
   394  		n.httpHandler = nil
   395  	}
   396  }
   397  
   398  // startWS initializes and starts the websocket RPC endpoint.
   399  func (n *Node) startWS(endpoint string, apis []rpc.API, modules []string, wsOrigins string) error {
   400  	// Short circuit if the WS endpoint isn't being exposed
   401  	if endpoint == "" {
   402  		return nil
   403  	}
   404  	// Generate the whitelist based on the allowed modules
   405  	whitelist := make(map[string]bool)
   406  	for _, module := range modules {
   407  		whitelist[module] = true
   408  	}
   409  	// Register all the APIs exposed by the services
   410  	handler := rpc.NewServer()
   411  	for _, api := range apis {
   412  		if whitelist[api.Namespace] || (len(whitelist) == 0 && api.Public) {
   413  			if err := handler.RegisterName(api.Namespace, api.Service); err != nil {
   414  				return err
   415  			}
   416  			glog.V(logger.Debug).Infof("WebSocket registered %T under '%s'", api.Service, api.Namespace)
   417  		}
   418  	}
   419  	// All APIs registered, start the HTTP listener
   420  	var (
   421  		listener net.Listener
   422  		err      error
   423  	)
   424  	if listener, err = net.Listen("tcp", endpoint); err != nil {
   425  		return err
   426  	}
   427  	go rpc.NewWSServer(wsOrigins, handler).Serve(listener)
   428  	glog.V(logger.Info).Infof("WebSocket endpoint opened: ws://%s", endpoint)
   429  	glog.D(logger.Warn).Infof("WebSocket endpoint opened: ws://%s", logger.ColorGreen(endpoint))
   430  
   431  	// All listeners booted successfully
   432  	n.wsEndpoint = endpoint
   433  	n.wsListener = listener
   434  	n.wsHandler = handler
   435  	n.wsOrigins = wsOrigins
   436  
   437  	return nil
   438  }
   439  
   440  // stopWS terminates the websocket RPC endpoint.
   441  func (n *Node) stopWS() {
   442  	if n.wsListener != nil {
   443  		n.wsListener.Close()
   444  		n.wsListener = nil
   445  
   446  		glog.V(logger.Info).Infof("WebSocket endpoint closed: ws://%s", n.wsEndpoint)
   447  		glog.V(logger.Warn).Warnf("WebSocket endpoint closed: ws://%s", n.wsEndpoint)
   448  	}
   449  	if n.wsHandler != nil {
   450  		n.wsHandler.Stop()
   451  		n.wsHandler = nil
   452  	}
   453  }
   454  
   455  // Stop terminates a running node along with all it's services. In the node was
   456  // not started, an error is returned.
   457  func (n *Node) Stop() error {
   458  	n.lock.Lock()
   459  	defer n.lock.Unlock()
   460  
   461  	// Short circuit if the node's not running
   462  	if n.server == nil {
   463  		return ErrNodeStopped
   464  	}
   465  	// Otherwise terminate the API, all services and the P2P server too
   466  	n.stopWS()
   467  	n.stopHTTP()
   468  	n.stopIPC()
   469  	n.rpcAPIs = nil
   470  
   471  	failure := &StopError{
   472  		Services: make(map[reflect.Type]error),
   473  	}
   474  	for kind, service := range n.services {
   475  		if err := service.Stop(); err != nil {
   476  			failure.Services[kind] = err
   477  		}
   478  	}
   479  	n.server.Stop()
   480  
   481  	n.services = nil
   482  	n.server = nil
   483  	close(n.stop)
   484  
   485  	if len(failure.Services) > 0 {
   486  		return failure
   487  	}
   488  	return nil
   489  }
   490  
   491  // Wait blocks the thread until the node is stopped. If the node is not running
   492  // at the time of invocation, the method immediately returns.
   493  func (n *Node) Wait() {
   494  	n.lock.RLock()
   495  	if n.server == nil {
   496  		return
   497  	}
   498  	stop := n.stop
   499  	n.lock.RUnlock()
   500  
   501  	<-stop
   502  }
   503  
   504  // Restart terminates a running node and boots up a new one in its place. If the
   505  // node isn't running, an error is returned.
   506  func (n *Node) Restart() error {
   507  	if err := n.Stop(); err != nil {
   508  		return err
   509  	}
   510  	if err := n.Start(); err != nil {
   511  		return err
   512  	}
   513  	return nil
   514  }
   515  
   516  // Attach creates an RPC client attached to an in-process API handler.
   517  func (n *Node) Attach() (rpc.Client, error) {
   518  	n.lock.RLock()
   519  	defer n.lock.RUnlock()
   520  
   521  	// Short circuit if the node's not running
   522  	if n.server == nil {
   523  		return nil, ErrNodeStopped
   524  	}
   525  	// Otherwise attach to the API and return
   526  	return rpc.NewInProcRPCClient(n.inprocHandler), nil
   527  }
   528  
   529  // Server retrieves the currently running P2P network layer. This method is meant
   530  // only to inspect fields of the currently running server, life cycle management
   531  // should be left to this Node entity.
   532  func (n *Node) Server() *p2p.Server {
   533  	n.lock.RLock()
   534  	defer n.lock.RUnlock()
   535  
   536  	return n.server
   537  }
   538  
   539  // Service retrieves a currently running service registered of a specific type.
   540  func (n *Node) Service(service interface{}) error {
   541  	n.lock.RLock()
   542  	defer n.lock.RUnlock()
   543  
   544  	// Short circuit if the node's not running
   545  	if n.server == nil {
   546  		return ErrNodeStopped
   547  	}
   548  	// Otherwise try to find the service to return
   549  	element := reflect.ValueOf(service).Elem()
   550  	if running, ok := n.services[element.Type()]; ok {
   551  		element.Set(reflect.ValueOf(running))
   552  		return nil
   553  	}
   554  	return ErrServiceUnknown
   555  }
   556  
   557  // DataDir retrieves the current datadir used by the protocol stack.
   558  func (n *Node) DataDir() string {
   559  	return n.datadir
   560  }
   561  
   562  // IPCEndpoint retrieves the current IPC endpoint used by the protocol stack.
   563  func (n *Node) IPCEndpoint() string {
   564  	return n.ipcEndpoint
   565  }
   566  
   567  // HTTPEndpoint retrieves the current HTTP endpoint used by the protocol stack.
   568  func (n *Node) HTTPEndpoint() string {
   569  	return n.httpEndpoint
   570  }
   571  
   572  // WSEndpoint retrieves the current WS endpoint used by the protocol stack.
   573  func (n *Node) WSEndpoint() string {
   574  	return n.wsEndpoint
   575  }
   576  
   577  // EventMux retrieves the event multiplexer used by all the network services in
   578  // the current protocol stack.
   579  func (n *Node) EventMux() *event.TypeMux {
   580  	return n.eventmux
   581  }
   582  
   583  // apis returns the collection of RPC descriptors this node offers.
   584  func (n *Node) apis() []rpc.API {
   585  	return []rpc.API{
   586  		{
   587  			Namespace: "admin",
   588  			Version:   "1.0",
   589  			Service:   NewPrivateAdminAPI(n),
   590  		}, {
   591  			Namespace: "admin",
   592  			Version:   "1.0",
   593  			Service:   NewPublicAdminAPI(n),
   594  			Public:    true,
   595  		}, {
   596  			Namespace: "web3",
   597  			Version:   "1.0",
   598  			Service:   NewPublicWeb3API(n),
   599  			Public:    true,
   600  		},
   601  	}
   602  }