github.com/fff-chain/go-fff@v0.0.0-20220726032732-1c84420b8a99/rpc/server.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 rpc 18 19 import ( 20 "context" 21 "io" 22 "sync/atomic" 23 24 mapset "github.com/deckarep/golang-set" 25 "github.com/fff-chain/go-fff/log" 26 ) 27 28 const MetadataApi = "rpc" 29 30 // CodecOption specifies which type of messages a codec supports. 31 // 32 // Deprecated: this option is no longer honored by Server. 33 type CodecOption int 34 35 const ( 36 // OptionMethodInvocation is an indication that the codec supports RPC method calls 37 OptionMethodInvocation CodecOption = 1 << iota 38 39 // OptionSubscriptions is an indication that the codec supports RPC notifications 40 OptionSubscriptions = 1 << iota // support pub sub 41 ) 42 43 // Server is an RPC server. 44 type Server struct { 45 services serviceRegistry 46 idgen func() ID 47 run int32 48 codecs mapset.Set 49 } 50 51 // NewServer creates a new server instance with no registered handlers. 52 func NewServer() *Server { 53 server := &Server{idgen: randomIDGenerator(), codecs: mapset.NewSet(), run: 1} 54 // Register the default service providing meta information about the RPC service such 55 // as the services and methods it offers. 56 rpcService := &RPCService{server} 57 server.RegisterName(MetadataApi, rpcService) 58 return server 59 } 60 61 // RegisterName creates a service for the given receiver type under the given name. When no 62 // methods on the given receiver match the criteria to be either a RPC method or a 63 // subscription an error is returned. Otherwise a new service is created and added to the 64 // service collection this server provides to clients. 65 func (s *Server) RegisterName(name string, receiver interface{}) error { 66 log.Info("注册服务","服务",name,"re",receiver) 67 return s.services.registerName(name, receiver) 68 } 69 70 // ServeCodec reads incoming requests from codec, calls the appropriate callback and writes 71 // the response back using the given codec. It will block until the codec is closed or the 72 // server is stopped. In either case the codec is closed. 73 // 74 // Note that codec options are no longer supported. 75 func (s *Server) ServeCodec(codec ServerCodec, options CodecOption) { 76 defer codec.close() 77 78 // Don't serve if server is stopped. 79 if atomic.LoadInt32(&s.run) == 0 { 80 return 81 } 82 83 // Add the codec to the set so it can be closed by Stop. 84 s.codecs.Add(codec) 85 defer s.codecs.Remove(codec) 86 87 c := initClient(codec, s.idgen, &s.services) 88 <-codec.closed() 89 c.Close() 90 } 91 92 // serveSingleRequest reads and processes a single RPC request from the given codec. This 93 // is used to serve HTTP connections. Subscriptions and reverse calls are not allowed in 94 // this mode. 95 func (s *Server) serveSingleRequest(ctx context.Context, codec ServerCodec) { 96 // Don't serve if server is stopped. 97 if atomic.LoadInt32(&s.run) == 0 { 98 return 99 } 100 101 h := newHandler(ctx, codec, s.idgen, &s.services) 102 h.allowSubscribe = false 103 defer h.close(io.EOF, nil) 104 105 reqs, batch, err := codec.readBatch() 106 if err != nil { 107 if err != io.EOF { 108 codec.writeJSON(ctx, errorMessage(&invalidMessageError{"parse error"})) 109 } 110 return 111 } 112 if batch { 113 h.handleBatch(ctx, reqs) 114 } else { 115 h.handleMsg(ctx, reqs[0]) 116 } 117 } 118 119 // Stop stops reading new requests, waits for stopPendingRequestTimeout to allow pending 120 // requests to finish, then closes all codecs which will cancel pending requests and 121 // subscriptions. 122 func (s *Server) Stop() { 123 if atomic.CompareAndSwapInt32(&s.run, 1, 0) { 124 log.Debug("RPC server shutting down") 125 s.codecs.Each(func(c interface{}) bool { 126 c.(ServerCodec).close() 127 return true 128 }) 129 } 130 } 131 132 // RPCService gives meta information about the server. 133 // e.g. gives information about the loaded modules. 134 type RPCService struct { 135 server *Server 136 } 137 138 // Modules returns the list of RPC services with their version number 139 func (s *RPCService) Modules() map[string]string { 140 s.server.services.mu.Lock() 141 defer s.server.services.mu.Unlock() 142 143 modules := make(map[string]string) 144 for name := range s.server.services.services { 145 modules[name] = "1.0" 146 } 147 return modules 148 }