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