gateway_rpc/servlet/rpc-servlet.go

194 lines
4.3 KiB
Go
Raw Normal View History

2018-04-06 12:44:24 +00:00
package servlet
import (
2018-04-09 16:02:35 +00:00
"context"
2018-04-13 12:12:04 +00:00
"sync"
2018-04-09 16:02:35 +00:00
logging "git.loafle.net/commons/logging-go"
crp "git.loafle.net/commons/rpc-go/protocol"
2018-04-06 12:44:24 +00:00
"git.loafle.net/commons/server-go"
2018-04-13 12:12:04 +00:00
css "git.loafle.net/commons/server-go/socket"
2018-04-09 16:02:35 +00:00
cssw "git.loafle.net/commons/server-go/socket/web"
2018-05-11 08:05:31 +00:00
oe "git.loafle.net/overflow/external-go"
2018-05-11 07:55:34 +00:00
oeg "git.loafle.net/overflow/external-go/grpc"
2018-04-09 16:02:35 +00:00
og "git.loafle.net/overflow/gateway"
"github.com/valyala/fasthttp"
2018-04-09 17:04:28 +00:00
"google.golang.org/grpc/metadata"
2018-04-06 12:44:24 +00:00
)
type RPCServlet interface {
cssw.Servlet
2018-04-06 12:57:41 +00:00
}
2018-04-06 12:44:24 +00:00
type RPCServlets struct {
cssw.Servlets
2018-05-08 10:09:47 +00:00
RPCServerCodec crp.ServerCodec
UseSession bool
2018-04-13 12:12:04 +00:00
sessions sync.Map
2018-04-06 12:44:24 +00:00
}
func (s *RPCServlets) Handshake(servletCtx server.ServletCtx, ctx *fasthttp.RequestCtx) (*fasthttp.ResponseHeader, error) {
return nil, nil
}
2018-04-13 12:12:04 +00:00
func (s *RPCServlets) OnConnect(servletCtx server.ServletCtx, conn css.Conn) {
s.Servlets.OnConnect(servletCtx, conn)
if s.UseSession {
sessionID := servletCtx.GetAttribute(og.SessionIDKey)
targetID := servletCtx.GetAttribute(og.SessionTargetIDKey)
if nil != sessionID && nil != targetID {
s.sessions.Store(sessionID.(string), RetainSession(targetID.(string), servletCtx))
}
}
}
func (s *RPCServlets) OnDisconnect(servletCtx server.ServletCtx) {
s.Servlets.OnDisconnect(servletCtx)
if s.UseSession {
sessionID := servletCtx.GetAttribute(og.SessionIDKey)
if nil != sessionID {
s.sessions.Delete(sessionID.(string))
}
}
}
2018-04-09 16:02:35 +00:00
func (s *RPCServlets) Handle(servletCtx server.ServletCtx,
stopChan <-chan struct{}, doneChan chan<- struct{},
readChan <-chan []byte, writeChan chan<- []byte) {
2018-04-06 12:44:24 +00:00
defer func() {
doneChan <- struct{}{}
}()
2018-04-09 16:02:35 +00:00
var (
2018-04-09 17:04:28 +00:00
md metadata.MD
2018-04-09 16:02:35 +00:00
src crp.ServerRequestCodec
method string
params []string
grpcCtx context.Context
grpcReply string
replyBuff []byte
err error
)
2018-04-09 17:04:28 +00:00
_clientType := servletCtx.GetAttribute(og.SessionClientTypeKey)
_sessionID := servletCtx.GetAttribute(og.SessionIDKey)
_targetID := servletCtx.GetAttribute(og.SessionTargetIDKey)
if nil != _clientType && nil != _sessionID && nil != _targetID {
md = metadata.Pairs(
2018-05-11 08:05:31 +00:00
oe.GRPCClientTypeKey.String(), _clientType.(og.ClientType).String(),
oe.GRPCSessionIDKey.String(), _sessionID.(string),
oe.GRPCTargetIDKey.String(), _targetID.(string),
2018-04-09 17:04:28 +00:00
)
}
servletCtx.SetAttribute(og.SessionWriteChanKey, writeChan)
2018-04-06 12:44:24 +00:00
for {
select {
case msg, ok := <-readChan:
if !ok {
return
}
// grpc exec method call
2018-05-08 10:09:47 +00:00
src, err = s.RPCServerCodec.NewRequest(msg)
2018-04-09 16:02:35 +00:00
if nil != err {
2018-04-10 03:53:46 +00:00
logging.Logger().Error(err)
2018-04-09 16:02:35 +00:00
break
}
2018-04-06 12:44:24 +00:00
2018-04-09 16:02:35 +00:00
method = src.Method()
params, err = src.Params()
if nil != err {
2018-04-10 03:53:46 +00:00
logging.Logger().Error(err)
s.writeError(src, writeChan, crp.E_BAD_PARAMS, "", err)
2018-04-09 16:02:35 +00:00
break
}
2018-04-06 12:44:24 +00:00
2018-04-09 17:04:28 +00:00
grpcCtx = metadata.NewOutgoingContext(context.Background(), md)
2018-05-11 07:55:34 +00:00
grpcReply, err = oeg.Exec(grpcCtx, method, params...)
2018-04-19 14:45:56 +00:00
if nil != err {
logging.Logger().Error(err)
}
if !src.HasResponse() {
break
}
2018-04-09 16:02:35 +00:00
replyBuff, err = src.NewResponseWithString(grpcReply, err)
2018-04-09 16:46:48 +00:00
if nil != err {
2018-04-10 03:53:46 +00:00
logging.Logger().Error(err)
s.writeError(src, writeChan, crp.E_INTERNAL, "", err)
2018-04-09 16:46:48 +00:00
break
}
2018-04-06 12:44:24 +00:00
2018-04-09 16:02:35 +00:00
writeChan <- replyBuff
2018-04-06 12:44:24 +00:00
case <-stopChan:
return
}
}
2018-04-09 16:02:35 +00:00
}
2018-04-09 16:46:48 +00:00
2018-04-10 03:53:46 +00:00
func (s *RPCServlets) writeError(src crp.ServerRequestCodec, writeChan chan<- []byte, code crp.ErrorCode, message string, data interface{}) {
2018-04-09 16:46:48 +00:00
if !src.HasResponse() {
return
}
pErr := &crp.Error{
Code: code,
Message: message,
Data: data,
}
buf, err := src.NewResponse(nil, pErr)
if nil != err {
2018-04-10 03:53:46 +00:00
logging.Logger().Error(err)
2018-04-09 16:46:48 +00:00
return
}
writeChan <- buf
}
2018-04-13 12:12:04 +00:00
func (s *RPCServlets) GetSessions(sessionIDs []string) []*Session {
var sessions []*Session
if nil == sessionIDs || 0 == len(sessionIDs) {
return sessions
}
for _, sessionID := range sessionIDs {
session, ok := s.sessions.Load(sessionID)
if ok {
sessions = append(sessions, session.(*Session))
}
}
return sessions
}
func (s *RPCServlets) GetSessionsByTargetIDs(targetIDs []string) []*Session {
var sessions []*Session
if nil == targetIDs || 0 == len(targetIDs) {
return sessions
}
s.sessions.Range(func(k, v interface{}) bool {
session := v.(*Session)
for _, targetID := range targetIDs {
if session.TargetID == targetID {
sessions = append(sessions, session)
break
}
}
return true
})
return sessions
}