...

Source file src/net/rpc/jsonrpc/server.go

Documentation: net/rpc/jsonrpc

		 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.
		 4  
		 5  package jsonrpc
		 6  
		 7  import (
		 8  	"encoding/json"
		 9  	"errors"
		10  	"io"
		11  	"net/rpc"
		12  	"sync"
		13  )
		14  
		15  var errMissingParams = errors.New("jsonrpc: request body missing params")
		16  
		17  type serverCodec struct {
		18  	dec *json.Decoder // for reading JSON values
		19  	enc *json.Encoder // for writing JSON values
		20  	c	 io.Closer
		21  
		22  	// temporary work space
		23  	req serverRequest
		24  
		25  	// JSON-RPC clients can use arbitrary json values as request IDs.
		26  	// Package rpc expects uint64 request IDs.
		27  	// We assign uint64 sequence numbers to incoming requests
		28  	// but save the original request ID in the pending map.
		29  	// When rpc responds, we use the sequence number in
		30  	// the response to find the original request ID.
		31  	mutex	 sync.Mutex // protects seq, pending
		32  	seq		 uint64
		33  	pending map[uint64]*json.RawMessage
		34  }
		35  
		36  // NewServerCodec returns a new rpc.ServerCodec using JSON-RPC on conn.
		37  func NewServerCodec(conn io.ReadWriteCloser) rpc.ServerCodec {
		38  	return &serverCodec{
		39  		dec:		 json.NewDecoder(conn),
		40  		enc:		 json.NewEncoder(conn),
		41  		c:			 conn,
		42  		pending: make(map[uint64]*json.RawMessage),
		43  	}
		44  }
		45  
		46  type serverRequest struct {
		47  	Method string					 `json:"method"`
		48  	Params *json.RawMessage `json:"params"`
		49  	Id		 *json.RawMessage `json:"id"`
		50  }
		51  
		52  func (r *serverRequest) reset() {
		53  	r.Method = ""
		54  	r.Params = nil
		55  	r.Id = nil
		56  }
		57  
		58  type serverResponse struct {
		59  	Id		 *json.RawMessage `json:"id"`
		60  	Result interface{}			`json:"result"`
		61  	Error	interface{}			`json:"error"`
		62  }
		63  
		64  func (c *serverCodec) ReadRequestHeader(r *rpc.Request) error {
		65  	c.req.reset()
		66  	if err := c.dec.Decode(&c.req); err != nil {
		67  		return err
		68  	}
		69  	r.ServiceMethod = c.req.Method
		70  
		71  	// JSON request id can be any JSON value;
		72  	// RPC package expects uint64.	Translate to
		73  	// internal uint64 and save JSON on the side.
		74  	c.mutex.Lock()
		75  	c.seq++
		76  	c.pending[c.seq] = c.req.Id
		77  	c.req.Id = nil
		78  	r.Seq = c.seq
		79  	c.mutex.Unlock()
		80  
		81  	return nil
		82  }
		83  
		84  func (c *serverCodec) ReadRequestBody(x interface{}) error {
		85  	if x == nil {
		86  		return nil
		87  	}
		88  	if c.req.Params == nil {
		89  		return errMissingParams
		90  	}
		91  	// JSON params is array value.
		92  	// RPC params is struct.
		93  	// Unmarshal into array containing struct for now.
		94  	// Should think about making RPC more general.
		95  	var params [1]interface{}
		96  	params[0] = x
		97  	return json.Unmarshal(*c.req.Params, &params)
		98  }
		99  
	 100  var null = json.RawMessage([]byte("null"))
	 101  
	 102  func (c *serverCodec) WriteResponse(r *rpc.Response, x interface{}) error {
	 103  	c.mutex.Lock()
	 104  	b, ok := c.pending[r.Seq]
	 105  	if !ok {
	 106  		c.mutex.Unlock()
	 107  		return errors.New("invalid sequence number in response")
	 108  	}
	 109  	delete(c.pending, r.Seq)
	 110  	c.mutex.Unlock()
	 111  
	 112  	if b == nil {
	 113  		// Invalid request so no id. Use JSON null.
	 114  		b = &null
	 115  	}
	 116  	resp := serverResponse{Id: b}
	 117  	if r.Error == "" {
	 118  		resp.Result = x
	 119  	} else {
	 120  		resp.Error = r.Error
	 121  	}
	 122  	return c.enc.Encode(resp)
	 123  }
	 124  
	 125  func (c *serverCodec) Close() error {
	 126  	return c.c.Close()
	 127  }
	 128  
	 129  // ServeConn runs the JSON-RPC server on a single connection.
	 130  // ServeConn blocks, serving the connection until the client hangs up.
	 131  // The caller typically invokes ServeConn in a go statement.
	 132  func ServeConn(conn io.ReadWriteCloser) {
	 133  	rpc.ServeCodec(NewServerCodec(conn))
	 134  }
	 135  

View as plain text