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 type serverCodec struct {
16 dec *json.Decoder // for reading JSON values
17 enc *json.Encoder // for writing JSON values
20 // temporary work space
24 // JSON-RPC clients can use arbitrary json values as request IDs.
25 // Package rpc expects uint64 request IDs.
26 // We assign uint64 sequence numbers to incoming requests
27 // but save the original request ID in the pending map.
28 // When rpc responds, we use the sequence number in
29 // the response to find the original request ID.
30 mutex sync.Mutex // protects seq, pending
32 pending map[uint64]*json.RawMessage
35 // NewServerCodec returns a new rpc.ServerCodec using JSON-RPC on conn.
36 func NewServerCodec(conn io.ReadWriteCloser) rpc.ServerCodec {
38 dec: json.NewDecoder(conn),
39 enc: json.NewEncoder(conn),
41 pending: make(map[uint64]*json.RawMessage),
45 type serverRequest struct {
46 Method string "method"
47 Params *json.RawMessage "params"
48 Id *json.RawMessage "id"
51 func (r *serverRequest) reset() {
54 *r.Params = (*r.Params)[0:0]
61 type serverResponse struct {
62 Id *json.RawMessage "id"
63 Result interface{} "result"
64 Error interface{} "error"
67 func (c *serverCodec) ReadRequestHeader(r *rpc.Request) os.Error {
69 if err := c.dec.Decode(&c.req); err != nil {
72 r.ServiceMethod = c.req.Method
74 // JSON request id can be any JSON value;
75 // RPC package expects uint64. Translate to
76 // internal uint64 and save JSON on the side.
79 c.pending[c.seq] = c.req.Id
87 func (c *serverCodec) ReadRequestBody(x interface{}) os.Error {
88 // JSON params is array value.
89 // RPC params is struct.
90 // Unmarshal into array containing struct for now.
91 // Should think about making RPC more general.
92 var params [1]interface{}
94 return json.Unmarshal(*c.req.Params, ¶ms)
97 var null = json.RawMessage([]byte("null"))
99 func (c *serverCodec) WriteResponse(r *rpc.Response, x interface{}) os.Error {
100 var resp serverResponse
102 b, ok := c.pending[r.Seq]
105 return os.NewError("invalid sequence number in response")
107 c.pending[r.Seq] = nil, false
111 // Invalid request so no id. Use JSON null.
121 return c.enc.Encode(resp)
124 func (c *serverCodec) Close() os.Error {
128 // ServeConn runs the JSON-RPC server on a single connection.
129 // ServeConn blocks, serving the connection until the client hangs up.
130 // The caller typically invokes ServeConn in a go statement.
131 func ServeConn(conn io.ReadWriteCloser) {
132 rpc.ServeCodec(NewServerCodec(conn))