I try to send a protocol buffer message over TCP, but on the recipient side I get the "Missing required fields" error when trying to parse, although apparently all the fields are there. I am sending a 4 byte header before a 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 encode the header and serialize 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 the hexadecimal print of the resulting buffer, where the first 4 bytes is the length of the encoded message (13 bytes).
00 00 00 0d 0a 07 63 68 61 6e 6e 65 6c 10 01 18 05
On the server side, I get the header, decode it, and then get N bytes, where N is the size of the message reported in the header. Buffer on server with remote header:
0a 07 63 68 61 6e 6e 65 6c 10 01 18 05
This is exactly the same as one encoded client side minus the header, but when I try ParseFromArray in this buffer, I get an error message:
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
During debugging, I noticed that the point at which decoding takes place is in this part of the code created by protobuf:
bool ReplayRequest::IsInitialized() const { if ((_has_bits_[0] & 0x00000007) != 0x00000007) return false; return true; }
has_bits_ is for some reason read as zero on the server side, but I cannot understand why.
Any ideas?
I use boost :: asio for the network part, if that matters.
Update
As requested, I am sending a code that calls parseFromArray.
request_.ParseFromArray( &data_buffer_, data_buffer_.size() );
request_ is a ReplayRequest member variable until this call does anything to it.
data_buffer_ is the vector <uint8_t> where TCP data is received.
I confirmed that it has the correct size of 13 bytes, and this is its hexadecimal dump, which I get when I flush the client side of the buffer after serialization.
0a 07 63 68 61 6e 6e 65 6c 10 01 18 05
Update 2
I can parse the buffer to another client-side ReplayRequest instance, that is:
...snip... req.SerializeToArray( &write_buffer[HEADER_SIZE], byte_size ); ReplayRequest test; test.ParseFromArray( &write_buffer[HEADER_SIZE], byte_size );
Test
successfully filled in with the correct fields.