ing
This commit is contained in:
parent
8e6981767b
commit
afd49dd0dc
136
client/client.go
136
client/client.go
|
@ -4,7 +4,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -15,9 +14,10 @@ import (
|
||||||
"git.loafle.net/commons_go/rpc/protocol"
|
"git.loafle.net/commons_go/rpc/protocol"
|
||||||
)
|
)
|
||||||
|
|
||||||
func New(ch ClientHandler) Client {
|
func New(ch ClientHandler, rwcHandler ClientReadWriteCloseHandler) Client {
|
||||||
c := &client{
|
c := &client{
|
||||||
ch: ch,
|
ch: ch,
|
||||||
|
rwcHandler: rwcHandler,
|
||||||
}
|
}
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
@ -32,9 +32,11 @@ type Client interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
type client struct {
|
type client struct {
|
||||||
|
ctx ClientContext
|
||||||
ch ClientHandler
|
ch ClientHandler
|
||||||
|
rwcHandler ClientReadWriteCloseHandler
|
||||||
|
|
||||||
conn net.Conn
|
conn interface{}
|
||||||
|
|
||||||
pendingRequestsCount uint32
|
pendingRequestsCount uint32
|
||||||
pendingRequests map[uint64]*RequestState
|
pendingRequests map[uint64]*RequestState
|
||||||
|
@ -48,13 +50,27 @@ type client struct {
|
||||||
|
|
||||||
func (c *client) Connect() error {
|
func (c *client) Connect() error {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
|
if nil == c.ch {
|
||||||
|
panic("RPC Client: Client handler must be specified.")
|
||||||
|
}
|
||||||
c.ch.Validate()
|
c.ch.Validate()
|
||||||
|
|
||||||
|
if nil == c.rwcHandler {
|
||||||
|
panic("RPC Client: Client RWC handler must be specified.")
|
||||||
|
}
|
||||||
|
c.rwcHandler.Validate()
|
||||||
|
|
||||||
if c.stopChan != nil {
|
if c.stopChan != nil {
|
||||||
panic("RPC Client: the given client is already started. Call Client.Stop() before calling Client.Start() again!")
|
panic("RPC Client: the given client is already started. Call Client.Stop() before calling Client.Start() again!")
|
||||||
}
|
}
|
||||||
|
c.ctx = c.ch.ClientContext(nil)
|
||||||
|
|
||||||
if c.conn, err = c.ch.Connect(); nil != err {
|
if err := c.ch.Init(c.ctx); nil != err {
|
||||||
|
logging.Logger().Panic(fmt.Sprintf("RPC Client: Initialization of client has been failed %v", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.conn, err = c.rwcHandler.Connect(); nil != err {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
c.stopChan = make(chan struct{})
|
c.stopChan = make(chan struct{})
|
||||||
|
@ -68,23 +84,28 @@ func (c *client) Connect() error {
|
||||||
|
|
||||||
func (c *client) Close() {
|
func (c *client) Close() {
|
||||||
if c.stopChan == nil {
|
if c.stopChan == nil {
|
||||||
panic("Client: the client must be started before stopping it")
|
panic("RPC Client: the client must be started before stopping it")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c.ch.Destroy(c.ctx)
|
||||||
|
|
||||||
close(c.stopChan)
|
close(c.stopChan)
|
||||||
c.stopWg.Wait()
|
c.stopWg.Wait()
|
||||||
c.stopChan = nil
|
c.stopChan = nil
|
||||||
|
|
||||||
|
logging.Logger().Info(fmt.Sprintf("RPC Client: stopped"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *client) Send(method string, args ...interface{}) (err error) {
|
func (c *client) Send(method string, args ...interface{}) (err error) {
|
||||||
var cs *RequestState
|
var rs *RequestState
|
||||||
if cs, err = c.send(true, false, nil, method, args...); nil != err {
|
if rs, err = c.send(true, false, nil, method, args...); nil != err {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case <-cs.DoneChan:
|
case <-rs.DoneChan:
|
||||||
err = cs.Error
|
err = rs.Error
|
||||||
releaseCallState(cs)
|
releaseCallState(rs)
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -95,19 +116,19 @@ func (c *client) Call(result interface{}, method string, args ...interface{}) er
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *client) CallTimeout(timeout time.Duration, result interface{}, method string, args ...interface{}) (err error) {
|
func (c *client) CallTimeout(timeout time.Duration, result interface{}, method string, args ...interface{}) (err error) {
|
||||||
var cs *RequestState
|
var rs *RequestState
|
||||||
if cs, err = c.send(true, true, result, method, args...); nil != err {
|
if rs, err = c.send(true, true, result, method, args...); nil != err {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
t := retainTimer(timeout)
|
t := retainTimer(timeout)
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case <-cs.DoneChan:
|
case <-rs.DoneChan:
|
||||||
result, err = cs.Result, cs.Error
|
result, err = rs.Result, rs.Error
|
||||||
releaseCallState(cs)
|
releaseCallState(rs)
|
||||||
case <-t.C:
|
case <-t.C:
|
||||||
cs.Cancel()
|
rs.Cancel()
|
||||||
err = getClientTimeoutError(c, timeout)
|
err = getClientTimeoutError(c, timeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,30 +137,30 @@ func (c *client) CallTimeout(timeout time.Duration, result interface{}, method s
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *client) send(usePool bool, hasResponse bool, result interface{}, method string, args ...interface{}) (cs *RequestState, err error) {
|
func (c *client) send(usePool bool, hasResponse bool, result interface{}, method string, args ...interface{}) (rs *RequestState, err error) {
|
||||||
if !hasResponse {
|
if !hasResponse {
|
||||||
usePool = true
|
usePool = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if usePool {
|
if usePool {
|
||||||
cs = retainRequestState()
|
rs = retainRequestState()
|
||||||
} else {
|
} else {
|
||||||
cs = &RequestState{}
|
rs = &RequestState{}
|
||||||
}
|
}
|
||||||
|
|
||||||
cs.hasResponse = hasResponse
|
rs.hasResponse = hasResponse
|
||||||
cs.Method = method
|
rs.Method = method
|
||||||
cs.Args = args
|
rs.Args = args
|
||||||
cs.DoneChan = make(chan *RequestState, 1)
|
rs.DoneChan = make(chan *RequestState, 1)
|
||||||
|
|
||||||
if hasResponse {
|
if hasResponse {
|
||||||
cs.ID = c.ch.GetRequestID()
|
rs.ID = c.ch.GetRequestID()
|
||||||
cs.Result = result
|
rs.Result = result
|
||||||
}
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case c.requestQueueChan <- cs:
|
case c.requestQueueChan <- rs:
|
||||||
return cs, nil
|
return rs, nil
|
||||||
default:
|
default:
|
||||||
// Try substituting the oldest async request by the new one
|
// Try substituting the oldest async request by the new one
|
||||||
// on requests' queue overflow.
|
// on requests' queue overflow.
|
||||||
|
@ -149,7 +170,7 @@ func (c *client) send(usePool bool, hasResponse bool, result interface{}, method
|
||||||
// Immediately notify the caller not interested
|
// Immediately notify the caller not interested
|
||||||
// in the response on requests' queue overflow, since
|
// in the response on requests' queue overflow, since
|
||||||
// there are no other ways to notify it later.
|
// there are no other ways to notify it later.
|
||||||
releaseCallState(cs)
|
releaseCallState(rs)
|
||||||
return nil, getClientOverflowError(c)
|
return nil, getClientOverflowError(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,12 +187,12 @@ func (c *client) send(usePool bool, hasResponse bool, result interface{}, method
|
||||||
}
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case c.requestQueueChan <- cs:
|
case c.requestQueueChan <- rs:
|
||||||
return cs, nil
|
return rs, nil
|
||||||
default:
|
default:
|
||||||
// Release m even if usePool = true, since m wasn't exposed
|
// Release m even if usePool = true, since m wasn't exposed
|
||||||
// to the caller yet.
|
// to the caller yet.
|
||||||
releaseCallState(cs)
|
releaseCallState(rs)
|
||||||
return nil, getClientOverflowError(c)
|
return nil, getClientOverflowError(c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -201,7 +222,7 @@ func (c *client) handleRPC() {
|
||||||
<-writerDone
|
<-writerDone
|
||||||
}
|
}
|
||||||
|
|
||||||
c.conn.Close()
|
c.rwcHandler.Disconnect(c.conn)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
//c.LogError("%s", err)
|
//c.LogError("%s", err)
|
||||||
|
@ -212,11 +233,11 @@ func (c *client) handleRPC() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, cs := range c.pendingRequests {
|
for _, rs := range c.pendingRequests {
|
||||||
atomic.AddUint32(&c.pendingRequestsCount, ^uint32(0))
|
atomic.AddUint32(&c.pendingRequestsCount, ^uint32(0))
|
||||||
cs.Error = err
|
rs.Error = err
|
||||||
if cs.DoneChan != nil {
|
if rs.DoneChan != nil {
|
||||||
cs.Done()
|
rs.Done()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,10 +250,10 @@ func (c *client) rpcWriter(stopChan <-chan struct{}, writerDone chan<- error) {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
var cs *RequestState
|
var rs *RequestState
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case cs = <-c.requestQueueChan:
|
case rs = <-c.requestQueueChan:
|
||||||
default:
|
default:
|
||||||
// Give the last chance for ready goroutines filling c.requestsChan :)
|
// Give the last chance for ready goroutines filling c.requestsChan :)
|
||||||
runtime.Gosched()
|
runtime.Gosched()
|
||||||
|
@ -240,25 +261,25 @@ func (c *client) rpcWriter(stopChan <-chan struct{}, writerDone chan<- error) {
|
||||||
select {
|
select {
|
||||||
case <-stopChan:
|
case <-stopChan:
|
||||||
return
|
return
|
||||||
case cs = <-c.requestQueueChan:
|
case rs = <-c.requestQueueChan:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if cs.IsCanceled() {
|
if rs.IsCanceled() {
|
||||||
if nil != cs.DoneChan {
|
if nil != rs.DoneChan {
|
||||||
// cs.Error = ErrCanceled
|
// rs.Error = ErrCanceled
|
||||||
// close(m.done)
|
// close(m.done)
|
||||||
cs.Done()
|
rs.Done()
|
||||||
} else {
|
} else {
|
||||||
releaseCallState(cs)
|
releaseCallState(rs)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if cs.hasResponse {
|
if rs.hasResponse {
|
||||||
c.pendingRequestsLock.Lock()
|
c.pendingRequestsLock.Lock()
|
||||||
n := len(c.pendingRequests)
|
n := len(c.pendingRequests)
|
||||||
c.pendingRequests[cs.ID] = cs
|
c.pendingRequests[rs.ID] = rs
|
||||||
c.pendingRequestsLock.Unlock()
|
c.pendingRequestsLock.Unlock()
|
||||||
atomic.AddUint32(&c.pendingRequestsCount, 1)
|
atomic.AddUint32(&c.pendingRequestsCount, 1)
|
||||||
|
|
||||||
|
@ -270,13 +291,14 @@ func (c *client) rpcWriter(stopChan <-chan struct{}, writerDone chan<- error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var requestID interface{}
|
var requestID interface{}
|
||||||
if 0 < cs.ID {
|
if 0 < rs.ID {
|
||||||
requestID = cs.ID
|
requestID = rs.ID
|
||||||
}
|
}
|
||||||
err = c.ch.GetCodec().WriteRequest(c.conn, cs.Method, cs.Args, requestID)
|
|
||||||
if !cs.hasResponse {
|
err = c.rwcHandler.WriteRequest(c.ctx, c.ch.GetCodec(), c.conn, rs.Method, rs.Args, requestID)
|
||||||
cs.Error = err
|
if !rs.hasResponse {
|
||||||
cs.Done()
|
rs.Error = err
|
||||||
|
rs.Done()
|
||||||
}
|
}
|
||||||
if nil != err {
|
if nil != err {
|
||||||
if err == io.ErrUnexpectedEOF || err == io.EOF {
|
if err == io.ErrUnexpectedEOF || err == io.EOF {
|
||||||
|
@ -303,7 +325,7 @@ func (c *client) rpcReader(readerDone chan<- error) {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
resCodec, err := c.ch.GetCodec().NewResponse(c.conn)
|
resCodec, err := c.rwcHandler.ReadResponse(c.ctx, c.ch.GetCodec(), c.conn)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
if err == io.ErrUnexpectedEOF || err == io.EOF {
|
if err == io.ErrUnexpectedEOF || err == io.EOF {
|
||||||
logging.Logger().Info("Client: disconnected from server")
|
logging.Logger().Info("Client: disconnected from server")
|
||||||
|
@ -332,7 +354,7 @@ func (c *client) handleResponse(resCodec protocol.ClientResponseCodec) error {
|
||||||
c.pendingRequestsLock.Lock()
|
c.pendingRequestsLock.Lock()
|
||||||
id := reflect.ValueOf(resCodec.ID()).Convert(uint64Type).Uint()
|
id := reflect.ValueOf(resCodec.ID()).Convert(uint64Type).Uint()
|
||||||
|
|
||||||
cs, ok := c.pendingRequests[id]
|
rs, ok := c.pendingRequests[id]
|
||||||
if ok {
|
if ok {
|
||||||
delete(c.pendingRequests, id)
|
delete(c.pendingRequests, id)
|
||||||
}
|
}
|
||||||
|
@ -344,18 +366,18 @@ func (c *client) handleResponse(resCodec protocol.ClientResponseCodec) error {
|
||||||
|
|
||||||
atomic.AddUint32(&c.pendingRequestsCount, ^uint32(0))
|
atomic.AddUint32(&c.pendingRequestsCount, ^uint32(0))
|
||||||
|
|
||||||
if err := resCodec.Result(cs.Result); nil != err {
|
if err := resCodec.Result(rs.Result); nil != err {
|
||||||
log.Printf("responseHandle:%v", err)
|
log.Printf("responseHandle:%v", err)
|
||||||
}
|
}
|
||||||
if err := resCodec.Error(); nil != err {
|
if err := resCodec.Error(); nil != err {
|
||||||
log.Printf("responseHandle:%v", err)
|
log.Printf("responseHandle:%v", err)
|
||||||
// cs.Error = &ClientError{
|
// rs.Error = &ClientError{
|
||||||
// Server: true,
|
// Server: true,
|
||||||
// err: fmt.Errorf("gorpc.Client: [%s]. Server error: [%s]", c.Addr, wr.Error),
|
// err: fmt.Errorf("gorpc.Client: [%s]. Server error: [%s]", c.Addr, wr.Error),
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
cs.Done()
|
rs.Done()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
20
client/client_context.go
Normal file
20
client/client_context.go
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
package client
|
||||||
|
|
||||||
|
import (
|
||||||
|
cuc "git.loafle.net/commons_go/util/context"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ClientContext interface {
|
||||||
|
cuc.Context
|
||||||
|
}
|
||||||
|
|
||||||
|
type clientContext struct {
|
||||||
|
cuc.Context
|
||||||
|
}
|
||||||
|
|
||||||
|
func newClientContext(parent cuc.Context) ClientContext {
|
||||||
|
cCTX := &clientContext{}
|
||||||
|
cCTX.Context = cuc.NewContext(parent)
|
||||||
|
|
||||||
|
return cCTX
|
||||||
|
}
|
|
@ -1,21 +1,23 @@
|
||||||
package client
|
package client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.loafle.net/commons_go/rpc"
|
"git.loafle.net/commons_go/rpc"
|
||||||
"git.loafle.net/commons_go/rpc/protocol"
|
"git.loafle.net/commons_go/rpc/protocol"
|
||||||
|
cuc "git.loafle.net/commons_go/util/context"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ClientHandler interface {
|
type ClientHandler interface {
|
||||||
Connect() (net.Conn, error)
|
ClientContext(parent cuc.Context) ClientContext
|
||||||
GetCodec() protocol.ClientCodec
|
|
||||||
|
|
||||||
|
Init(clientCTX ClientContext) error
|
||||||
|
Destroy(clientCTX ClientContext)
|
||||||
|
|
||||||
|
GetCodec() protocol.ClientCodec
|
||||||
GetRPCRegistry() rpc.Registry
|
GetRPCRegistry() rpc.Registry
|
||||||
GetRequestTimeout() time.Duration
|
GetRequestTimeout() time.Duration
|
||||||
GetPendingRequests() int
|
GetPendingRequests() int
|
||||||
|
|
||||||
GetRequestID() uint64
|
GetRequestID() uint64
|
||||||
Validate()
|
Validate()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,19 @@
|
||||||
package client
|
package client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"net"
|
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"git.loafle.net/commons_go/logging"
|
||||||
|
|
||||||
"git.loafle.net/commons_go/rpc"
|
"git.loafle.net/commons_go/rpc"
|
||||||
"git.loafle.net/commons_go/rpc/protocol"
|
"git.loafle.net/commons_go/rpc/protocol"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ClientHandlers struct {
|
type ClientHandlers struct {
|
||||||
Codec protocol.ClientCodec
|
Codec protocol.ClientCodec
|
||||||
|
RPCRegistry rpc.Registry
|
||||||
|
|
||||||
// Maximum request time.
|
// Maximum request time.
|
||||||
// Default value is DefaultRequestTimeout.
|
// Default value is DefaultRequestTimeout.
|
||||||
RequestTimeout time.Duration
|
RequestTimeout time.Duration
|
||||||
|
@ -24,14 +26,20 @@ type ClientHandlers struct {
|
||||||
// Default is DefaultPendingMessages.
|
// Default is DefaultPendingMessages.
|
||||||
PendingRequests int
|
PendingRequests int
|
||||||
|
|
||||||
RPCRegistry rpc.Registry
|
|
||||||
|
|
||||||
requestID uint64
|
requestID uint64
|
||||||
requestIDMtx sync.Mutex
|
requestIDMtx sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ch *ClientHandlers) Connect() (net.Conn, error) {
|
func (ch *ClientHandlers) ClientContext(parent cuc.Context) ClientContext {
|
||||||
return nil, errors.New("RPC Client: ClientHandlers method[Connect] is not implement")
|
return newClientContext(parent)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ch *ClientHandlers) Init(clientCTX ClientContext) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ch *ClientHandlers) Destroy(clientCTX ClientContext) {
|
||||||
|
// no op
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ch *ClientHandlers) GetCodec() protocol.ClientCodec {
|
func (ch *ClientHandlers) GetCodec() protocol.ClientCodec {
|
||||||
|
@ -61,6 +69,13 @@ func (ch *ClientHandlers) GetRequestID() uint64 {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ch *ClientHandlers) Validate() {
|
func (ch *ClientHandlers) Validate() {
|
||||||
|
if nil == ch.Codec {
|
||||||
|
logging.Logger().Panic("RPC Client Handler: Codec must be specified")
|
||||||
|
}
|
||||||
|
if nil == ch.RPCRegistry {
|
||||||
|
logging.Logger().Panic("RPC Client Handler: RPCRegistry must be specified")
|
||||||
|
}
|
||||||
|
|
||||||
if ch.RequestTimeout <= 0 {
|
if ch.RequestTimeout <= 0 {
|
||||||
ch.RequestTimeout = DefaultRequestTimeout
|
ch.RequestTimeout = DefaultRequestTimeout
|
||||||
}
|
}
|
||||||
|
|
12
client/client_rwc_handler.go
Normal file
12
client/client_rwc_handler.go
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
package client
|
||||||
|
|
||||||
|
import "git.loafle.net/commons_go/rpc/protocol"
|
||||||
|
|
||||||
|
type ClientReadWriteCloseHandler interface {
|
||||||
|
Connect() (interface{}, error)
|
||||||
|
ReadResponse(clientCTX ClientContext, codec protocol.ClientCodec, conn interface{}) (protocol.ClientResponseCodec, error)
|
||||||
|
WriteRequest(clientCTX ClientContext, codec protocol.ClientCodec, conn interface{}, method string, params interface{}, id interface{}) error
|
||||||
|
Disconnect(conn interface{})
|
||||||
|
|
||||||
|
Validate()
|
||||||
|
}
|
30
client/client_rwc_handlers.go
Normal file
30
client/client_rwc_handlers.go
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
package client
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"git.loafle.net/commons_go/rpc/protocol"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ClientReadWriteCloseHandlers struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (crwch *ClientReadWriteCloseHandlers) Connect() (interface{}, error) {
|
||||||
|
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) {
|
||||||
|
return nil, fmt.Errorf("RPC Client RWC Handler: ClientHandlers method[ReadResponse] is not implement")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (crwch *ClientReadWriteCloseHandlers) WriteRequest(clientCTX ClientContext, codec protocol.ClientCodec, conn interface{}, method string, params interface{}, id interface{}) error {
|
||||||
|
return fmt.Errorf("RPC Client RWC Handler: ClientHandlers method[WriteRequest] is not implement")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (crwch *ClientReadWriteCloseHandlers) Disconnect(conn interface{}) {
|
||||||
|
// no op
|
||||||
|
}
|
||||||
|
|
||||||
|
func (crwch *ClientReadWriteCloseHandlers) Validate() {
|
||||||
|
|
||||||
|
}
|
|
@ -11,7 +11,7 @@ var zeroTime time.Time
|
||||||
type RequestState struct {
|
type RequestState struct {
|
||||||
ID uint64
|
ID uint64
|
||||||
Method string
|
Method string
|
||||||
Args interface{}
|
Args []interface{}
|
||||||
Result interface{}
|
Result interface{}
|
||||||
Error error
|
Error error
|
||||||
DoneChan chan *RequestState
|
DoneChan chan *RequestState
|
||||||
|
|
48
client/rwc/socket/client_handlers.go
Normal file
48
client/rwc/socket/client_handlers.go
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
package socket
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"git.loafle.net/commons_go/logging"
|
||||||
|
"git.loafle.net/commons_go/rpc/client"
|
||||||
|
"git.loafle.net/commons_go/rpc/protocol"
|
||||||
|
"git.loafle.net/commons_go/server"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ClientReadWriteCloseHandlers struct {
|
||||||
|
client.ClientReadWriteCloseHandlers
|
||||||
|
|
||||||
|
Address string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (crwch *ClientReadWriteCloseHandlers) Connect() (interface{}, error) {
|
||||||
|
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) {
|
||||||
|
soc := conn.(server.Socket)
|
||||||
|
resCodec, err := codec.NewResponse(soc)
|
||||||
|
|
||||||
|
return resCodec, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (crwch *ClientReadWriteCloseHandlers) WriteRequest(clientCTX ClientContext, codec protocol.ClientCodec, conn interface{}, method string, params interface{}, id interface{}) error {
|
||||||
|
soc := conn.(server.Socket)
|
||||||
|
|
||||||
|
if wErr := codec.WriteRequest(soc, method, params); nil != wErr {
|
||||||
|
return wErr
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (crwch *ClientReadWriteCloseHandlers) Disconnect(conn interface{}) {
|
||||||
|
soc := conn.(server.Socket)
|
||||||
|
soc.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (crwch *ClientReadWriteCloseHandlers) Validate() {
|
||||||
|
if "" == crwch.Address {
|
||||||
|
logging.Logger().Panic("RPC Client RWC Handler: Address must be specified")
|
||||||
|
}
|
||||||
|
}
|
52
client/rwc/websocket/fasthttp/client_handlers.go
Normal file
52
client/rwc/websocket/fasthttp/client_handlers.go
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
package fasthttp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/gorilla/websocket"
|
||||||
|
|
||||||
|
"git.loafle.net/commons_go/rpc/client"
|
||||||
|
"git.loafle.net/commons_go/rpc/protocol"
|
||||||
|
cwf "git.loafle.net/commons_go/websocket_fasthttp"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ClientReadWriteCloseHandlers struct {
|
||||||
|
client.ClientReadWriteCloseHandlers
|
||||||
|
}
|
||||||
|
|
||||||
|
func (crwch *ClientReadWriteCloseHandlers) Connect() (interface{}, error) {
|
||||||
|
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) {
|
||||||
|
soc := conn.(cwf.Socket)
|
||||||
|
_, r, err := soc.NextReader()
|
||||||
|
|
||||||
|
resCodec, err := codec.NewResponse(r)
|
||||||
|
|
||||||
|
return resCodec, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (crwch *ClientReadWriteCloseHandlers) WriteRequest(clientCTX ClientContext, codec protocol.ClientCodec, conn interface{}, method string, params interface{}, id interface{}) error {
|
||||||
|
soc := conn.(cwf.Socket)
|
||||||
|
|
||||||
|
wc, wErr := soc.NextWriter(websocket.TextMessage)
|
||||||
|
if nil != wErr {
|
||||||
|
return wErr
|
||||||
|
}
|
||||||
|
|
||||||
|
if wErr := codec.WriteRequest(wc, method, params); nil != wErr {
|
||||||
|
return wErr
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (crwch *ClientReadWriteCloseHandlers) Disconnect(conn interface{}) {
|
||||||
|
soc := conn.(cwf.Socket)
|
||||||
|
soc.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (crwch *ClientReadWriteCloseHandlers) Validate() {
|
||||||
|
|
||||||
|
}
|
|
@ -1,44 +0,0 @@
|
||||||
package socket
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
|
|
||||||
"git.loafle.net/commons_go/rpc"
|
|
||||||
"git.loafle.net/commons_go/rpc/protocol"
|
|
||||||
)
|
|
||||||
|
|
||||||
type ServletHandlers struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sh *ServletHandlers) ReadRequest(servletCTX rpc.ServletContext, codec protocol.ServerCodec, conn interface{}) (protocol.ServerRequestCodec, error) {
|
|
||||||
nConn := conn.(net.Conn)
|
|
||||||
requestCodec, err := codec.NewRequest(nConn)
|
|
||||||
|
|
||||||
return requestCodec, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sh *ServletHandlers) WriteResponse(servletCTX rpc.ServletContext, conn interface{}, requestCodec protocol.ServerRequestCodec, result interface{}, err error) error {
|
|
||||||
nConn := conn.(net.Conn)
|
|
||||||
|
|
||||||
if nil != err {
|
|
||||||
if wErr := requestCodec.WriteError(nConn, 500, err); nil != wErr {
|
|
||||||
return wErr
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if wErr := requestCodec.WriteResponse(nConn, result); nil != wErr {
|
|
||||||
return wErr
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sh *ServletHandlers) WriteNotification(servletCTX rpc.ServletContext, conn interface{}, codec protocol.ServerCodec, method string, args []interface{}) error {
|
|
||||||
nConn := conn.(net.Conn)
|
|
||||||
|
|
||||||
if wErr := codec.WriteNotification(nConn, method, args); nil != wErr {
|
|
||||||
return wErr
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
44
server/rwc/socket/servlet_handlers.go
Normal file
44
server/rwc/socket/servlet_handlers.go
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
package socket
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.loafle.net/commons_go/rpc"
|
||||||
|
"git.loafle.net/commons_go/rpc/protocol"
|
||||||
|
"git.loafle.net/commons_go/server"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ServletReadWriteCloseHandler struct {
|
||||||
|
rpc.ServletReadWriteCloseHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
func (srwch *ServletReadWriteCloseHandler) ReadRequest(servletCTX rpc.ServletContext, codec protocol.ServerCodec, conn interface{}) (protocol.ServerRequestCodec, error) {
|
||||||
|
soc := conn.(server.Socket)
|
||||||
|
reqCodec, err := codec.NewRequest(soc)
|
||||||
|
|
||||||
|
return reqCodec, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (srwch *ServletReadWriteCloseHandler) WriteResponse(servletCTX rpc.ServletContext, conn interface{}, reqCodec protocol.ServerRequestCodec, result interface{}, err error) error {
|
||||||
|
soc := conn.(server.Socket)
|
||||||
|
|
||||||
|
if nil != err {
|
||||||
|
if wErr := reqCodec.WriteError(soc, 500, err); nil != wErr {
|
||||||
|
return wErr
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if wErr := reqCodec.WriteResponse(soc, result); nil != wErr {
|
||||||
|
return wErr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (srwch *ServletReadWriteCloseHandler) WriteNotification(servletCTX rpc.ServletContext, conn interface{}, codec protocol.ServerCodec, method string, params interface{}) error {
|
||||||
|
soc := conn.(server.Socket)
|
||||||
|
|
||||||
|
if wErr := codec.WriteNotification(soc, method, params); nil != wErr {
|
||||||
|
return wErr
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -7,10 +7,11 @@ import (
|
||||||
"git.loafle.net/commons_go/websocket_fasthttp/websocket"
|
"git.loafle.net/commons_go/websocket_fasthttp/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ServletHandlers struct {
|
type ServletReadWriteCloseHandler struct {
|
||||||
|
rpc.ServletReadWriteCloseHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sh *ServletHandlers) ReadRequest(servletCTX rpc.ServletContext, codec protocol.ServerCodec, conn interface{}) (protocol.ServerRequestCodec, error) {
|
func (srwch *ServletReadWriteCloseHandler) ReadRequest(servletCTX rpc.ServletContext, codec protocol.ServerCodec, conn interface{}) (protocol.ServerRequestCodec, error) {
|
||||||
soc := conn.(cwf.Socket)
|
soc := conn.(cwf.Socket)
|
||||||
_, r, err := soc.NextReader()
|
_, r, err := soc.NextReader()
|
||||||
|
|
||||||
|
@ -19,7 +20,7 @@ func (sh *ServletHandlers) ReadRequest(servletCTX rpc.ServletContext, codec prot
|
||||||
return requestCodec, err
|
return requestCodec, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sh *ServletHandlers) WriteResponse(servletCTX rpc.ServletContext, conn interface{}, requestCodec protocol.ServerRequestCodec, result interface{}, err error) error {
|
func (srwch *ServletReadWriteCloseHandler) WriteResponse(servletCTX rpc.ServletContext, conn interface{}, requestCodec protocol.ServerRequestCodec, result interface{}, err error) error {
|
||||||
soc := conn.(cwf.Socket)
|
soc := conn.(cwf.Socket)
|
||||||
|
|
||||||
wc, wErr := soc.NextWriter(websocket.TextMessage)
|
wc, wErr := soc.NextWriter(websocket.TextMessage)
|
||||||
|
@ -40,7 +41,7 @@ func (sh *ServletHandlers) WriteResponse(servletCTX rpc.ServletContext, conn int
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sh *ServletHandlers) WriteNotification(servletCTX rpc.ServletContext, conn interface{}, codec protocol.ServerCodec, method string, args []interface{}) error {
|
func (srwch *ServletReadWriteCloseHandler) WriteNotification(servletCTX rpc.ServletContext, conn interface{}, codec protocol.ServerCodec, method string, args []interface{}) error {
|
||||||
soc := conn.(cwf.Socket)
|
soc := conn.(cwf.Socket)
|
||||||
|
|
||||||
wc, wErr := soc.NextWriter(websocket.TextMessage)
|
wc, wErr := soc.NextWriter(websocket.TextMessage)
|
26
servlet.go
26
servlet.go
|
@ -11,9 +11,10 @@ import (
|
||||||
cuc "git.loafle.net/commons_go/util/context"
|
cuc "git.loafle.net/commons_go/util/context"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewServlet(sh ServletHandler) Servlet {
|
func NewServlet(sh ServletHandler, rwcSH ServletReadWriteCloseHandler) Servlet {
|
||||||
return &rpcServlet{
|
return &rpcServlet{
|
||||||
sh: sh,
|
sh: sh,
|
||||||
|
rwcSH: rwcSH,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,6 +30,8 @@ type Servlet interface {
|
||||||
type rpcServlet struct {
|
type rpcServlet struct {
|
||||||
ctx ServletContext
|
ctx ServletContext
|
||||||
sh ServletHandler
|
sh ServletHandler
|
||||||
|
rwcSH ServletReadWriteCloseHandler
|
||||||
|
|
||||||
responseQueueChan chan *responseState
|
responseQueueChan chan *responseState
|
||||||
|
|
||||||
doneChan chan<- error
|
doneChan chan<- error
|
||||||
|
@ -45,12 +48,17 @@ func (s *rpcServlet) Start(parentCTX cuc.Context, conn interface{}, doneChan cha
|
||||||
}
|
}
|
||||||
s.sh.Validate()
|
s.sh.Validate()
|
||||||
|
|
||||||
|
if nil == s.rwcSH {
|
||||||
|
panic("Servlet: servlet RWC handler must be specified.")
|
||||||
|
}
|
||||||
|
s.rwcSH.Validate()
|
||||||
|
|
||||||
if s.stopChan != nil {
|
if s.stopChan != nil {
|
||||||
return fmt.Errorf("Servlet: servlet is already running. Stop it before starting it again")
|
return fmt.Errorf("Servlet: servlet is already running. Stop it before starting it again")
|
||||||
}
|
}
|
||||||
servletCTX := s.sh.ServletContext(parentCTX)
|
s.ctx = s.sh.ServletContext(parentCTX)
|
||||||
|
|
||||||
sc, err := s.sh.getCodec(servletCTX.GetAttribute(ContentTypeKey).(string))
|
sc, err := s.sh.getCodec(s.ctx.GetAttribute(ContentTypeKey).(string))
|
||||||
if nil != err {
|
if nil != err {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -76,10 +84,12 @@ func (s *rpcServlet) Stop() {
|
||||||
if s.stopChan == nil {
|
if s.stopChan == nil {
|
||||||
panic("Server: server must be started before stopping it")
|
panic("Server: server must be started before stopping it")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s.sh.Destroy(s.ctx)
|
||||||
|
|
||||||
close(s.stopChan)
|
close(s.stopChan)
|
||||||
s.stopWg.Wait()
|
s.stopWg.Wait()
|
||||||
s.stopChan = nil
|
s.stopChan = nil
|
||||||
s.sh.Destroy(s.ctx)
|
|
||||||
|
|
||||||
s.responseQueueChan = nil
|
s.responseQueueChan = nil
|
||||||
|
|
||||||
|
@ -153,7 +163,7 @@ func handleReader(s *rpcServlet, stopChan chan struct{}, doneChan chan error) {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
requestCodec, err := s.sh.ReadRequest(s.ctx, s.serverCodec, s.conn)
|
requestCodec, err := s.rwcSH.ReadRequest(s.ctx, s.serverCodec, s.conn)
|
||||||
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")
|
||||||
|
@ -204,11 +214,11 @@ func handleWriter(s *rpcServlet, stopChan chan struct{}, doneChan chan error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if nil != rs.requestCodec {
|
if nil != rs.requestCodec {
|
||||||
if err := s.sh.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().Error(fmt.Sprintf("RPC Server: response error %v", err))
|
logging.Logger().Error(fmt.Sprintf("RPC Server: response error %v", err))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if err := s.sh.WriteNotification(s.ctx, s.conn, s.serverCodec, rs.noti.method, rs.noti.args); nil != err {
|
if err := s.rwcSH.WriteNotification(s.ctx, s.conn, s.serverCodec, rs.noti.method, rs.noti.args); nil != err {
|
||||||
logging.Logger().Error(fmt.Sprintf("RPC Server: notification error %v", err))
|
logging.Logger().Error(fmt.Sprintf("RPC Server: notification error %v", err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -242,5 +252,5 @@ type responseState struct {
|
||||||
|
|
||||||
type notification struct {
|
type notification struct {
|
||||||
method string
|
method string
|
||||||
args []interface{}
|
args interface{}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,10 +10,7 @@ type ServletHandler interface {
|
||||||
|
|
||||||
Init(servletCTX ServletContext) error
|
Init(servletCTX ServletContext) error
|
||||||
|
|
||||||
ReadRequest(servletCTX ServletContext, codec protocol.ServerCodec, conn interface{}) (protocol.ServerRequestCodec, error)
|
|
||||||
Invoke(servletCTX ServletContext, requestCodec protocol.RegistryCodec) (result interface{}, err error)
|
Invoke(servletCTX ServletContext, requestCodec protocol.RegistryCodec) (result interface{}, err error)
|
||||||
WriteResponse(servletCTX ServletContext, conn interface{}, requestCodec protocol.ServerRequestCodec, result interface{}, err error) error
|
|
||||||
WriteNotification(servletCTX ServletContext, conn interface{}, codec protocol.ServerCodec, method string, args []interface{}) error
|
|
||||||
|
|
||||||
Destroy(servletCTX ServletContext)
|
Destroy(servletCTX ServletContext)
|
||||||
|
|
||||||
|
|
|
@ -29,22 +29,10 @@ func (sh *ServletHandlers) Init(servletCTX ServletContext) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sh *ServletHandlers) ReadRequest(servletCTX ServletContext, codec protocol.ServerCodec, conn interface{}) (protocol.ServerRequestCodec, error) {
|
|
||||||
return nil, fmt.Errorf("Servlet Handler: ReadRequest is not implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sh *ServletHandlers) Invoke(servletCTX ServletContext, requestCodec protocol.RegistryCodec) (result interface{}, err error) {
|
func (sh *ServletHandlers) Invoke(servletCTX ServletContext, requestCodec protocol.RegistryCodec) (result interface{}, err error) {
|
||||||
return nil, fmt.Errorf("Servlet Handler: Invoke is not implemented")
|
return nil, fmt.Errorf("Servlet Handler: Invoke is not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sh *ServletHandlers) WriteResponse(servletCTX ServletContext, conn interface{}, requestCodec protocol.ServerRequestCodec, result interface{}, err error) error {
|
|
||||||
return fmt.Errorf("Servlet Handler: WriteResponse is not implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sh *ServletHandlers) WriteNotification(servletCTX ServletContext, conn interface{}, codec protocol.ServerCodec, method string, args []interface{}) error {
|
|
||||||
return fmt.Errorf("Servlet Handler: WriteNotification is not implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sh *ServletHandlers) Destroy(servletCTX ServletContext) {
|
func (sh *ServletHandlers) Destroy(servletCTX ServletContext) {
|
||||||
// no op
|
// no op
|
||||||
}
|
}
|
||||||
|
|
11
servlet_rwc_handler.go
Normal file
11
servlet_rwc_handler.go
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
package rpc
|
||||||
|
|
||||||
|
import "git.loafle.net/commons_go/rpc/protocol"
|
||||||
|
|
||||||
|
type ServletReadWriteCloseHandler interface {
|
||||||
|
ReadRequest(servletCTX ServletContext, codec protocol.ServerCodec, conn interface{}) (protocol.ServerRequestCodec, 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
|
||||||
|
|
||||||
|
Validate()
|
||||||
|
}
|
26
servlet_rwc_handlers.go
Normal file
26
servlet_rwc_handlers.go
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
package rpc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"git.loafle.net/commons_go/rpc/protocol"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ServletReadWriteCloseHandlers struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (srwch *ServletReadWriteCloseHandlers) ReadRequest(servletCTX ServletContext, codec protocol.ServerCodec, conn interface{}) (protocol.ServerRequestCodec, error) {
|
||||||
|
return nil, fmt.Errorf("Servlet RWC Handler: ReadRequest is not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (srwch *ServletReadWriteCloseHandlers) WriteResponse(servletCTX ServletContext, conn interface{}, requestCodec protocol.ServerRequestCodec, result interface{}, err error) error {
|
||||||
|
return fmt.Errorf("Servlet RWC Handler: WriteResponse is not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (srwch *ServletReadWriteCloseHandlers) WriteNotification(servletCTX ServletContext, conn interface{}, codec protocol.ServerCodec, method string, params interface{}) error {
|
||||||
|
return fmt.Errorf("Servlet RWC Handler: WriteNotification is not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (srwch *ServletReadWriteCloseHandlers) Validate() {
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user