github.com/jeffallen/go-ethereum@v1.1.4-0.20150910155051-571d3236c49c/rpc/codec/json.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 codec 18 19 import ( 20 "encoding/json" 21 "fmt" 22 "net" 23 "time" 24 "strings" 25 26 "github.com/ethereum/go-ethereum/rpc/shared" 27 ) 28 29 const ( 30 READ_TIMEOUT = 60 // in seconds 31 MAX_REQUEST_SIZE = 1024 * 1024 32 MAX_RESPONSE_SIZE = 1024 * 1024 33 ) 34 35 // Json serialization support 36 type JsonCodec struct { 37 c net.Conn 38 d *json.Decoder 39 } 40 41 // Create new JSON coder instance 42 func NewJsonCoder(conn net.Conn) ApiCoder { 43 return &JsonCodec{ 44 c: conn, 45 d: json.NewDecoder(conn), 46 } 47 } 48 49 // Read incoming request and parse it to RPC request 50 func (self *JsonCodec) ReadRequest() (requests []*shared.Request, isBatch bool, err error) { 51 deadline := time.Now().Add(READ_TIMEOUT * time.Second) 52 if err := self.c.SetDeadline(deadline); err != nil { 53 return nil, false, err 54 } 55 56 var incoming json.RawMessage 57 err = self.d.Decode(&incoming) 58 if err == nil { 59 isBatch = incoming[0] == '[' 60 if isBatch { 61 requests = make([]*shared.Request, 0) 62 err = json.Unmarshal(incoming, &requests) 63 } else { 64 requests = make([]*shared.Request, 1) 65 var singleRequest shared.Request 66 if err = json.Unmarshal(incoming, &singleRequest); err == nil { 67 requests[0] = &singleRequest 68 } 69 } 70 return 71 } 72 73 self.c.Close() 74 return nil, false, err 75 } 76 77 func (self *JsonCodec) Recv() (interface{}, error) { 78 var msg json.RawMessage 79 err := self.d.Decode(&msg) 80 if err != nil { 81 self.c.Close() 82 return nil, err 83 } 84 85 return msg, err 86 } 87 88 func (self *JsonCodec) ReadResponse() (interface{}, error) { 89 in, err := self.Recv() 90 if err != nil { 91 return nil, err 92 } 93 94 if msg, ok := in.(json.RawMessage); ok { 95 var req *shared.Request 96 if err = json.Unmarshal(msg, &req); err == nil && strings.HasPrefix(req.Method, "agent_") { 97 return req, nil 98 } 99 100 var failure *shared.ErrorResponse 101 if err = json.Unmarshal(msg, &failure); err == nil && failure.Error != nil { 102 return failure, fmt.Errorf(failure.Error.Message) 103 } 104 105 var success *shared.SuccessResponse 106 if err = json.Unmarshal(msg, &success); err == nil { 107 return success, nil 108 } 109 } 110 111 return in, err 112 } 113 114 // Decode data 115 func (self *JsonCodec) Decode(data []byte, msg interface{}) error { 116 return json.Unmarshal(data, msg) 117 } 118 119 // Encode message 120 func (self *JsonCodec) Encode(msg interface{}) ([]byte, error) { 121 return json.Marshal(msg) 122 } 123 124 // Parse JSON data from conn to obj 125 func (self *JsonCodec) WriteResponse(res interface{}) error { 126 data, err := json.Marshal(res) 127 if err != nil { 128 self.c.Close() 129 return err 130 } 131 132 bytesWritten := 0 133 134 for bytesWritten < len(data) { 135 n, err := self.c.Write(data[bytesWritten:]) 136 if err != nil { 137 self.c.Close() 138 return err 139 } 140 bytesWritten += n 141 } 142 143 return nil 144 } 145 146 // Close decoder and encoder 147 func (self *JsonCodec) Close() { 148 self.c.Close() 149 }