1 // Copyright 2010 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
15 var errMissingParams = errors.New("jsonrpc: request body missing params")
17 type serverCodec struct {
18 dec *json.Decoder // for reading JSON values
19 enc *json.Encoder // for writing JSON values
22 // temporary work space
26 // JSON-RPC clients can use arbitrary json values as request IDs.
27 // Package rpc expects uint64 request IDs.
28 // We assign uint64 sequence numbers to incoming requests
29 // but save the original request ID in the pending map.
30 // When rpc responds, we use the sequence number in
31 // the response to find the original request ID.
32 mutex sync.Mutex // protects seq, pending
34 pending map[uint64]*json.RawMessage
37 // NewServerCodec returns a new rpc.ServerCodec using JSON-RPC on conn.
38 func NewServerCodec(conn io.ReadWriteCloser) rpc.ServerCodec {
40 dec: json.NewDecoder(conn),
41 enc: json.NewEncoder(conn),
43 pending: make(map[uint64]*json.RawMessage),
47 type serverRequest struct {
48 Method string `json:"method"`
49 Params *json.RawMessage `json:"params"`
50 Id *json.RawMessage `json:"id"`
53 func (r *serverRequest) reset() {
59 type serverResponse struct {
60 Id *json.RawMessage `json:"id"`
61 Result interface{} `json:"result"`
62 Error interface{} `json:"error"`
65 func (c *serverCodec) ReadRequestHeader(r *rpc.Request) error {
67 if err := c.dec.Decode(&c.req); err != nil {
70 r.ServiceMethod = c.req.Method
72 // JSON request id can be any JSON value;
73 // RPC package expects uint64. Translate to
74 // internal uint64 and save JSON on the side.
77 c.pending[c.seq] = c.req.Id
85 func (c *serverCodec) ReadRequestBody(x interface{}) error {
89 if c.req.Params == nil {
90 return errMissingParams
92 // JSON params is array value.
93 // RPC params is struct.
94 // Unmarshal into array containing struct for now.
95 // Should think about making RPC more general.
96 var params [1]interface{}
98 return json.Unmarshal(*c.req.Params, ¶ms)
101 var null = json.RawMessage([]byte("null"))
103 func (c *serverCodec) WriteResponse(r *rpc.Response, x interface{}) error {
104 var resp serverResponse
106 b, ok := c.pending[r.Seq]
109 return errors.New("invalid sequence number in response")
111 delete(c.pending, r.Seq)
115 // Invalid request so no id. Use JSON null.
125 return c.enc.Encode(resp)
128 func (c *serverCodec) Close() error {
132 // ServeConn runs the JSON-RPC server on a single connection.
133 // ServeConn blocks, serving the connection until the client hangs up.
134 // The caller typically invokes ServeConn in a go statement.
135 func ServeConn(conn io.ReadWriteCloser) {
136 rpc.ServeCodec(NewServerCodec(conn))