Parsing error in Protocol Buffer using C++ API - c++

I have a test.proto file having the code shown below. I am using code generated by this file in my client server program.
message Person {
required string user_name = 1;
optional int32 favourite_number = 2;
repeated string interests = 3;
}
Client side i have no problem to send data but at the server side i am getting protocol buffer parsing error(in the file:\protobuf\message_lite.cc(line123)) says "cant parse message of type 'person' because its missing required field:user_name"
Though i have checked my client side but couldnt find anything wrong but i might missing something at server side which is not reading string data ?
//Server side code for Protocol Buffers
Person filldata;
google::protobuf::uint32 size;
//here i might need google::protobuf::string stsize; Not sure ?
google::protobuf::io::ArrayInputStream ais(buffer,filldata.ByteSize());
CodedInputStream coded_input(&ais);
coded_input.ReadVarint32(&size);
//have tried here both coded_input.ReadString and coded_input.ReadRaw
filldata.ParseFromCodedStream(&coded_input);
cout<<"Message is "<<filldata.DebugString();
//still getting same error have no idea what to do exactly to fix it :(
Haved Looked Here but still couldnt got it from that explanation, Hope someone can fix it.
Thanks!

google::protobuf::io::ArrayInputStream ais(buffer,filldata.ByteSize());
At this point, filldata is a newly-initialized message, so filldata.ByteSize() is zero. So, you're telling protobufs to parse an empty array. Hence, no fields are set, and you get a required fields error. Messages have variable length, so you need to make sure the exact message size is passed along from the server.

Related

modify raw protobuf stream

Let's say I have compiled an application (Receiver) with the following proto file:
syntax = "proto3";
message Control {
bytes version = 1;
uint32 id = 2;
bytes color = 3;
}
and I have another application (Transmitter) which initially has the same proto file but after an update a new field is added like:
syntax = "proto3";
message Control {
bytes name = 1;
uint32 id = 2;
bytes color = 3;
uint32 color_id = 4;
}
I have seen that if the Receiver app tries to parse the proto, change some data and then serialize it back the added fields coming from the Transmitter app are removed.
I need a way to change the id field directly accessing to the raw bytes without having to parse/serialize the proto. Is it possible ?
This is needed because I have some "header" fields in the Control message that I know that will never be changed but others that can be added/changed in the same proto of trasmitter app due to app update.
I have seen: https://developers.google.com/protocol-buffers/docs/reference/cpp/google.protobuf.io.coded_stream
but I was not able to modify an existing bytestream and the ReadString is not able to understand the string length.
Thanks in advance
I don't think there is an official way to do it. You could do this by hand following the encoding guidelines by protobuf (https://developers.google.com/protocol-buffers/docs/encoding#structure).
Basically you should do this:
start decoding with the very first bit
decode until you reach the field number of the id
identify the bits representing the id and replace them with your new (encoded!) id
This is bad for several reasons. Most importantly, your code has to know details about the message structure and content (field number and data type of your id), and this is exactly what you want to avoid when using protocol buffers (you always need some info from the .proto files).
In proto2 syntax, protobuf C++ library used to preserve unknown fields so that when you re-encoded the message, they would remain. Unfortunately this feature (like many others) have been removed in the proto3 syntax.
One workaround could be to do it this way:
Set only the new id value in the Receiver message and encode it.
Append this data after the original binary data.
This relies on the protobuf feature that appended messages replace original values of fields in protobuf messages.
Hmm, actually reading the issue report linked above, it seems that you can turn on unknown field preservation in protobuf version 3.5 and newer.
Just deserialize the entire message and map it on the new message. It is the cleanest way. You do not have a lot of data and probably no real time requirements. Create a mapper and do not overthink the problem.

Sending a STOMP frame through websocket

Since there's no webstomp (STOMP through Websocket) C++ implementation anywhere, I'm developing my own. I have a webstomp server set up already, and I've confirmed that it works using the javascript implementation of webstomp.
Now I'm relying on QT's implementation of websocket. I tested and works with a regular websocket. So now comes the implementation of STOMP. Looking at the STOMP frames the first frame I have to send could be something like this:
CONNECT
login: <username>
passcode: <passcode>
^#
With ^#being the null-character. The problem I'm having is that no matter what I do, I can't seem to get any type of response from the server. I tried different encodings, different messages, different connect frames, etc. I was wondering if I was doing something wrong or if I was missing something. An example of the above frame looks like this:
void WebSTOMP::onConnected()
{
if (m_debug)
qDebug() << "WebSocket connected";
connect(&m_webSocket, &QWebSocket::textMessageReceived,
this, &EchoClient::onTextMessageReceived);
std::string myMessage = "CONNECT \nlogin: test\npasscode : test\n\n\0";
m_webSocket.sendTextMessage(QString::fromUtf8(myMessage.c_str()));
}
And then I never get a response back.
Thanks in advance =)
Add one to the length of the message due to the string's null character terminator
Solved it. For the future: had to manually specify the length due to including a null character terminator.

