github.com/ethereum/go-ethereum@v1.14.4-0.20240516095835-473ee8fc07a3/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" 23 "sync/atomic" 24 25 "github.com/ethereum/go-ethereum/log" 26 ) 27 28 const MetadataApi = "rpc" 29 const EngineApi = "engine" 30 31 // CodecOption specifies which type of messages a codec supports. 32 // 33 // Deprecated: this option is no longer honored by Server. 34 type CodecOption int 35 36 const ( 37 // OptionMethodInvocation is an indication that the codec supports RPC method calls 38 OptionMethodInvocation CodecOption = 1 << iota 39 40 // OptionSubscriptions is an indication that the codec supports RPC notifications 41 OptionSubscriptions = 1 << iota // support pub sub 42 ) 43 44 // Server is an RPC server. 45 type Server struct { 46 services serviceRegistry 47 idgen func() ID 48 49 mutex sync.Mutex 50 codecs map[ServerCodec]struct{} 51 run atomic.Bool 52 batchItemLimit int 53 batchResponseLimit int 54 httpBodyLimit int 55 } 56 57 // NewServer creates a new server instance with no registered handlers. 58 func NewServer() *Server { 59 server := &Server{ 60 idgen: randomIDGenerator(), 61 codecs: make(map[ServerCodec]struct{}), 62 httpBodyLimit: defaultBodyLimit, 63 } 64 server.run.Store(true) 65 // Register the default service providing meta information about the RPC service such 66 // as the services and methods it offers. 67 rpcService := &RPCService{server} 68 server.RegisterName(MetadataApi, rpcService) 69 return server 70 } 71 72 // SetBatchLimits sets limits applied to batch requests. There are two limits: 'itemLimit' 73 // is the maximum number of items in a batch. 'maxResponseSize' is the maximum number of 74 // response bytes across all requests in a batch. 75 // 76 // This method should be called before processing any requests via ServeCodec, ServeHTTP, 77 // ServeListener etc. 78 func (s *Server) SetBatchLimits(itemLimit, maxResponseSize int) { 79 s.batchItemLimit = itemLimit 80 s.batchResponseLimit = maxResponseSize 81 } 82 83 // SetHTTPBodyLimit sets the size limit for HTTP requests. 84 // 85 // This method should be called before processing any requests via ServeHTTP. 86 func (s *Server) SetHTTPBodyLimit(limit int) { 87 s.httpBodyLimit = limit 88 } 89 90 // RegisterName creates a service for the given receiver type under the given name. When no 91 // methods on the given receiver match the criteria to be either an RPC method or a 92 // subscription an error is returned. Otherwise a new service is created and added to the 93 // service collection this server provides to clients. 94 func (s *Server) RegisterName(name string, receiver interface{}) error { 95 return s.services.registerName(name, receiver) 96 } 97 98 // ServeCodec reads incoming requests from codec, calls the appropriate callback and writes 99 // the response back using the given codec. It will block until the codec is closed or the 100 // server is stopped. In either case the codec is closed. 101 // 102 // Note that codec options are no longer supported. 103 func (s *Server) ServeCodec(codec ServerCodec, options CodecOption) { 104 defer codec.close() 105 106 if !s.trackCodec(codec) { 107 return 108 } 109 defer s.untrackCodec(codec) 110 111 cfg := &clientConfig{ 112 idgen: s.idgen, 113 batchItemLimit: s.batchItemLimit, 114 batchResponseLimit: s.batchResponseLimit, 115 } 116 c := initClient(codec, &s.services, cfg) 117 <-codec.closed() 118 c.Close() 119 } 120 121 func (s *Server) trackCodec(codec ServerCodec) bool { 122 s.mutex.Lock() 123 defer s.mutex.Unlock() 124 125 if !s.run.Load() { 126 return false // Don't serve if server is stopped. 127 } 128 s.codecs[codec] = struct{}{} 129 return true 130 } 131 132 func (s *Server) untrackCodec(codec ServerCodec) { 133 s.mutex.Lock() 134 defer s.mutex.Unlock() 135 136 delete(s.codecs, codec) 137 } 138 139 // serveSingleRequest reads and processes a single RPC request from the given codec. This 140 // is used to serve HTTP connections. Subscriptions and reverse calls are not allowed in 141 // this mode. 142 func (s *Server) serveSingleRequest(ctx context.Context, codec ServerCodec) { 143 // Don't serve if server is stopped. 144 if !s.run.Load() { 145 return 146 } 147 148 h := newHandler(ctx, codec, s.idgen, &s.services, s.batchItemLimit, s.batchResponseLimit) 149 h.allowSubscribe = false 150 defer h.close(io.EOF, nil) 151 152 reqs, batch, err := codec.readBatch() 153 if err != nil { 154 if err != io.EOF { 155 resp := errorMessage(&invalidMessageError{"parse error"}) 156 codec.writeJSON(ctx, resp, true) 157 } 158 return 159 } 160 if batch { 161 h.handleBatch(reqs) 162 } else { 163 h.handleMsg(reqs[0]) 164 } 165 } 166 167 // Stop stops reading new requests, waits for stopPendingRequestTimeout to allow pending 168 // requests to finish, then closes all codecs which will cancel pending requests and 169 // subscriptions. 170 func (s *Server) Stop() { 171 s.mutex.Lock() 172 defer s.mutex.Unlock() 173 174 if s.run.CompareAndSwap(true, false) { 175 log.Debug("RPC server shutting down") 176 for codec := range s.codecs { 177 codec.close() 178 } 179 } 180 } 181 182 // RPCService gives meta information about the server. 183 // e.g. gives information about the loaded modules. 184 type RPCService struct { 185 server *Server 186 } 187 188 // Modules returns the list of RPC services with their version number 189 func (s *RPCService) Modules() map[string]string { 190 s.server.services.mu.Lock() 191 defer s.server.services.mu.Unlock() 192 193 modules := make(map[string]string) 194 for name := range s.server.services.services { 195 modules[name] = "1.0" 196 } 197 return modules 198 } 199 200 // PeerInfo contains information about the remote end of the network connection. 201 // 202 // This is available within RPC method handlers through the context. Call 203 // PeerInfoFromContext to get information about the client connection related to 204 // the current method call. 205 type PeerInfo struct { 206 // Transport is name of the protocol used by the client. 207 // This can be "http", "ws" or "ipc". 208 Transport string 209 210 // Address of client. This will usually contain the IP address and port. 211 RemoteAddr string 212 213 // Additional information for HTTP and WebSocket connections. 214 HTTP struct { 215 // Protocol version, i.e. "HTTP/1.1". This is not set for WebSocket. 216 Version string 217 // Header values sent by the client. 218 UserAgent string 219 Origin string 220 Host string 221 } 222 } 223 224 type peerInfoContextKey struct{} 225 226 // PeerInfoFromContext returns information about the client's network connection. 227 // Use this with the context passed to RPC method handler functions. 228 // 229 // The zero value is returned if no connection info is present in ctx. 230 func PeerInfoFromContext(ctx context.Context) PeerInfo { 231 info, _ := ctx.Value(peerInfoContextKey{}).(PeerInfo) 232 return info 233 }