f8/cpp/netmsghandler.h
2020-06-12 19:06:28 +08:00

114 lines
3.7 KiB
C++

#ifndef NETMSGHANDLER_H
#define NETMSGHANDLER_H
#include <google/protobuf/generated_message_util.h>
#include <google/protobuf/message.h>
#include <google/protobuf/repeated_field.h>
#include <google/protobuf/extension_set.h>
#include <google/protobuf/unknown_field_set.h>
namespace f8
{
const unsigned short MAX_MSG_ID = 2000;
struct MsgHdr;
typedef bool (*CUSTOM_PARSER)(MsgHdr&, google::protobuf::Message*);
struct NetMsgHandler
{
int handlerid;
const ::google::protobuf::Message* prototype = nullptr;
CUSTOM_PARSER custom_parser = nullptr;
};
struct NetMsgHandlerObject
{
NetMsgHandler* handlers[MAX_MSG_ID] = { nullptr };
~NetMsgHandlerObject()
{
for (size_t i = 0; i < MAX_MSG_ID; ++i) {
if (handlers[i]) {
delete handlers[i];
handlers[i] = nullptr;
}
}
}
};
template<typename InstanceType, typename MsgType>
static void NetMsgHandlerWrapper(InstanceType* instance, MsgHdr& hdr, NetMsgHandler* handler)
{
MsgType msg;
bool ok = false;
if (handler->custom_parser) {
ok = handler->custom_parser(hdr, &msg);
} else {
ok = msg.ParseFromArray(hdr.buf + hdr.offset, hdr.buflen - hdr.offset);
}
assert(ok);
if (ok) {
struct Invoker: public NetMsgHandler
{
void (*wrapper)(InstanceType*, MsgHdr&, NetMsgHandler*);
void (InstanceType::*func)(MsgHdr&, const MsgType&);
};
Invoker* invoker = (Invoker*)handler;
auto ptr = invoker->func;
(instance->*ptr)(hdr, msg);
}
}
template<typename InstanceType, typename MsgType>
static void RegisterNetMsgHandler(NetMsgHandlerObject* msghandler,
void (InstanceType::*ptr)(MsgHdr&, const MsgType&),
CUSTOM_PARSER custom_parser = nullptr
)
{
MsgType dumy_msg;
static int msgid = f8::Net_GetMessageId(dumy_msg);
assert(msgid >= 0 || msgid < MAX_MSG_ID);
if (msgid < 0 || msgid >= MAX_MSG_ID) {
abort();
}
struct Invoker: public NetMsgHandler
{
void (*wrapper)(InstanceType*, MsgHdr&, NetMsgHandler*);
void (InstanceType::*func)(MsgHdr&, const MsgType&);
};
Invoker *p = new Invoker();
p->wrapper = &NetMsgHandlerWrapper<InstanceType, MsgType>;
p->func = ptr;
p->custom_parser = custom_parser;
p->handlerid = InstanceType::HID;
p->prototype = ::google::protobuf::MessageFactory::generated_factory()->GetPrototype(MsgType::descriptor());
msghandler->handlers[msgid] = p;
}
template<typename InstanceType>
static bool ProcessNetMsg(NetMsgHandler* handler,
InstanceType* instance,
MsgHdr& hdr)
{
if(handler){
struct Invoker: public NetMsgHandler
{
void (*wrapper)(InstanceType*, MsgHdr&, NetMsgHandler*);
void* func;
};
Invoker *p = (Invoker*)handler;
p->wrapper(instance, hdr, p);
return true;
}else{
return false;
}
}
NetMsgHandler* GetNetMsgHandler(NetMsgHandlerObject* handlers,
unsigned short msgid);
void DumpMsgToLog(f8::MsgHdr& hdr, f8::NetMsgHandler* handler, const char* prefix);
void DumpMsgToLog(const ::google::protobuf::Message& msg, const char* prefix);
}
#endif