Cannot Send Image File (image/jpg) Using Winsock WSABUF

I'm stuck and I need help.
I'm trying to write the correct code for sending back an image file so the web browser can render it. It can send back text/html just fine, but image/* is not working.
You can see the code and the URL is shown below.
https://github.com/MagnusTiberius/iocphttpd/blob/master/iocphttpl/SocketCompletionPortServer.cpp
What the browser is receiving is just a few bytes of image data.
I tried vector, std::string and const char* to set the values of WSABUF, but still the same few bytes are sent over.
Please let know what is the missing piece to make this one work.
Thanks in advance.
Here's your problem:
PerIoData->LPBuffer = _strdup(str.c_str());
The _strdup function only copies up until the first null, so it cannot be used to copy binary data. Consider using malloc and memcpy if you don't want to use the C++ library.
The alternate implementation (in the false branch) is also incorrect, because it saves the data in an object (vc) that goes out of scope before the I/O is completed. You could instead do something like
vector<char> * vc = new vector<char>;

Socket Read \n at the End From Java Client

Using below code I reading data from socket. On the other side the Java client sending string data. But while reading the data an additional \n appears at the end of the string. Can anyone explain why this happen.
Code:
unsigned char buf[100];
rd=read(newsockfd,buf,100);
char cmd[30];
sprintf(cmd,"%s",buf);
Result:
buf->"DATA\n"
cmd->"DATA\n"
From the client if I sent "DATA" then I am getting "DATA\n" at the server side. Can anyone explain the reason for this ? and how can I extract the exact data I sent.
My guess here would be that the newline comes from the Java client itself.
Probably the client is using a function like sendLine(String) or something that adds a newline to the string passed to it before sending it on the network. I don't know Java but this seems very likely.
In java you can say (as other people has pointed) socket.writeLine("Data") which appends a "\n" at the end.
One thing I've noticed though, in the code you wrote, there is a possibly error you could get, if the sender sends you more than 100 chars you would get a memory error.
unsigned char buf[100];
rd=read(newsockfd,buf,1024);
Here you say you want to read up to 1024 chars/bytes but the buffer is declared as [100], be careful!

Curlpp, incomplete data from request

I am using Curlpp to send requests to various webservices to send and receive data.
So far this has worked fine since i have only used it for sending/receiving JSON data.
Now i have a situation where a webservice returns a zip file in binary form. This is where i encountered a problem where the data received is not complete.
I first had Curl set to write any data to a ostringstream by using the option WriteStream, but this proved not to be the correct approach since the data contained null characters, and thus the data stopped at the first null char.
After that, instead of using WriteStream i used WriteFunction with a callback function.
The problem in this case is that this function is always called 2 or 3 times, regardless of the amount of data.
This results in always having a few chunks of data that don't seem to be the first part of the file, although the data always contains PK as the first 2 characters, indicating a zip file.
I used several tools to verify that the data is entirely being sent to my application so this is not a problem of the webservice.
Here the code. Do note that the options like hostname, port, headers and postfields are set elsewhere.
string requestData;
size_t WriteStringCallback(char* ptr, size_t size, size_t nmemb)
{
requestData += ptr;
int totalSize= size*nmemb;
return totalSize;
}
const string CurlRequest::Perform()
{
curlpp::options::WriteFunction wf(WriteStringCallback);
this->request.setOpt( wf );
this->request.perform();
return requestData;
}
I hope anyone can help me out with this issue because i've run dry of any leads on how to fix this, also because curlpp is poorly documented(and even worse since the curlpp website disappeared).
The problem with the code is that the data is put into a std::string, despite having the data in binary (ZIP) format. I'd recommend to put the data into a stream (or a binary array).
You can also register a callback to retrieve the response headers and act in the WriteCallback according to the "Content-type".
curlpp::options::HeaderFunction to register a callback to retrieve response-headers.
std::string is not a problem, but the concatenation is:
requestData += ptr;
C string (ptr) is terminated with zero, if the input contains any zero bytes, the input will be truncated. You should wrap it into a string which knows the length of its data:
requestData += std::string(ptr, size*nmemb);