github.com/klaytn/klaytn@v1.12.1/networks/grpc/gServer.go (about) 1 // Modifications Copyright 2019 The klaytn Authors 2 // Copyright 2015 The go-ethereum Authors 3 // This file is part of the go-ethereum library. 4 // 5 // The go-ethereum library is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Lesser General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // The go-ethereum library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Lesser General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public License 16 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 17 // 18 // This file is derived from rpc/http.go (2018/06/04). 19 // Modified and improved for the klaytn development. 20 21 package grpc 22 23 import ( 24 "bufio" 25 "bytes" 26 "context" 27 "encoding/json" 28 "io" 29 "net" 30 "time" 31 32 "github.com/klaytn/klaytn/common" 33 "github.com/klaytn/klaytn/log" 34 "github.com/klaytn/klaytn/networks/rpc" 35 "google.golang.org/grpc" 36 "google.golang.org/grpc/reflection" 37 ) 38 39 var logger = log.NewModuleLogger(log.NetworksGRPC) 40 41 type Listener struct { 42 Addr string 43 handler *rpc.Server 44 grpcServer *grpc.Server 45 } 46 47 // grpcReadWriteNopCloser wraps an io.Reader and io.Writer with a NOP Close method. 48 type grpcReadWriteNopCloser struct { 49 io.Reader 50 io.Writer 51 } 52 53 func (t *grpcReadWriteNopCloser) SetWriteDeadline(time.Time) error { return nil } 54 55 // Close does nothing and returns always nil. 56 func (t *grpcReadWriteNopCloser) Close() error { 57 return nil 58 } 59 60 // klaytnServer is an implementation of KlaytnNodeServer. 61 type klaytnServer struct { 62 handler *rpc.Server 63 } 64 65 type grpcWriter struct { 66 writer KlaytnNode_SubscribeServer 67 writeErr chan error 68 } 69 70 func (gw *grpcWriter) Write(p []byte) (n int, err error) { 71 resp := &RPCResponse{Payload: p} 72 if err := gw.writer.Send(resp); err != nil { 73 if gw.writeErr != nil { 74 gw.writeErr <- err 75 } 76 return 0, err 77 } 78 return len(p), nil 79 } 80 81 type bufWriter struct { 82 writer io.Writer 83 writeErr chan error 84 writeOk chan []byte 85 } 86 87 func (gw *bufWriter) Write(p []byte) (n int, err error) { 88 if _, err := gw.writer.Write(p); err != nil { 89 gw.writeErr <- err 90 return 0, err 91 } 92 gw.writeOk <- p 93 return len(p), nil 94 } 95 96 // BiCall handles bidirectional communication between client and server. 97 func (kns *klaytnServer) BiCall(stream KlaytnNode_BiCallServer) error { 98 for { 99 request, err := stream.Recv() 100 if err == io.EOF { 101 return nil 102 } 103 if err != nil { 104 logger.Error("error reading the request", "err", err) 105 return err 106 } 107 108 preader := bytes.NewReader(request.Params) 109 110 // Create a custom encode/decode pair to enforce payload size and number encoding 111 encoder := func(v interface{}) error { 112 msg, err := json.Marshal(v) 113 if err != nil { 114 return err 115 } 116 resp := &RPCResponse{Payload: msg} 117 err = stream.Send(resp) 118 if err != nil { 119 return err 120 } 121 return err 122 } 123 decoder := func(v interface{}) error { 124 dec := json.NewDecoder(preader) 125 dec.UseNumber() 126 return dec.Decode(v) 127 } 128 129 ctx := context.Background() 130 131 reader := bufio.NewReaderSize(preader, common.MaxRequestContentLength) 132 kns.handler.ServeSingleRequest(ctx, rpc.NewFuncCodec(&grpcReadWriteNopCloser{reader, &grpcWriter{stream, nil}}, encoder, decoder)) 133 } 134 } 135 136 // only server can send message to client repeatedly 137 func (kns *klaytnServer) Subscribe(request *RPCRequest, stream KlaytnNode_SubscribeServer) error { 138 var ( 139 writeErr = make(chan error, 1) 140 readErr = make(chan error, 1) 141 ) 142 143 preader := bytes.NewReader(request.Params) 144 145 // Create a custom encode/decode pair to enforce payload size and number encoding 146 encoder := func(v interface{}) error { 147 msg, err := json.Marshal(v) 148 if err != nil { 149 return err 150 } 151 resp := &RPCResponse{Payload: msg} 152 err = stream.Send(resp) 153 if err != nil { 154 writeErr <- err 155 return err 156 } 157 return err 158 } 159 decoder := func(v interface{}) error { 160 dec := json.NewDecoder(preader) 161 dec.UseNumber() 162 err := dec.Decode(v) 163 if err != nil { 164 readErr <- err 165 } 166 return err 167 } 168 169 ctx := context.Background() 170 171 reader := bufio.NewReaderSize(preader, common.MaxRequestContentLength) 172 kns.handler.ServeSingleRequest(ctx, rpc.NewFuncCodec(&grpcReadWriteNopCloser{reader, &grpcWriter{stream, writeErr}}, encoder, decoder)) 173 174 var err error 175 loop: 176 for { 177 select { 178 case err = <-writeErr: 179 logger.Warn("fail to write", "err", err) 180 break loop 181 case err = <-readErr: 182 logger.Warn("fail to read", "err", err) 183 break loop 184 } 185 } 186 187 return nil 188 } 189 190 // general RPC call, such as one-to-one communication 191 func (kns *klaytnServer) Call(ctx context.Context, request *RPCRequest) (*RPCResponse, error) { 192 var ( 193 err error 194 writeErr = make(chan error, 1) 195 readErr = make(chan error, 1) 196 writeOk = make(chan []byte, 1) 197 ) 198 199 preader := bytes.NewReader(request.Params) 200 201 var res bytes.Buffer 202 writer := &bufWriter{&res, writeErr, writeOk} 203 204 // Create a custom encode/decode pair to enforce payload size and number encoding 205 encoder := func(v interface{}) error { 206 msg, err := json.Marshal(v) 207 if err != nil { 208 return err 209 } 210 _, err = writer.Write(msg) 211 if err != nil { 212 writeErr <- err 213 return err 214 } 215 return err 216 } 217 decoder := func(v interface{}) error { 218 dec := json.NewDecoder(preader) 219 dec.UseNumber() 220 err := dec.Decode(v) 221 if err != nil { 222 readErr <- err 223 } 224 return err 225 } 226 227 reader := bufio.NewReaderSize(preader, common.MaxRequestContentLength) 228 kns.handler.ServeSingleRequest(ctx, rpc.NewFuncCodec(&grpcReadWriteNopCloser{reader, writer}, encoder, decoder)) 229 loop: 230 for { 231 select { 232 case _ = <-writeOk: 233 break loop 234 case err = <-writeErr: 235 logger.Error("fail to write", "err", err) 236 break loop 237 case err = <-readErr: 238 logger.Error("fail to read", "err", err) 239 break loop 240 } 241 } 242 243 if err == nil { 244 return &RPCResponse{Payload: res.Bytes()}, nil 245 } else { 246 return &RPCResponse{Payload: []byte("")}, err 247 } 248 } 249 250 // SetRPCServer sets the RPC server. 251 func (gs *Listener) SetRPCServer(handler *rpc.Server) { 252 gs.handler = handler 253 } 254 255 func (gs *Listener) Start() { 256 lis, err := net.Listen("tcp", gs.Addr) 257 if err != nil { 258 // TODO-Klaytn-gRPC Need to handle err 259 logger.Error("failed to listen", "err", err) 260 } 261 gs.grpcServer = grpc.NewServer() 262 263 RegisterKlaytnNodeServer(gs.grpcServer, &klaytnServer{handler: gs.handler}) 264 265 // Register reflection service on gRPC server. 266 reflection.Register(gs.grpcServer) 267 if err := gs.grpcServer.Serve(lis); err != nil { 268 // TODO-Klaytn-gRPC Need to handle err 269 logger.Error("failed to serve", "err", err) 270 } 271 } 272 273 func (gs *Listener) Stop() { 274 if gs.grpcServer != nil { 275 gs.grpcServer.Stop() 276 } 277 }