61 lines
1.7 KiB
C++
61 lines
1.7 KiB
C++
|
#include "proto_msg.h"
|
||
|
#include <google/protobuf/descriptor.h>
|
||
|
#include <string>
|
||
|
|
||
|
using namespace std;
|
||
|
using namespace google::protobuf;
|
||
|
|
||
|
// 4 byte total msg len, including this 4 bytes
|
||
|
// 4 byte name len
|
||
|
// name string not null ended
|
||
|
// protobuf data
|
||
|
ProtoMessage *ProtoMsgCodec::decode(unsigned char* buf, size_t size)
|
||
|
{
|
||
|
if (size < 8) {
|
||
|
return nullptr;
|
||
|
}
|
||
|
char *p = (char *)buf;
|
||
|
uint32_t msglen = *(uint32_t *)buf;
|
||
|
uint32_t namelen = *(uint32_t *)(buf + 4);
|
||
|
if (size < msglen || size < 4 + namelen) {
|
||
|
return nullptr;
|
||
|
}
|
||
|
string typeName(p + 8, namelen);
|
||
|
ProtoMessage *msg = NULL;
|
||
|
const ProtoDescriptor *des = DescriptorPool::generated_pool()->FindMessageTypeByName(typeName);
|
||
|
if (des) {
|
||
|
const ProtoMessage *proto = MessageFactory::generated_factory()->GetPrototype(des);
|
||
|
if (proto) {
|
||
|
msg = proto->New();
|
||
|
}
|
||
|
}
|
||
|
if (msg == NULL) {
|
||
|
return nullptr;
|
||
|
}
|
||
|
int r = msg->ParseFromArray(p + 8 + namelen, msglen - 8 - namelen);
|
||
|
if (!r) {
|
||
|
delete msg;
|
||
|
return nullptr;
|
||
|
}
|
||
|
return msg;
|
||
|
}
|
||
|
|
||
|
unsigned char* ProtoMsgCodec::encode(ProtoMessage *msg, size_t& msgSize) {
|
||
|
if (!msg)
|
||
|
return nullptr;
|
||
|
const string &typeName = msg->GetDescriptor()->full_name();
|
||
|
uint32_t buf_size = 4 + 4 + typeName.size() + msg->ByteSize();
|
||
|
unsigned char* buf = new unsigned char[buf_size];
|
||
|
if (!buf)
|
||
|
return nullptr;
|
||
|
*(uint32_t*)buf = buf_size;
|
||
|
size_t offset = 4;
|
||
|
*(uint32_t*)(buf + offset) = typeName.size();
|
||
|
offset += 4;
|
||
|
memcpy_s(buf + offset, buf_size, typeName.data(), typeName.size());
|
||
|
offset += typeName.size();
|
||
|
msg->SerializeToArray(buf + offset, msg->ByteSize());
|
||
|
msgSize = buf_size;
|
||
|
return buf;
|
||
|
}
|