aboutsummaryrefslogtreecommitdiffstats
path: root/rpc/codec
diff options
context:
space:
mode:
Diffstat (limited to 'rpc/codec')
-rw-r--r--rpc/codec/codec.go47
-rw-r--r--rpc/codec/json.go75
2 files changed, 122 insertions, 0 deletions
diff --git a/rpc/codec/codec.go b/rpc/codec/codec.go
new file mode 100644
index 000000000..5e8f38438
--- /dev/null
+++ b/rpc/codec/codec.go
@@ -0,0 +1,47 @@
+package codec
+
+import (
+ "net"
+ "strconv"
+
+ "github.com/ethereum/go-ethereum/rpc/shared"
+)
+
+type Codec int
+
+// (de)serialization support for rpc interface
+type ApiCoder interface {
+ // Parse message to request from underlying stream
+ ReadRequest() (*shared.Request, error)
+ // Parse response message from underlying stream
+ ReadResponse() (interface{}, error)
+ // Encode response to encoded form in underlying stream
+ WriteResponse(interface{}) error
+ // Decode single message from data
+ Decode([]byte, interface{}) error
+ // Encode msg to encoded form
+ Encode(msg interface{}) ([]byte, error)
+ // close the underlying stream
+ Close()
+}
+
+// supported codecs
+const (
+ JSON Codec = iota
+ nCodecs
+)
+
+var (
+ // collection with supported coders
+ coders = make([]func(net.Conn) ApiCoder, nCodecs)
+)
+
+// create a new coder instance
+func (c Codec) New(conn net.Conn) ApiCoder {
+ switch c {
+ case JSON:
+ return NewJsonCoder(conn)
+ }
+
+ panic("codec: request for codec #" + strconv.Itoa(int(c)) + " is unavailable")
+}
diff --git a/rpc/codec/json.go b/rpc/codec/json.go
new file mode 100644
index 000000000..31024ee74
--- /dev/null
+++ b/rpc/codec/json.go
@@ -0,0 +1,75 @@
+package codec
+
+import (
+ "encoding/json"
+ "net"
+
+ "github.com/ethereum/go-ethereum/rpc/shared"
+)
+
+const (
+ MAX_RESPONSE_SIZE = 64 * 1024
+)
+
+// Json serialization support
+type JsonCodec struct {
+ c net.Conn
+ d *json.Decoder
+ e *json.Encoder
+}
+
+// Create new JSON coder instance
+func NewJsonCoder(conn net.Conn) ApiCoder {
+ return &JsonCodec{
+ c: conn,
+ d: json.NewDecoder(conn),
+ e: json.NewEncoder(conn),
+ }
+}
+
+// Serialize obj to JSON and write it to conn
+func (self *JsonCodec) ReadRequest() (*shared.Request, error) {
+ req := shared.Request{}
+ err := self.d.Decode(&req)
+ if err == nil {
+ return &req, nil
+ }
+ return nil, err
+}
+
+func (self *JsonCodec) ReadResponse() (interface{}, error) {
+ var err error
+ buf := make([]byte, MAX_RESPONSE_SIZE)
+ n, _ := self.c.Read(buf)
+
+ var failure shared.ErrorResponse
+ if err = json.Unmarshal(buf[:n], &failure); err == nil && failure.Error != nil {
+ return failure, nil
+ }
+
+ var success shared.SuccessResponse
+ if err = json.Unmarshal(buf[:n], &success); err == nil {
+ return success, nil
+ }
+
+ return nil, err
+}
+
+// Encode response to encoded form in underlying stream
+func (self *JsonCodec) Decode(data []byte, msg interface{}) error {
+ return json.Unmarshal(data, msg)
+}
+
+func (self *JsonCodec) Encode(msg interface{}) ([]byte, error) {
+ return json.Marshal(msg)
+}
+
+// Parse JSON data from conn to obj
+func (self *JsonCodec) WriteResponse(res interface{}) error {
+ return self.e.Encode(&res)
+}
+
+// Close decoder and encoder
+func (self *JsonCodec) Close() {
+ self.c.Close()
+}