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 }