This commit is contained in:
crusader 2018-03-23 16:43:05 +09:00
parent a3d9c8941a
commit 08688dfb2f
19 changed files with 114 additions and 152 deletions

View File

@ -37,6 +37,7 @@ type client struct {
rwcHandler ClientReadWriteCloseHandler rwcHandler ClientReadWriteCloseHandler
conn interface{} conn interface{}
decoder interface{}
pendingRequestsCount uint32 pendingRequestsCount uint32
pendingRequests map[uint64]*RequestState pendingRequests map[uint64]*RequestState
@ -46,18 +47,21 @@ type client struct {
stopChan chan struct{} stopChan chan struct{}
stopWg sync.WaitGroup stopWg sync.WaitGroup
requestMtx sync.Mutex
responseMtx sync.Mutex
} }
func (c *client) Connect() error { func (c *client) Connect() error {
var err error var err error
if nil == c.ch { if nil == c.ch {
panic("RPC Client: Client handler must be specified.") return fmt.Errorf("RPC Client: Client handler must be specified")
} }
c.ch.Validate() c.ch.Validate()
if nil == c.rwcHandler { if nil == c.rwcHandler {
panic("RPC Client: Client RWC handler must be specified.") return fmt.Errorf("RPC Client: Client RWC handler must be specified")
} }
c.rwcHandler.Validate() c.rwcHandler.Validate()
@ -67,12 +71,18 @@ func (c *client) Connect() error {
c.ctx = c.ch.ClientContext(nil) c.ctx = c.ch.ClientContext(nil)
if err := c.ch.Init(c.ctx); nil != err { if err := c.ch.Init(c.ctx); nil != err {
logging.Logger().Panicf("RPC Client: Initialization of client has been failed %v", err) return fmt.Errorf("RPC Client: Initialization of client has been failed %v", err)
} }
if c.conn, err = c.rwcHandler.Connect(c.ctx); nil != err { if c.conn, err = c.rwcHandler.Connect(c.ctx); nil != err {
return err return err
} }
c.decoder, err = c.rwcHandler.NewDecoder(c.ctx, c.ch.GetCodec(), c.conn)
if nil != err {
return fmt.Errorf("RPC Client: Cannot build rpc decoder")
}
c.stopChan = make(chan struct{}) c.stopChan = make(chan struct{})
c.requestQueueChan = make(chan *RequestState, c.ch.GetPendingRequests()) c.requestQueueChan = make(chan *RequestState, c.ch.GetPendingRequests())
c.pendingRequests = make(map[uint64]*RequestState) c.pendingRequests = make(map[uint64]*RequestState)
@ -303,7 +313,9 @@ func (c *client) rpcWriter(stopChan <-chan struct{}, writerDone chan<- error) {
return return
} }
c.requestMtx.Lock()
err = c.rwcHandler.WriteRequest(c.ctx, c.ch.GetCodec(), c.conn, rs.Method, rs.Args, requestID) err = c.rwcHandler.WriteRequest(c.ctx, c.ch.GetCodec(), c.conn, rs.Method, rs.Args, requestID)
c.requestMtx.Unlock()
if !rs.hasResponse { if !rs.hasResponse {
rs.Error = err rs.Error = err
rs.Done() rs.Done()
@ -337,7 +349,9 @@ func (c *client) rpcReader(readerDone chan<- error) {
err = io.EOF err = io.EOF
return return
} }
resCodec, err := c.rwcHandler.ReadResponse(c.ctx, c.ch.GetCodec(), c.conn) c.responseMtx.Lock()
resCodec, err := c.rwcHandler.ReadResponse(c.ctx, c.ch.GetCodec(), c.decoder)
c.responseMtx.Unlock()
if nil != err { if nil != err {
if err == io.ErrUnexpectedEOF || err == io.EOF { if err == io.ErrUnexpectedEOF || err == io.EOF {
logging.Logger().Infof("Client: disconnected from server") logging.Logger().Infof("Client: disconnected from server")

View File

@ -4,7 +4,8 @@ import "git.loafle.net/commons_go/rpc/protocol"
type ClientReadWriteCloseHandler interface { type ClientReadWriteCloseHandler interface {
Connect(clientCTX ClientContext) (interface{}, error) Connect(clientCTX ClientContext) (interface{}, error)
ReadResponse(clientCTX ClientContext, codec protocol.ClientCodec, conn interface{}) (protocol.ClientResponseCodec, error) NewDecoder(clientCTX ClientContext, codec protocol.ClientCodec, conn interface{}) (interface{}, error)
ReadResponse(clientCTX ClientContext, codec protocol.ClientCodec, decoder interface{}) (protocol.ClientResponseCodec, error)
WriteRequest(clientCTX ClientContext, codec protocol.ClientCodec, conn interface{}, method string, params []interface{}, id interface{}) error WriteRequest(clientCTX ClientContext, codec protocol.ClientCodec, conn interface{}, method string, params []interface{}, id interface{}) error
Disconnect(clientCTX ClientContext, conn interface{}) Disconnect(clientCTX ClientContext, conn interface{})

View File

@ -2,21 +2,22 @@ package client
import ( import (
"fmt" "fmt"
"sync"
"git.loafle.net/commons_go/rpc/protocol" "git.loafle.net/commons_go/rpc/protocol"
) )
type ClientReadWriteCloseHandlers struct { type ClientReadWriteCloseHandlers struct {
ReadMtx sync.Mutex
WriteMtx sync.Mutex
} }
func (crwch *ClientReadWriteCloseHandlers) Connect(clientCTX ClientContext) (interface{}, error) { func (crwch *ClientReadWriteCloseHandlers) Connect(clientCTX ClientContext) (interface{}, error) {
return nil, fmt.Errorf("RPC Client RWC Handler: ClientHandlers method[Connect] is not implement") return nil, fmt.Errorf("RPC Client RWC Handler: ClientHandlers method[Connect] is not implement")
} }
func (crwch *ClientReadWriteCloseHandlers) ReadResponse(clientCTX ClientContext, codec protocol.ClientCodec, conn interface{}) (protocol.ClientResponseCodec, error) { func (crwch *ClientReadWriteCloseHandlers) NewDecoder(clientCTX ClientContext, codec protocol.ClientCodec, conn interface{}) (interface{}, error) {
return nil, fmt.Errorf("RPC Client RWC Handler: NewDecoder is not implemented")
}
func (crwch *ClientReadWriteCloseHandlers) ReadResponse(clientCTX ClientContext, codec protocol.ClientCodec, decoder interface{}) (protocol.ClientResponseCodec, error) {
return nil, fmt.Errorf("RPC Client RWC Handler: ClientHandlers method[ReadResponse] is not implement") return nil, fmt.Errorf("RPC Client RWC Handler: ClientHandlers method[ReadResponse] is not implement")
} }

View File

@ -24,12 +24,14 @@ func (crwch *ClientReadWriteCloseHandlers) Connect(clientCTX client.ClientContex
return csc.NewSocket(crwch.SocketBuilder, clientCTX) return csc.NewSocket(crwch.SocketBuilder, clientCTX)
} }
func (crwch *ClientReadWriteCloseHandlers) ReadResponse(clientCTX client.ClientContext, codec protocol.ClientCodec, conn interface{}) (protocol.ClientResponseCodec, error) { func (crwch *ClientReadWriteCloseHandlers) NewDecoder(clientCTX client.ClientContext, codec protocol.ClientCodec, conn interface{}) (interface{}, error) {
soc := conn.(csc.Socket) soc := conn.(csc.Socket)
crwch.ReadMtx.Lock() return codec.NewDecoder(soc), nil
resCodec, err := codec.NewResponse(soc) }
crwch.ReadMtx.Unlock()
func (crwch *ClientReadWriteCloseHandlers) ReadResponse(clientCTX client.ClientContext, codec protocol.ClientCodec, decoder interface{}) (protocol.ClientResponseCodec, error) {
resCodec, err := codec.NewResponse(decoder)
return resCodec, err return resCodec, err
} }
@ -40,9 +42,7 @@ func (crwch *ClientReadWriteCloseHandlers) WriteRequest(clientCTX client.ClientC
) )
soc := conn.(csc.Socket) soc := conn.(csc.Socket)
crwch.WriteMtx.Lock()
wErr = codec.WriteRequest(soc, method, params, id) wErr = codec.WriteRequest(soc, method, params, id)
crwch.WriteMtx.Unlock()
return wErr return wErr
} }

View File

@ -27,13 +27,18 @@ func (crwch *ClientReadWriteCloseHandlers) Connect(clientCTX client.ClientContex
return cwfc.NewSocket(crwch.SocketBuilder, clientCTX) return cwfc.NewSocket(crwch.SocketBuilder, clientCTX)
} }
func (crwch *ClientReadWriteCloseHandlers) ReadResponse(clientCTX client.ClientContext, codec protocol.ClientCodec, conn interface{}) (protocol.ClientResponseCodec, error) { func (crwch *ClientReadWriteCloseHandlers) NewDecoder(clientCTX client.ClientContext, codec protocol.ClientCodec, conn interface{}) (interface{}, error) {
soc := conn.(cwfc.Socket) soc := conn.(cwfc.Socket)
crwch.ReadMtx.Lock()
_, r, err := soc.NextReader() _, r, err := soc.NextReader()
resCodec, err := codec.NewResponse(r) if nil != err {
crwch.ReadMtx.Unlock() return nil, err
}
return codec.NewDecoder(r), nil
}
func (crwch *ClientReadWriteCloseHandlers) ReadResponse(clientCTX client.ClientContext, codec protocol.ClientCodec, decoder interface{}) (protocol.ClientResponseCodec, error) {
resCodec, err := codec.NewResponse(decoder)
return resCodec, err return resCodec, err
} }
@ -45,10 +50,8 @@ func (crwch *ClientReadWriteCloseHandlers) WriteRequest(clientCTX client.ClientC
) )
soc := conn.(cwfc.Socket) soc := conn.(cwfc.Socket)
crwch.WriteMtx.Lock()
wc, wErr = soc.NextWriter(websocket.TextMessage) wc, wErr = soc.NextWriter(websocket.TextMessage)
if nil != wErr { if nil != wErr {
crwch.WriteMtx.Unlock()
return wErr return wErr
} }
defer func() { defer func() {
@ -57,8 +60,6 @@ func (crwch *ClientReadWriteCloseHandlers) WriteRequest(clientCTX client.ClientC
wErr = codec.WriteRequest(wc, method, params, id) wErr = codec.WriteRequest(wc, method, params, id)
crwch.WriteMtx.Unlock()
return wErr return wErr
} }

View File

@ -1,23 +0,0 @@
package codec
import "io"
// Codec interface contains the encoder for response or decoder for request.
// Eg. gzip, flate compressions.
type Codec interface {
Encode(w io.Writer) io.Writer
Decode(r io.Reader) io.Reader
}
type codec struct {
}
func (_ *codec) Encode(w io.Writer) io.Writer {
return w
}
func (_ *codec) Decode(r io.Reader) io.Reader {
return r
}
var DefaultCodec = &codec{}

View File

@ -1,25 +0,0 @@
package codec
import "io"
// CodecSelector interface provides a way to select encoder using the http
// request. Typically people can use this to check HEADER of the request and
// figure out client capabilities.
// Eg. "Accept-Encoding" tells about supported compressions.
type CodecSelector interface {
SelectByReader(r io.Reader) Codec
SelectByWriter(w io.Writer) Codec
}
type codecSelector struct {
}
func (_ *codecSelector) SelectByReader(_ io.Reader) Codec {
return DefaultCodec
}
func (_ *codecSelector) SelectByWriter(_ io.Writer) Codec {
return DefaultCodec
}
var DefaultCodecSelector = &codecSelector{}

View File

@ -6,8 +6,10 @@ import (
// ClientCodec creates a ClientCodecRequest to process each request. // ClientCodec creates a ClientCodecRequest to process each request.
type ClientCodec interface { type ClientCodec interface {
NewDecoder(r io.Reader) interface{}
WriteRequest(w io.Writer, method string, args []interface{}, id interface{}) error WriteRequest(w io.Writer, method string, args []interface{}, id interface{}) error
NewResponse(rc io.Reader) (ClientResponseCodec, error) NewResponse(decoder interface{}) (ClientResponseCodec, error)
} }
type ClientResponseCodec interface { type ClientResponseCodec interface {

View File

@ -4,7 +4,6 @@ import (
"encoding/json" "encoding/json"
"io" "io"
"git.loafle.net/commons_go/rpc/codec"
"git.loafle.net/commons_go/rpc/protocol" "git.loafle.net/commons_go/rpc/protocol"
) )
@ -12,19 +11,17 @@ import (
// Codec // Codec
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// NewCustomClientCodec returns a new JSON Codec based on passed encoder selector.
func NewCustomClientCodec(codecSel codec.CodecSelector) protocol.ClientCodec {
return &ClientCodec{codecSel: codecSel}
}
// NewClientCodec returns a new JSON Codec. // NewClientCodec returns a new JSON Codec.
func NewClientCodec() protocol.ClientCodec { func NewClientCodec() protocol.ClientCodec {
return NewCustomClientCodec(codec.DefaultCodecSelector) return &ClientCodec{}
} }
// ClientCodec creates a ClientCodecRequest to process each request. // ClientCodec creates a ClientCodecRequest to process each request.
type ClientCodec struct { type ClientCodec struct {
codecSel codec.CodecSelector }
func (cc *ClientCodec) NewDecoder(r io.Reader) interface{} {
return json.NewDecoder(r)
} }
func (cc *ClientCodec) WriteRequest(w io.Writer, method string, args []interface{}, id interface{}) error { func (cc *ClientCodec) WriteRequest(w io.Writer, method string, args []interface{}, id interface{}) error {
@ -40,7 +37,7 @@ func (cc *ClientCodec) WriteRequest(w io.Writer, method string, args []interface
ID: id, ID: id,
} }
encoder := json.NewEncoder(cc.codecSel.SelectByWriter(w).Encode(w)) encoder := json.NewEncoder(w)
if err := encoder.Encode(req); nil != err { if err := encoder.Encode(req); nil != err {
return err return err
} }
@ -49,6 +46,6 @@ func (cc *ClientCodec) WriteRequest(w io.Writer, method string, args []interface
} }
// NewMessage returns a ClientMessageCodec. // NewMessage returns a ClientMessageCodec.
func (cc *ClientCodec) NewResponse(r io.Reader) (protocol.ClientResponseCodec, error) { func (cc *ClientCodec) NewResponse(decoder interface{}) (protocol.ClientResponseCodec, error) {
return newClientResponseCodec(r, cc.codecSel.SelectByReader(r)) return newClientResponseCodec(decoder.(*json.Decoder))
} }

View File

@ -3,7 +3,6 @@ package json
import ( import (
"encoding/json" "encoding/json"
"git.loafle.net/commons_go/rpc/codec"
crp "git.loafle.net/commons_go/rpc/protocol" crp "git.loafle.net/commons_go/rpc/protocol"
cuej "git.loafle.net/commons_go/util/encoding/json" cuej "git.loafle.net/commons_go/util/encoding/json"
) )
@ -23,7 +22,6 @@ type clientNotification struct {
type ClientNotificationCodec struct { type ClientNotificationCodec struct {
noti *clientNotification noti *clientNotification
err error err error
codec codec.Codec
} }
func (cnc *ClientNotificationCodec) HasResponse() bool { func (cnc *ClientNotificationCodec) HasResponse() bool {

View File

@ -5,7 +5,6 @@ import (
"fmt" "fmt"
"io" "io"
"git.loafle.net/commons_go/rpc/codec"
"git.loafle.net/commons_go/rpc/protocol" "git.loafle.net/commons_go/rpc/protocol"
crp "git.loafle.net/commons_go/rpc/protocol" crp "git.loafle.net/commons_go/rpc/protocol"
) )
@ -25,7 +24,6 @@ type clientResponse struct {
type ClientResponseCodec struct { type ClientResponseCodec struct {
res *clientResponse res *clientResponse
err error err error
codec codec.Codec
} }
func (crc *ClientResponseCodec) ID() interface{} { func (crc *ClientResponseCodec) ID() interface{} {
@ -61,15 +59,11 @@ func (crc *ClientResponseCodec) Notification() (protocol.ClientNotificationCodec
return nil, err return nil, err
} }
return &ClientNotificationCodec{noti: noti, err: err, codec: crc.codec}, nil return &ClientNotificationCodec{noti: noti, err: err}, nil
} }
// newClientMessageCodec returns a new ClientMessageCodec. // newClientMessageCodec returns a new ClientMessageCodec.
func newClientResponseCodec(r io.Reader, codec codec.Codec) (protocol.ClientResponseCodec, error) { func newClientResponseCodec(decoder *json.Decoder) (protocol.ClientResponseCodec, error) {
decoder := json.NewDecoder(r)
if nil == r {
return nil, io.EOF
}
decoder.UseNumber() decoder.UseNumber()
res := &clientResponse{} res := &clientResponse{}
@ -92,5 +86,5 @@ func newClientResponseCodec(r io.Reader, codec codec.Codec) (protocol.ClientResp
} }
} }
return &ClientResponseCodec{res: res, err: err, codec: codec}, nil return &ClientResponseCodec{res: res, err: err}, nil
} }

View File

@ -4,7 +4,6 @@ import (
"encoding/json" "encoding/json"
"io" "io"
"git.loafle.net/commons_go/rpc/codec"
"git.loafle.net/commons_go/rpc/protocol" "git.loafle.net/commons_go/rpc/protocol"
) )
@ -14,24 +13,22 @@ var null = json.RawMessage([]byte("null"))
// Codec // 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. // NewServerCodec returns a new JSON Codec.
func NewServerCodec() protocol.ServerCodec { func NewServerCodec() protocol.ServerCodec {
return NewCustomServerCodec(codec.DefaultCodecSelector) return &ServerCodec{}
} }
// ServerCodec creates a ServerRequestCodec to process each request. // ServerCodec creates a ServerRequestCodec to process each request.
type ServerCodec struct { type ServerCodec struct {
codecSel codec.CodecSelector }
func (sc *ServerCodec) NewDecoder(r io.Reader) interface{} {
return json.NewDecoder(r)
} }
// NewRequest returns a ServerRequestCodec. // NewRequest returns a ServerRequestCodec.
func (sc *ServerCodec) NewRequest(r io.Reader) (protocol.ServerRequestCodec, error) { func (sc *ServerCodec) NewRequest(decoder interface{}) (protocol.ServerRequestCodec, error) {
return newServerRequestCodec(r, sc.codecSel.SelectByReader(r)) return newServerRequestCodec(decoder.(*json.Decoder))
} }
// WriteNotification send a notification from server to client. // WriteNotification send a notification from server to client.
@ -44,7 +41,7 @@ func (sc *ServerCodec) WriteNotification(w io.Writer, method string, args []inte
noti := &serverNotification{Method: method, Params: params} noti := &serverNotification{Method: method, Params: params}
res := &serverResponse{Version: Version, Result: noti} res := &serverResponse{Version: Version, Result: noti}
encoder := json.NewEncoder(sc.codecSel.SelectByWriter(w).Encode(w)) encoder := json.NewEncoder(w)
// Not sure in which case will this happen. But seems harmless. // Not sure in which case will this happen. But seems harmless.
if err := encoder.Encode(res); nil != err { if err := encoder.Encode(res); nil != err {
return err return err

View File

@ -4,7 +4,6 @@ import (
"encoding/json" "encoding/json"
"io" "io"
"git.loafle.net/commons_go/rpc/codec"
"git.loafle.net/commons_go/rpc/protocol" "git.loafle.net/commons_go/rpc/protocol"
crp "git.loafle.net/commons_go/rpc/protocol" crp "git.loafle.net/commons_go/rpc/protocol"
cuej "git.loafle.net/commons_go/util/encoding/json" cuej "git.loafle.net/commons_go/util/encoding/json"
@ -36,14 +35,8 @@ type serverRequest struct {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// newRequestCodec returns a new ServerRequestCodec. // newRequestCodec returns a new ServerRequestCodec.
func newServerRequestCodec(r io.Reader, codec codec.Codec) (protocol.ServerRequestCodec, error) { func newServerRequestCodec(decoder *json.Decoder) (protocol.ServerRequestCodec, error) {
// Decode the request body and check if RPC method is valid. // Decode the request body and check if RPC method is valid.
decoder := json.NewDecoder(r)
if nil == r {
return nil, io.EOF
}
decoder.UseNumber()
req := &serverRequest{} req := &serverRequest{}
err := decoder.Decode(req) err := decoder.Decode(req)
if err == io.ErrUnexpectedEOF || err == io.EOF { if err == io.ErrUnexpectedEOF || err == io.EOF {
@ -64,14 +57,13 @@ func newServerRequestCodec(r io.Reader, codec codec.Codec) (protocol.ServerReque
} }
} }
return &ServerRequestCodec{req: req, err: err, codec: codec}, nil return &ServerRequestCodec{req: req, err: err}, nil
} }
// ServerRequestCodec decodes and encodes a single request. // ServerRequestCodec decodes and encodes a single request.
type ServerRequestCodec struct { type ServerRequestCodec struct {
req *serverRequest req *serverRequest
err error err error
codec codec.Codec
} }
func (src *ServerRequestCodec) HasResponse() bool { func (src *ServerRequestCodec) HasResponse() bool {
@ -155,7 +147,7 @@ func (src *ServerRequestCodec) WriteError(w io.Writer, status int, err error) er
func (src *ServerRequestCodec) writeServerResponse(w io.Writer, res *serverResponse) error { func (src *ServerRequestCodec) writeServerResponse(w io.Writer, res *serverResponse) error {
// ID is null for notifications and they don't have a response. // ID is null for notifications and they don't have a response.
if src.req.ID != nil { if src.req.ID != nil {
encoder := json.NewEncoder(src.codec.Encode(w)) encoder := json.NewEncoder(w)
// Not sure in which case will this happen. But seems harmless. // Not sure in which case will this happen. But seems harmless.
if err := encoder.Encode(res); nil != err { if err := encoder.Encode(res); nil != err {
return err return err

View File

@ -6,7 +6,9 @@ import (
// ServerCodec creates a ServerRequestCodec to process each request. // ServerCodec creates a ServerRequestCodec to process each request.
type ServerCodec interface { type ServerCodec interface {
NewRequest(r io.Reader) (ServerRequestCodec, error) NewDecoder(r io.Reader) interface{}
NewRequest(decoder interface{}) (ServerRequestCodec, error)
WriteNotification(w io.Writer, method string, args []interface{}) error WriteNotification(w io.Writer, method string, args []interface{}) error
} }

View File

@ -14,12 +14,14 @@ type ServletReadWriteCloseHandlers struct {
rpc.ServletReadWriteCloseHandlers rpc.ServletReadWriteCloseHandlers
} }
func (srwch *ServletReadWriteCloseHandlers) ReadRequest(servletCTX rpc.ServletContext, codec protocol.ServerCodec, conn interface{}) (protocol.ServerRequestCodec, error) { func (srwch *ServletReadWriteCloseHandlers) NewDecoder(servletCTX rpc.ServletContext, codec protocol.ServerCodec, conn interface{}) (interface{}, error) {
soc := conn.(server.Socket) soc := conn.(server.Socket)
srwch.ReadMtx.Lock() return codec.NewDecoder(soc), nil
reqCodec, err := codec.NewRequest(soc) }
srwch.ReadMtx.Unlock()
func (srwch *ServletReadWriteCloseHandlers) ReadRequest(servletCTX rpc.ServletContext, codec protocol.ServerCodec, decoder interface{}) (protocol.ServerRequestCodec, error) {
reqCodec, err := codec.NewRequest(decoder)
return reqCodec, err return reqCodec, err
} }
@ -30,13 +32,11 @@ func (srwch *ServletReadWriteCloseHandlers) WriteResponse(servletCTX rpc.Servlet
) )
soc := conn.(server.Socket) soc := conn.(server.Socket)
srwch.WriteMtx.Lock()
if nil != err { if nil != err {
wErr = reqCodec.WriteError(soc, 500, err) wErr = reqCodec.WriteError(soc, 500, err)
} else { } else {
wErr = reqCodec.WriteResponse(soc, result) wErr = reqCodec.WriteResponse(soc, result)
} }
srwch.WriteMtx.Unlock()
return wErr return wErr
} }
@ -47,9 +47,7 @@ func (srwch *ServletReadWriteCloseHandlers) WriteNotification(servletCTX rpc.Ser
) )
soc := conn.(server.Socket) soc := conn.(server.Socket)
srwch.WriteMtx.Lock()
wErr = codec.WriteNotification(soc, method, params) wErr = codec.WriteNotification(soc, method, params)
srwch.WriteMtx.Unlock()
return wErr return wErr
} }

View File

@ -17,13 +17,18 @@ type ServletReadWriteCloseHandlers struct {
rpc.ServletReadWriteCloseHandlers rpc.ServletReadWriteCloseHandlers
} }
func (srwch *ServletReadWriteCloseHandlers) ReadRequest(servletCTX rpc.ServletContext, codec protocol.ServerCodec, conn interface{}) (protocol.ServerRequestCodec, error) { func (srwch *ServletReadWriteCloseHandlers) NewDecoder(servletCTX rpc.ServletContext, codec protocol.ServerCodec, conn interface{}) (interface{}, error) {
soc := conn.(cwf.Socket) soc := conn.(cwf.Socket)
srwch.ReadMtx.Lock()
_, r, err := soc.NextReader() _, r, err := soc.NextReader()
requestCodec, err := codec.NewRequest(r) if nil != err {
srwch.ReadMtx.Unlock() return nil, err
}
return codec.NewDecoder(r), nil
}
func (srwch *ServletReadWriteCloseHandlers) ReadRequest(servletCTX rpc.ServletContext, codec protocol.ServerCodec, decoder interface{}) (protocol.ServerRequestCodec, error) {
requestCodec, err := codec.NewRequest(decoder)
return requestCodec, err return requestCodec, err
} }
@ -35,10 +40,8 @@ func (srwch *ServletReadWriteCloseHandlers) WriteResponse(servletCTX rpc.Servlet
) )
soc := conn.(cwf.Socket) soc := conn.(cwf.Socket)
srwch.WriteMtx.Lock()
wc, wErr = soc.NextWriter(websocket.TextMessage) wc, wErr = soc.NextWriter(websocket.TextMessage)
if nil != wErr { if nil != wErr {
srwch.WriteMtx.Unlock()
return wErr return wErr
} }
@ -51,7 +54,6 @@ func (srwch *ServletReadWriteCloseHandlers) WriteResponse(servletCTX rpc.Servlet
} else { } else {
wErr = requestCodec.WriteResponse(wc, result) wErr = requestCodec.WriteResponse(wc, result)
} }
srwch.WriteMtx.Unlock()
return wErr return wErr
} }
@ -63,10 +65,8 @@ func (srwch *ServletReadWriteCloseHandlers) WriteNotification(servletCTX rpc.Ser
) )
soc := conn.(cwf.Socket) soc := conn.(cwf.Socket)
srwch.WriteMtx.Lock()
wc, wErr = soc.NextWriter(websocket.TextMessage) wc, wErr = soc.NextWriter(websocket.TextMessage)
if nil != wErr { if nil != wErr {
srwch.WriteMtx.Unlock()
return wErr return wErr
} }
@ -75,7 +75,6 @@ func (srwch *ServletReadWriteCloseHandlers) WriteNotification(servletCTX rpc.Ser
}() }()
wErr = codec.WriteNotification(wc, method, params) wErr = codec.WriteNotification(wc, method, params)
srwch.WriteMtx.Unlock()
return wErr return wErr
} }

View File

@ -36,11 +36,13 @@ type rpcServlet struct {
conn interface{} conn interface{}
serverCodec protocol.ServerCodec serverCodec protocol.ServerCodec
decoder interface{}
stopChan chan struct{} stopChan chan struct{}
stopWg sync.WaitGroup stopWg sync.WaitGroup
sendMtx sync.RWMutex requestMtx sync.Mutex
responseMTX sync.Mutex
} }
func (s *rpcServlet) Context() ServletContext { func (s *rpcServlet) Context() ServletContext {
@ -70,6 +72,10 @@ func (s *rpcServlet) Start(parentCTX cuc.Context, conn interface{}, doneChan cha
s.conn = conn s.conn = conn
s.serverCodec = sc s.serverCodec = sc
s.decoder, err = s.rwcSH.NewDecoder(s.ctx, sc, conn)
if nil != err {
return fmt.Errorf("RPC Servlet: Cannot build rpc decoder")
}
if err := s.sh.Init(s.ctx); nil != err { if err := s.sh.Init(s.ctx); nil != err {
return fmt.Errorf("RPC Servlet: Initialization of servlet has been failed %v", err) return fmt.Errorf("RPC Servlet: Initialization of servlet has been failed %v", err)
@ -168,7 +174,9 @@ func handleReader(s *rpcServlet, stopChan chan struct{}, doneChan chan error) {
return return
} }
requestCodec, err := s.rwcSH.ReadRequest(s.ctx, s.serverCodec, s.conn) s.requestMtx.Lock()
requestCodec, err := s.rwcSH.ReadRequest(s.ctx, s.serverCodec, s.decoder)
s.requestMtx.Unlock()
if nil != err { if nil != err {
if err == io.ErrUnexpectedEOF || err == io.EOF { if err == io.ErrUnexpectedEOF || err == io.EOF {
err = fmt.Errorf("RPC Server: Disconnected from client") err = fmt.Errorf("RPC Server: Disconnected from client")
@ -221,6 +229,7 @@ func handleWriter(s *rpcServlet, stopChan chan struct{}, doneChan chan error) {
return return
} }
s.responseMTX.Lock()
if nil != rs.requestCodec { if nil != rs.requestCodec {
if err := s.rwcSH.WriteResponse(s.ctx, s.conn, rs.requestCodec, rs.result, rs.err); nil != err { if err := s.rwcSH.WriteResponse(s.ctx, s.conn, rs.requestCodec, rs.result, rs.err); nil != err {
logging.Logger().Errorf("RPC Servlet: response error %v", err) logging.Logger().Errorf("RPC Servlet: response error %v", err)
@ -230,9 +239,9 @@ func handleWriter(s *rpcServlet, stopChan chan struct{}, doneChan chan error) {
logging.Logger().Errorf("RPC Servlet: notification error %v", err) logging.Logger().Errorf("RPC Servlet: notification error %v", err)
} }
} }
s.responseMTX.Unlock()
} }
} }
func handleRequest(s *rpcServlet, requestCodec protocol.ServerRequestCodec) { func handleRequest(s *rpcServlet, requestCodec protocol.ServerRequestCodec) {

View File

@ -3,7 +3,9 @@ package rpc
import "git.loafle.net/commons_go/rpc/protocol" import "git.loafle.net/commons_go/rpc/protocol"
type ServletReadWriteCloseHandler interface { type ServletReadWriteCloseHandler interface {
ReadRequest(servletCTX ServletContext, codec protocol.ServerCodec, conn interface{}) (protocol.ServerRequestCodec, error) NewDecoder(servletCTX ServletContext, codec protocol.ServerCodec, conn interface{}) (interface{}, error)
ReadRequest(servletCTX ServletContext, codec protocol.ServerCodec, decoder interface{}) (protocol.ServerRequestCodec, error)
WriteResponse(servletCTX ServletContext, conn interface{}, requestCodec protocol.ServerRequestCodec, result interface{}, err error) error WriteResponse(servletCTX ServletContext, conn interface{}, requestCodec protocol.ServerRequestCodec, result interface{}, err error) error
WriteNotification(servletCTX ServletContext, conn interface{}, codec protocol.ServerCodec, method string, params []interface{}) error WriteNotification(servletCTX ServletContext, conn interface{}, codec protocol.ServerCodec, method string, params []interface{}) error

View File

@ -2,17 +2,20 @@ package rpc
import ( import (
"fmt" "fmt"
"sync"
"git.loafle.net/commons_go/logging"
"git.loafle.net/commons_go/rpc/protocol" "git.loafle.net/commons_go/rpc/protocol"
) )
type ServletReadWriteCloseHandlers struct { type ServletReadWriteCloseHandlers struct {
ReadMtx sync.Mutex
WriteMtx sync.Mutex
} }
func (srwch *ServletReadWriteCloseHandlers) ReadRequest(servletCTX ServletContext, codec protocol.ServerCodec, conn interface{}) (protocol.ServerRequestCodec, error) { func (srwch *ServletReadWriteCloseHandlers) NewDecoder(servletCTX ServletContext, codec protocol.ServerCodec, conn interface{}) interface{} {
logging.Logger().Errorf("Servlet RWC Handler: NewDecoder is not implemented")
return nil
}
func (srwch *ServletReadWriteCloseHandlers) ReadRequest(servletCTX ServletContext, codec protocol.ServerCodec, decoder interface{}) (protocol.ServerRequestCodec, error) {
return nil, fmt.Errorf("Servlet RWC Handler: ReadRequest is not implemented") return nil, fmt.Errorf("Servlet RWC Handler: ReadRequest is not implemented")
} }