gitee.com/liuxuezhan/go-micro-v1.18.0@v1.0.0/codec/jsonrpc/client.go (about) 1 package jsonrpc 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "io" 7 "sync" 8 9 "gitee.com/liuxuezhan/go-micro-v1.18.0/codec" 10 ) 11 12 type clientCodec struct { 13 dec *json.Decoder // for reading JSON values 14 enc *json.Encoder // for writing JSON values 15 c io.Closer 16 17 // temporary work space 18 req clientRequest 19 resp clientResponse 20 21 sync.Mutex 22 pending map[interface{}]string 23 } 24 25 type clientRequest struct { 26 Method string `json:"method"` 27 Params [1]interface{} `json:"params"` 28 ID interface{} `json:"id"` 29 } 30 31 type clientResponse struct { 32 ID interface{} `json:"id"` 33 Result *json.RawMessage `json:"result"` 34 Error interface{} `json:"error"` 35 } 36 37 func newClientCodec(conn io.ReadWriteCloser) *clientCodec { 38 return &clientCodec{ 39 dec: json.NewDecoder(conn), 40 enc: json.NewEncoder(conn), 41 c: conn, 42 pending: make(map[interface{}]string), 43 } 44 } 45 46 func (c *clientCodec) Write(m *codec.Message, b interface{}) error { 47 c.Lock() 48 c.pending[m.Id] = m.Method 49 c.Unlock() 50 c.req.Method = m.Method 51 c.req.Params[0] = b 52 c.req.ID = m.Id 53 return c.enc.Encode(&c.req) 54 } 55 56 func (r *clientResponse) reset() { 57 r.ID = 0 58 r.Result = nil 59 r.Error = nil 60 } 61 62 func (c *clientCodec) ReadHeader(m *codec.Message) error { 63 c.resp.reset() 64 if err := c.dec.Decode(&c.resp); err != nil { 65 return err 66 } 67 68 c.Lock() 69 m.Method = c.pending[c.resp.ID] 70 delete(c.pending, c.resp.ID) 71 c.Unlock() 72 73 m.Error = "" 74 m.Id = fmt.Sprintf("%v", c.resp.ID) 75 if c.resp.Error != nil { 76 x, ok := c.resp.Error.(string) 77 if !ok { 78 return fmt.Errorf("invalid error %v", c.resp.Error) 79 } 80 if x == "" { 81 x = "unspecified error" 82 } 83 m.Error = x 84 } 85 return nil 86 } 87 88 func (c *clientCodec) ReadBody(x interface{}) error { 89 if x == nil || c.resp.Result == nil { 90 return nil 91 } 92 return json.Unmarshal(*c.resp.Result, x) 93 } 94 95 func (c *clientCodec) Close() error { 96 return c.c.Close() 97 }