2017-10-31 09:25:44 +00:00
|
|
|
package json
|
|
|
|
|
|
|
|
import (
|
2018-03-23 03:22:16 +00:00
|
|
|
"encoding/json"
|
2017-10-31 09:25:44 +00:00
|
|
|
"fmt"
|
2017-11-28 16:19:03 +00:00
|
|
|
"io"
|
2017-10-31 09:25:44 +00:00
|
|
|
|
2017-11-26 10:15:51 +00:00
|
|
|
"git.loafle.net/commons_go/rpc/codec"
|
2017-10-31 09:25:44 +00:00
|
|
|
"git.loafle.net/commons_go/rpc/protocol"
|
2018-03-20 06:31:54 +00:00
|
|
|
crp "git.loafle.net/commons_go/rpc/protocol"
|
2017-10-31 09:25:44 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
2017-11-26 10:15:51 +00:00
|
|
|
// ClientResponseCodec
|
2017-10-31 09:25:44 +00:00
|
|
|
// ----------------------------------------------------------------------------
|
2017-11-26 10:15:51 +00:00
|
|
|
// clientResponse represents a JSON-RPC response returned to a client.
|
|
|
|
type clientResponse struct {
|
2017-11-28 16:19:03 +00:00
|
|
|
Version string `json:"jsonrpc"`
|
|
|
|
Result *json.RawMessage `json:"result,omitempty"`
|
|
|
|
Error error `json:"error,omitempty"`
|
|
|
|
ID interface{} `json:"id,omitempty"`
|
2017-10-31 09:25:44 +00:00
|
|
|
}
|
|
|
|
|
2017-11-26 10:15:51 +00:00
|
|
|
// ClientResponseCodec decodes and encodes a single request.
|
|
|
|
type ClientResponseCodec struct {
|
2017-11-28 16:19:03 +00:00
|
|
|
res *clientResponse
|
|
|
|
err error
|
|
|
|
codec codec.Codec
|
2017-10-31 09:25:44 +00:00
|
|
|
}
|
|
|
|
|
2017-11-28 16:19:03 +00:00
|
|
|
func (crc *ClientResponseCodec) ID() interface{} {
|
|
|
|
return crc.res.ID
|
2017-10-31 09:25:44 +00:00
|
|
|
}
|
|
|
|
|
2017-11-28 16:19:03 +00:00
|
|
|
func (crc *ClientResponseCodec) Result(result interface{}) error {
|
|
|
|
if nil == crc.err && nil != crc.res.Result {
|
2018-03-23 03:48:20 +00:00
|
|
|
if err := json.Unmarshal(*crc.res.Result, result); nil != err {
|
2017-11-28 16:19:03 +00:00
|
|
|
crc.err = &Error{
|
2018-03-20 06:31:54 +00:00
|
|
|
Code: crp.E_PARSE,
|
2017-11-28 16:19:03 +00:00
|
|
|
Message: err.Error(),
|
|
|
|
Data: crc.res.Result,
|
2017-11-01 09:58:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-10-31 09:25:44 +00:00
|
|
|
|
2017-11-28 16:19:03 +00:00
|
|
|
return crc.err
|
2017-10-31 09:25:44 +00:00
|
|
|
}
|
|
|
|
|
2017-11-28 16:19:03 +00:00
|
|
|
func (crc *ClientResponseCodec) Error() error {
|
|
|
|
return crc.res.Error
|
2017-10-31 09:25:44 +00:00
|
|
|
}
|
|
|
|
|
2017-11-28 16:19:03 +00:00
|
|
|
func (crc *ClientResponseCodec) Notification() (protocol.ClientNotificationCodec, error) {
|
|
|
|
if nil != crc.res.ID || nil == crc.res.Result {
|
|
|
|
return nil, fmt.Errorf("RPC[JSON]: This is not notification")
|
|
|
|
}
|
2017-10-31 09:25:44 +00:00
|
|
|
|
2017-11-28 16:19:03 +00:00
|
|
|
noti := &clientNotification{}
|
2018-03-23 03:48:20 +00:00
|
|
|
err := json.Unmarshal(*crc.res.Result, noti)
|
2017-11-28 16:19:03 +00:00
|
|
|
if nil != err {
|
|
|
|
return nil, err
|
2017-10-31 09:25:44 +00:00
|
|
|
}
|
2017-11-28 16:19:03 +00:00
|
|
|
|
|
|
|
return &ClientNotificationCodec{noti: noti, err: err, codec: crc.codec}, nil
|
2017-10-31 09:25:44 +00:00
|
|
|
}
|
|
|
|
|
2017-11-28 16:19:03 +00:00
|
|
|
// newClientMessageCodec returns a new ClientMessageCodec.
|
|
|
|
func newClientResponseCodec(r io.Reader, codec codec.Codec) (protocol.ClientResponseCodec, error) {
|
2018-03-23 03:48:20 +00:00
|
|
|
decoder := json.NewDecoder(r)
|
2017-11-29 11:17:01 +00:00
|
|
|
if nil == r {
|
|
|
|
return nil, io.EOF
|
|
|
|
}
|
|
|
|
|
2017-11-28 16:19:03 +00:00
|
|
|
res := &clientResponse{}
|
2017-11-29 11:17:01 +00:00
|
|
|
err := decoder.Decode(res)
|
2017-11-28 16:19:03 +00:00
|
|
|
if err != nil {
|
|
|
|
if err == io.ErrUnexpectedEOF || err == io.EOF {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
err = &Error{
|
2018-03-20 06:31:54 +00:00
|
|
|
Code: crp.E_PARSE,
|
2017-11-28 16:19:03 +00:00
|
|
|
Message: err.Error(),
|
|
|
|
Data: res,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if res.Version != Version {
|
|
|
|
err = &Error{
|
2018-03-20 06:31:54 +00:00
|
|
|
Code: crp.E_INVALID_REQ,
|
2017-11-28 16:19:03 +00:00
|
|
|
Message: "jsonrpc must be " + Version,
|
|
|
|
Data: res,
|
|
|
|
}
|
|
|
|
}
|
2017-10-31 09:25:44 +00:00
|
|
|
|
2017-11-28 16:19:03 +00:00
|
|
|
return &ClientResponseCodec{res: res, err: err, codec: codec}, nil
|
2017-10-31 09:25:44 +00:00
|
|
|
}
|