package json import ( "encoding/json" "io" "sync" "git.loafle.net/commons_go/rpc/codec" "git.loafle.net/commons_go/rpc/protocol" ) var null = json.RawMessage([]byte("null")) type serverMessage struct { // JSON-RPC protocol. Version string `json:"jsonrpc"` MessageType protocol.MessageType `json:"messageType"` Message interface{} `json:"message"` } // ---------------------------------------------------------------------------- // Codec // ---------------------------------------------------------------------------- // NewCustomServerCodec returns a new JSON Codec based on passed encoder selector. func NewCustomServerCodec(codecSel codec.CodecSelector) protocol.ServerCodec { return &ServerCodec{codecSel: codecSel} } // NewServerCodec returns a new JSON Codec. func NewServerCodec() protocol.ServerCodec { return NewCustomServerCodec(codec.DefaultCodecSelector) } // ServerCodec creates a ServerRequestCodec to process each request. type ServerCodec struct { codecSel codec.CodecSelector } // NewRequest returns a ServerRequestCodec. func (sc *ServerCodec) NewRequest(r io.Reader) (protocol.ServerRequestCodec, error) { return newServerRequestCodec(r, sc.codecSel.SelectByReader(r)) } // WriteNotification send a notification from server to client. func (sc *ServerCodec) WriteNotification(w io.Writer, method string, args interface{}) error { noti := retainServerNotification(method, args) defer func() { releaseServerNotification(noti) }() msg := retainServerMessage(protocol.MessageTypeNotification, noti) defer func() { releaseServerMessage(msg) }() encoder := json.NewEncoder(sc.codecSel.SelectByWriter(w).Encode(w)) // Not sure in which case will this happen. But seems harmless. if err := encoder.Encode(msg); nil != err { return err } return nil } var serverMessagePool sync.Pool func retainServerMessage(msgType protocol.MessageType, msg interface{}) *serverMessage { var sm *serverMessage v := serverMessagePool.Get() if v == nil { sm = &serverMessage{} } else { sm = v.(*serverMessage) } sm.Version = Version sm.MessageType = msgType sm.Message = msg return sm } func releaseServerMessage(sm *serverMessage) { sm.Version = "" sm.MessageType = protocol.MessageTypeUnknown sm.Message = nil serverMessagePool.Put(sm) }