URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [net/] [rpc/] [jsonrpc/] [server.go] - Rev 747
Compare with Previous | Blame | View Log
// Copyright 2010 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.package jsonrpcimport ("encoding/json""errors""io""net/rpc""sync")type serverCodec struct {dec *json.Decoder // for reading JSON valuesenc *json.Encoder // for writing JSON valuesc io.Closer// temporary work spacereq serverRequestresp serverResponse// JSON-RPC clients can use arbitrary json values as request IDs.// Package rpc expects uint64 request IDs.// We assign uint64 sequence numbers to incoming requests// but save the original request ID in the pending map.// When rpc responds, we use the sequence number in// the response to find the original request ID.mutex sync.Mutex // protects seq, pendingseq uint64pending map[uint64]*json.RawMessage}// NewServerCodec returns a new rpc.ServerCodec using JSON-RPC on conn.func NewServerCodec(conn io.ReadWriteCloser) rpc.ServerCodec {return &serverCodec{dec: json.NewDecoder(conn),enc: json.NewEncoder(conn),c: conn,pending: make(map[uint64]*json.RawMessage),}}type serverRequest struct {Method string `json:"method"`Params *json.RawMessage `json:"params"`Id *json.RawMessage `json:"id"`}func (r *serverRequest) reset() {r.Method = ""if r.Params != nil {*r.Params = (*r.Params)[0:0]}if r.Id != nil {*r.Id = (*r.Id)[0:0]}}type serverResponse struct {Id *json.RawMessage `json:"id"`Result interface{} `json:"result"`Error interface{} `json:"error"`}func (c *serverCodec) ReadRequestHeader(r *rpc.Request) error {c.req.reset()if err := c.dec.Decode(&c.req); err != nil {return err}r.ServiceMethod = c.req.Method// JSON request id can be any JSON value;// RPC package expects uint64. Translate to// internal uint64 and save JSON on the side.c.mutex.Lock()c.seq++c.pending[c.seq] = c.req.Idc.req.Id = nilr.Seq = c.seqc.mutex.Unlock()return nil}func (c *serverCodec) ReadRequestBody(x interface{}) error {if x == nil {return nil}// JSON params is array value.// RPC params is struct.// Unmarshal into array containing struct for now.// Should think about making RPC more general.var params [1]interface{}params[0] = xreturn json.Unmarshal(*c.req.Params, ¶ms)}var null = json.RawMessage([]byte("null"))func (c *serverCodec) WriteResponse(r *rpc.Response, x interface{}) error {var resp serverResponsec.mutex.Lock()b, ok := c.pending[r.Seq]if !ok {c.mutex.Unlock()return errors.New("invalid sequence number in response")}delete(c.pending, r.Seq)c.mutex.Unlock()if b == nil {// Invalid request so no id. Use JSON null.b = &null}resp.Id = bresp.Result = xif r.Error == "" {resp.Error = nil} else {resp.Error = r.Error}return c.enc.Encode(resp)}func (c *serverCodec) Close() error {return c.c.Close()}// ServeConn runs the JSON-RPC server on a single connection.// ServeConn blocks, serving the connection until the client hangs up.// The caller typically invokes ServeConn in a go statement.func ServeConn(conn io.ReadWriteCloser) {rpc.ServeCodec(NewServerCodec(conn))}
