bool init_send_buf_ex(
const google::protobuf::Message& msg,
char* buf,
size_t* bufsize)
{
assert(buf && bufsize && *bufsize);
google::protobuf::io::ArrayOutputStream aos(
buf,
*bufsize);
google::protobuf::io::CodedOutputStream coded_output(&aos);
// 写名字长度
std::string msgname_ = msg.GetTypeName();
if(msgname_.empty() || msgname_.length() >= ProtobufMessageMaxNamelen)
{
LogError("Invalid message name '%s' when init_send_buf_ex",msgname_.c_str());
return false;
}
coded_output.WriteVarint32(uint32_t(msgname_.length()));
// 写名字
coded_output.WriteString(msgname_);
// buffer是否够大
if(msg.ByteSize() + coded_output.ByteCount() > *bufsize)
{
LogError("buf size '%ld' is too small,need '%ld'",
*bufsize,
msg.ByteSize() + coded_output.ByteCount());
return false;
}
// 序列化
msg.SerializeToCodedStream(&coded_output);
*bufsize = coded_output.ByteCount();
return true;
}
/**
* @brief 根据名字获取实际的Message对象
* @param typeName
* @return
*/
static google::protobuf::Message* Name2ProtobufMessage(
const char* name)
{
assert(name);
google::protobuf::Message* message = NULL;
const google::protobuf::Descriptor* descriptor =
google::protobuf::DescriptorPool::generated_pool()->FindMessageTypeByName(name);
if (descriptor)
{
const google::protobuf::Message* prototype =
google::protobuf::MessageFactory::generated_factory()->GetPrototype(descriptor);
if (prototype)
{
message = prototype->New();
}
}
return message;
}
void LanServerBase::read_imp(int fd)
{
char buf_[1024];
struct sockaddr_in addr_;
socklen_t addrlen_ = sizeof(addr_);
int len_ = recvfrom_ex(fd,buf_,sizeof(buf_),0,
(struct sockaddr*)&addr_,&addrlen_);
if(len_ <= 0)
{
if(len_ < 0)
{
LogError("%s %d %s",strerror(errno),errno,"recvfrom_ex");
}
return;
}
assert(sizeof(addr_) <= addrlen_);
google::protobuf::io::ArrayInputStream ais(buf_,len_);
google::protobuf::io::CodedInputStream coded_input(&ais);
// msg 类型是否合法
bool result_ = false;
// 读取名称长度
uint32_t msgname_len_ = 0;
result_ = coded_input.ReadVarint32(&msgname_len_);
if(!result_ ||
0 == msgname_len_ ||
ProtobufMessageMaxNamelen <= msgname_len_)
{
LogError("ReadVarint32 msgname_len fail with size '%d'",msgname_len_);
return;
}
// 读取名称
std::string msgname_;
result_ = coded_input.ReadString(&msgname_,msgname_len_);
if(!result_)
{
LogError("ReadString msgname fail with size '%d'",msgname_len_);
return;
}
google::protobuf::Message* msg_ = Name2ProtobufMessage(msgname_.c_str());
if(!msg_)
{
LogError("Name2ProtobufMessage fail with name '%s'",msgname_.c_str());
return;
}
if(!msg_->ParseFromCodedStream(&coded_input))
{
LogError("ParseFromCodedStream fail with name '%s'",msgname_.c_str());
delete msg_;
return;
}
delete msg_;
}