Source File
server.go
Belonging Package
net/rpc/jsonrpc
// 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 jsonrpc
import (
)
var errMissingParams = errors.New("jsonrpc: request body missing params")
type serverCodec struct {
dec *json.Decoder // for reading JSON values
enc *json.Encoder // for writing JSON values
c io.Closer
// temporary work space
req serverRequest
// 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, pending
seq uint64
pending map[uint64]*json.RawMessage
}
// NewServerCodec returns a new [rpc.ServerCodec] using JSON-RPC on conn.
func ( io.ReadWriteCloser) rpc.ServerCodec {
return &serverCodec{
dec: json.NewDecoder(),
enc: json.NewEncoder(),
c: ,
pending: make(map[uint64]*json.RawMessage),
}
}
type serverRequest struct {
Method string `json:"method"`
Params *json.RawMessage `json:"params"`
Id *json.RawMessage `json:"id"`
}
func ( *serverRequest) () {
.Method = ""
.Params = nil
.Id = nil
}
type serverResponse struct {
Id *json.RawMessage `json:"id"`
Result any `json:"result"`
Error any `json:"error"`
}
func ( *serverCodec) ( *rpc.Request) error {
.req.reset()
if := .dec.Decode(&.req); != nil {
return
}
.ServiceMethod = .req.Method
// JSON request id can be any JSON value;
// RPC package expects uint64. Translate to
// internal uint64 and save JSON on the side.
.mutex.Lock()
.seq++
.pending[.seq] = .req.Id
.req.Id = nil
.Seq = .seq
.mutex.Unlock()
return nil
}
func ( *serverCodec) ( any) error {
if == nil {
return nil
}
if .req.Params == nil {
return errMissingParams
}
// JSON params is array value.
// RPC params is struct.
// Unmarshal into array containing struct for now.
// Should think about making RPC more general.
var [1]any
[0] =
return json.Unmarshal(*.req.Params, &)
}
var null = json.RawMessage([]byte("null"))
func ( *serverCodec) ( *rpc.Response, any) error {
.mutex.Lock()
, := .pending[.Seq]
if ! {
.mutex.Unlock()
return errors.New("invalid sequence number in response")
}
delete(.pending, .Seq)
.mutex.Unlock()
if == nil {
// Invalid request so no id. Use JSON null.
= &null
}
:= serverResponse{Id: }
if .Error == "" {
.Result =
} else {
.Error = .Error
}
return .enc.Encode()
}
func ( *serverCodec) () error {
return .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 ( io.ReadWriteCloser) {
rpc.ServeCodec(NewServerCodec())
}
The pages are generated with Golds v0.7.0-preview. (GOOS=linux GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds. |