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  }