I have the following situation:
NSData *audioData = [NSData dataWithContentOfFile:[fileURL path] options:0 error:nil];
I need to send this audioData to the server using a method that accepts as input parameter pj_str_t value;
So I did:
unsigned char *getBytes = (unsigned char*)[audioData bytes]; //here insteand of 10600 bytes I only have 4 bytes.
value=pj_str((char*)getBytes);
The value is a string from 4 bytes. What am I doing wrong?
Beware that audio data can contain 0's and the pj_str(char *) function you're using will mistake them for the end of the string. Try this:
pj_str_t string;
pj_strset(&string, getBytes, [audioData length]);
Related
I am having a lot of trouble with GRPC when using byte array. This is by .proto
message myType {
int32 format = 1;
bytes data = 2;
}
I am using CPP for Server implementation and Java for Client. Using ByteString in Java is a breeze but cannot deserialize in CPP (byte[] being changed from what was being sent from Java).
buffer is a byte[] byte buffer[<large_size>] And I'm converting the byte array (it's an image) into a smaller byte array, and it's crashing when trying to convert the byte[] received from grpc. The conversion function in CPP is good as I used it with the same image before using GRPC
This is the deserialization code for CPP. Here "req" is a myType object, and buffer is a byte[]
myFormat = req->format();
dataLen = req->data().length();
memcpy(buffer, req->data().c_str(), dataLen);
From what I understand, req->data() is in cpp std::string format
On the client side, you should pass both the parameter and its length.
parameter.set_framemat(mat, 12);
Do check if the length of the array at the server side is not zero. Note that bytes is char array and grpc is de marshalling it as string. So if say the array is filled with null characters the data length comes as zero.
I was trying a similar use case
Proto file
message Parameters {
bytes framemat = 16;
};
Client Snippet
const char mat[12] = {0}
parameter.set_framemat(mat);
stream->Write(parameter);
Server Snippet
std::thread reader([&]() {
::nokia::nas::Parameters request;
while (stream->Read(&request))
{
//get the params
grpc::string mat = request.framemat();
logger->info(" Length of Bytes= {} , mat.length()}
Output was zero!
So I changed the client input to check with some char strings and sure enough the data length was coming as 4 at the server side; because this time it was a valid string and string length matched.
const char mat[12] = "sdsd";
Better way is to specify in the proto the data as well as the data length
message StreamBytes {
bytes data_bytes =1;
int32 data_length = 2;
};
My goal is to get this:
BYTE Data1[] = {0x6b,0x65,0x79};
BYTE Data2[] = {0x6D,0x65,0x73,0x73,0x61,0x67,0x65};
But my starting point is:
std::string msg = "message";
std::string key = "key";
I am not able to get from std::string to BYTE[].
I tried the following:
std::vector<BYTE> msgbytebuffer(msg.begin(), msg.end());
BYTE* Data1 = &msgbytebuffer[0];
This didn't cause compile or run time error. However, the end result (I feed this to a winapi function - crypto api) was not the same as when I used the actual byte array like in top most ({0x6D,0x65,0x73,0x73,0x61,0x67,0x65}).
You can use string::c_str() function which returns a pointer to c style string that can be passed to winapi functions like:
foo(string.c_str());
What it actually does is that it returns a pointer to an array that contains a null-terminated sequence of characters.
I suppose BYTE[] is actually a char array. You can assign your std::string to char array by doing:
std::string str = "hello";
BYTE byte[6]; // null terminated string;
strcpy(byte, str.c_str()); // copy from str to byte[]
If you want to copy the str without the 0 at the end, use strncpy instead:
BYTE byte[5];
strncpy(byte, str.c_str(), str.length());
Seems me that winapi is waiting a null terminated c-string. You can achieve that by using:
msg.c_str();
or, using your BYTE type, something like that:
std::vector<BYTE> msgbytebuffer(msg.length() + 1, 0);
std::copy(msg.begin(), msg.end(), msgbytebuffer.begin());
I'm trying to read by ReadFile but always get that its read 4 bytes, doesn't mutter how long was the string.
UART* uart = (UART*)lpParam;
char TempChar; //Temporary character used for reading
char SerialBuffer[256];//Buffer for storing Rxed Data
DWORD NoBytesRead;
int i = 0;
do
{
NoBytesRead = 0;
ReadFile(uart->connHandle, //Handle of the Serial port
&SerialBuffer, //Temporary character
sizeof(256),//Size of TempChar
&NoBytesRead, //Number of bytes read
NULL);
//SerialBuffer[i] = TempChar;// Store Tempchar into buffer
i++;
if (NoBytesRead > 0)
{
char* strMsg = (char*)malloc(sizeof(256 * sizeof(char)));
SerialBuffer[NoBytesRead] = '\0';
TRACE("read %d- %s\n", NoBytesRead,SerialBuffer);
strcpy_s(strMsg, 256,SerialBuffer);
ControllerPublishMsg(uart->controller, SerialBuffer);
}
SerialBuffer[0] = '\0';
In case i send string "hh" to connection I'm get output "read 4- hh".
The string is 2 bytes long, but NoBytesRead = 4.
thanks.
sizeof(256) defaults to sizeof(int) this is four bytes. replace sizeof(256) by 256. Also replace sizeof(256 * sizeof(char)) by (256 * sizeof(char)).
Think about the statement
sizeof(256)
that you pass as a buffer size.
That expression evaluates to the same thing as
sizeof(int)
which probably evaluates to 4 on your platform. You'd need to hand over the literal value 256 or better sizeof SerialBuffer to ReadFile.
And you got the same error in your malloc arguments.
Why you are receiving 4 characters when you (think you) are sending only 2 is impossible to see without the code on the sender side. In case ReadFile returns 4, it most probably received 4 characters. Due to the messed up buffer size argument, it will however not be able to receive more than 4 characters.
You are misusing sizeof.
When calling ReadFile(), you are using sizeof(256) as the number of bytes to read. A numeric literal is an int by default, so you are really using sizeof(int), which is 4 bytes on your compiler. Get rid of the sizeof and just use 256 by itself:
ReadFile(uart->connHandle, //Handle of the Serial port
&SerialBuffer, //Temporary character
256,//Size of TempChar
&NoBytesRead, //Number of bytes read
NULL);
Or better, get rid of the 256 and use sizeof(SerialBuffer) instead, since it is a static array with a fixed size known at compile time:
ReadFile(uart->connHandle, //Handle of the Serial port
&SerialBuffer, //Temporary character
sizeof(SerialBuffer),//Size of TempChar
&NoBytesRead, //Number of bytes read
NULL);
You are making a similar mistake when calling malloc(). sizeof(char) is always 1, so you are really calling sizeof(256) again. So again, you can get rid of sizeof and just use 256 by itself:
char* strMsg = (char*) malloc(256 * sizeof(char));
// or just: char* strMsg = (char*) malloc(256);
Although, you are not actually using strMsg for anything (and you are leaking it), so you should just get rid of it completely.
Try something more like this:
UART* uart = (UART*)lpParam;
char SerialBuffer[257];//Buffer for storing Rxed Data
DWORD NoBytesRead;
do
{
NoBytesRead = 0;
ReadFile(uart->connHandle, //Handle of the Serial port
SerialBuffer, //Temporary buffer
sizeof(SerialBuffer)-1,//Size of buffer minus null-terminator
&NoBytesRead, //Number of bytes read
NULL);
if (NoBytesRead > 0)
{
SerialBuffer[NoBytesRead] = '\0';
TRACE("read %u- %s\n", NoBytesRead, SerialBuffer);
ControllerPublishMsg(uart->controller, SerialBuffer);
}
I have a character buffer which I'm using to send messages over a network. I've serialized an integer using memcpy and so there are some null characters in the buffer. Currently, I'm declaring the buffer as a char array and packing the data from the structure m into it using my serialization routine
sendline = new char[256];
serialize(m, sendline);
void serialize(myMsg &m, char* out)
{
uint16_t seq = htons(m.seq);
memcpy(out, &m.type, sizeof(m.type));
memcpy(out + sizeof(m.type), &seq, sizeof(seq));
memcpy(out + sizeof(seq) + sizeof(m.type), m.data.c_str(), m.data.length());
}
My question is- can I use a string here instead of a char array? I tried making sendline a string, but it terminates the buffer on the first null character.
I have the following method that serialize my protocol buffer message and this works perfectly :
string DroolsMsgTransmission::serialize(const google::protobuf::Message* msg, const HeaderMsg& header)const
{
unsigned char buffer[20000];
google::protobuf::io::ArrayOutputStream arr(buffer, sizeof(buffer));
google::protobuf::io::CodedOutputStream output(&arr);
output.WriteVarint32(header.ByteSize());
header.SerializeToCodedStream(&output);
output.WriteVarint32(msg->ByteSize());
msg->SerializeToCodedStream(&output);
return string((char*)buffer, output.ByteCount());
}
Is it possible to use a dynamic buffer instead? I tried the following:
string DroolsMsgTransmission::serialize(const google::protobuf::Message* msg, const HeaderMsg& header)const
{
char* buffer = new char[header.ByteSize() + msg->ByteSize()]();
google::protobuf::io::ArrayOutputStream arr(buffer, sizeof(buffer));
google::protobuf::io::CodedOutputStream output(&arr);
output.WriteVarint32(header.ByteSize());
header.SerializeToCodedStream(&output);
output.WriteVarint32(msg->ByteSize());
msg->SerializeToCodedStream(&output);
string str = string(buffer);
delete buffer;
return str;
}
But this is not working. When I am trying the line above, the returned string does not contain the serialized data at all.
I also tried to use OstreamOutputStream instead of ArrayOutputStream, but no luck.
EDIT
Thanks to comments, I almost made it working :
string DroolsMsgTransmission::serialize(const google::protobuf::Message* msg, const HeaderMsg& header)const
{
char* buffer = new char[header.ByteSize() + msg->ByteSize()]();
google::protobuf::io::ArrayOutputStream arr(buffer, header.ByteSize() + msg->ByteSize());
google::protobuf::io::CodedOutputStream output(&arr);
output.WriteVarint32(header.ByteSize());
header.SerializeToCodedStream(&output);
output.WriteVarint32(msg->ByteSize());
msg->SerializeToCodedStream(&output);
string str = string(buffer ,output.ByteCount());
//return string((char*)buffer, output.ByteCount());
int toto = header.ByteSize() + msg->ByteSize();
int tata = output.ByteCount();
int titi = sizeof(buffer);
delete buffer;
return str;
}
What I did, I replaced this line
google::protobuf::io::ArrayOutputStream arr(buffer, sizeof(buffer));
by this line
google::protobuf::io::ArrayOutputStream arr(buffer, header.ByteSize() + msg->ByteSize());
I it better now, but I still have a problem where the returned string seems a little bit tuncated at the end. It might be related with WriteVarint32, but I don't understand. Somebody can explain why?
Thank you.
You're writing 4 things (the size of the header, the header, the size of the message, the message) but only allocating space for two of them (the header and message).
Hint: a Varint32 never takes more than 5 bytes.
(Also: you need the size in two places - when allocating the buffer and constructing arr. Compute it once and store it in a local variable.)