I'm trying to send a protocol buffer message over TCP, but on the receiving side I'm getting a "Missing required fields" error when trying to parse, even though apparently all the fields are there. I'm sending a 4 byte header before the message that contains the length of the message.
Here is the message definition:
message ReplayRequest {
required string channel = 1;
required uint32 start = 2;
required uint32 end = 3;
}
On the client side I'm encoding the header and serializing the message into a vector.
ReplayRequest req;
req.set_channel( "channel" )
req.set_start( 1 );
req.set_end( 5 );
int byte_size = req.ByteSize();
std::vector<uint8_t> write_buffer( HEADER_SIZE + byte_size );
encode_header( ... );
req.SerializeToArray( &write_buffer[HEADER_SIZE], byte_size );
This is a hex print of the resulting buffer, where the first 4 bytes are the encoded message length (13 bytes).
00 00 00 0d 0a 07 63 68 61 6e 6e 65 6c 10 01 18 05
On the server side, I receive the header, decode it and then receive N bytes where N is the message size reported in the header. The buffer in the server with the header removed is:
0a 07 63 68 61 6e 6e 65 6c 10 01 18 05
Which is exactly the same as the one encoded client side minus the header, but when I try to ParseFromArray this buffer I get an error:
libprotobuf ERROR c:\umdf_runtime\protobuf-2.4.1\src\google\protobuf\message_lit
e.cc:123] Can't parse message of type "ReplayRequest" because it is missing
required fields: channel, start, end
While debugging I noticed that the point where decoding fails is on this part of the protobuf generated code:
bool ReplayRequest::IsInitialized() const {
if ((_has_bits_[0] & 0x00000007) != 0x00000007) return false;
return true;
}
has_bits_ is being read as zero on the server side for some reason but I can't figure out why.
Any ideas?
I'm using boost::asio for the network part if it matters.
Update
As requested I'm posting the code that calls parseFromArray.
request_.ParseFromArray( &data_buffer_, data_buffer_.size() );
request_ is a ReplayRequest member variable, up until this call nothing is done to it.
data_buffer_ is a vector<uint8_t> where the TCP data is received into.
I confirmed that it is correctly sized at 13 bytes and this is its hex dump, which is the same that I get when I dump the buffer client side after serializing.
0a 07 63 68 61 6e 6e 65 6c 10 01 18 05
Update 2
I am able to parse the buffer into another instance of ReplayRequest on the client side, i.e.:
...snip...
req.SerializeToArray( &write_buffer[HEADER_SIZE], byte_size );
ReplayRequest test;
test.ParseFromArray( &write_buffer[HEADER_SIZE], byte_size );
test is successfully populated with the correct fields.