Files
hk4e/gate-hk4e/net/proto_endecode.go
2022-11-20 15:38:00 +08:00

161 lines
4.6 KiB
Go

package net
import (
"flswld.com/gate-hk4e-api/proto"
"flswld.com/logger"
pb "google.golang.org/protobuf/proto"
)
type ProtoEnDecode struct {
apiProtoMap *proto.ApiProtoMap
}
func NewProtoEnDecode() (r *ProtoEnDecode) {
r = new(ProtoEnDecode)
r.apiProtoMap = proto.NewApiProtoMap()
return r
}
type ProtoMsg struct {
ConvId uint64
ApiId uint16
HeadMessage *proto.PacketHead
PayloadMessage pb.Message
}
type ProtoMessage struct {
apiId uint16
message pb.Message
}
func (p *ProtoEnDecode) protoDecode(kcpMsg *KcpMsg) (protoMsgList []*ProtoMsg) {
protoMsgList = make([]*ProtoMsg, 0)
protoMsg := new(ProtoMsg)
protoMsg.ConvId = kcpMsg.ConvId
protoMsg.ApiId = kcpMsg.ApiId
// head msg
if kcpMsg.HeadData != nil && len(kcpMsg.HeadData) != 0 {
headMsg := new(proto.PacketHead)
err := pb.Unmarshal(kcpMsg.HeadData, headMsg)
if err != nil {
logger.LOG.Error("unmarshal head data err: %v", err)
return protoMsgList
}
protoMsg.HeadMessage = headMsg
} else {
protoMsg.HeadMessage = nil
}
// payload msg
protoMessageList := make([]*ProtoMessage, 0)
p.protoDecodePayloadCore(kcpMsg.ApiId, kcpMsg.ProtoData, &protoMessageList)
if len(protoMessageList) == 0 {
logger.LOG.Error("decode proto object is nil")
return protoMsgList
}
if kcpMsg.ApiId == proto.ApiUnionCmdNotify {
for _, protoMessage := range protoMessageList {
msg := new(ProtoMsg)
msg.ConvId = kcpMsg.ConvId
msg.ApiId = protoMessage.apiId
msg.HeadMessage = protoMsg.HeadMessage
msg.PayloadMessage = protoMessage.message
//logger.LOG.Debug("[recv] union proto msg, convId: %v, apiId: %v", msg.ConvId, msg.ApiId)
if protoMessage.apiId == proto.ApiUnionCmdNotify {
// 聚合消息自身不再往后发送
continue
}
//logger.LOG.Debug("[recv] proto msg, convId: %v, apiId: %v, headMsg: %v", protoMsg.ConvId, protoMsg.ApiId, protoMsg.HeadMessage)
protoMsgList = append(protoMsgList, msg)
}
// 聚合消息自身不再往后发送
return protoMsgList
} else {
protoMsg.PayloadMessage = protoMessageList[0].message
}
//logger.LOG.Debug("[recv] proto msg, convId: %v, apiId: %v, headMsg: %v", protoMsg.ConvId, protoMsg.ApiId, protoMsg.HeadMessage)
protoMsgList = append(protoMsgList, protoMsg)
return protoMsgList
}
func (p *ProtoEnDecode) protoDecodePayloadCore(apiId uint16, protoData []byte, protoMessageList *[]*ProtoMessage) {
protoObj := p.decodePayloadToProto(apiId, protoData)
if protoObj == nil {
logger.LOG.Error("decode proto object is nil")
return
}
if apiId == proto.ApiUnionCmdNotify {
// 处理聚合消息
unionCmdNotify, ok := protoObj.(*proto.UnionCmdNotify)
if !ok {
logger.LOG.Error("parse union cmd error")
return
}
for _, cmd := range unionCmdNotify.GetCmdList() {
p.protoDecodePayloadCore(uint16(cmd.MessageId), cmd.Body, protoMessageList)
}
}
*protoMessageList = append(*protoMessageList, &ProtoMessage{
apiId: apiId,
message: protoObj,
})
}
func (p *ProtoEnDecode) protoEncode(protoMsg *ProtoMsg) (kcpMsg *KcpMsg) {
//logger.LOG.Debug("[send] proto msg, convId: %v, apiId: %v, headMsg: %v", protoMsg.ConvId, protoMsg.ApiId, protoMsg.HeadMessage)
kcpMsg = new(KcpMsg)
kcpMsg.ConvId = protoMsg.ConvId
kcpMsg.ApiId = protoMsg.ApiId
// head msg
if protoMsg.HeadMessage != nil {
headData, err := pb.Marshal(protoMsg.HeadMessage)
if err != nil {
logger.LOG.Error("marshal head data err: %v", err)
return nil
}
kcpMsg.HeadData = headData
} else {
kcpMsg.HeadData = nil
}
// payload msg
if protoMsg.PayloadMessage != nil {
apiId, protoData := p.encodeProtoToPayload(protoMsg.PayloadMessage)
if apiId == 0 || protoData == nil {
logger.LOG.Error("encode proto data is nil")
return nil
}
if apiId != 65535 && apiId != protoMsg.ApiId {
logger.LOG.Error("api id is not match with proto obj, src api id: %v, found api id: %v", protoMsg.ApiId, apiId)
return nil
}
kcpMsg.ProtoData = protoData
} else {
kcpMsg.ProtoData = nil
}
return kcpMsg
}
func (p *ProtoEnDecode) decodePayloadToProto(apiId uint16, protoData []byte) (protoObj pb.Message) {
protoObj = p.apiProtoMap.GetProtoObjByApiId(apiId)
if protoObj == nil {
logger.LOG.Error("get new proto object is nil")
return nil
}
err := pb.Unmarshal(protoData, protoObj)
if err != nil {
logger.LOG.Error("unmarshal proto data err: %v", err)
return nil
}
return protoObj
}
func (p *ProtoEnDecode) encodeProtoToPayload(protoObj pb.Message) (apiId uint16, protoData []byte) {
apiId = p.apiProtoMap.GetApiIdByProtoObj(protoObj)
var err error = nil
protoData, err = pb.Marshal(protoObj)
if err != nil {
logger.LOG.Error("marshal proto object err: %v", err)
return 0, nil
}
return apiId, protoData
}