I have a function like this
void UnitTestWorker::constructTestPayload(QByteArray &payload)
{
QString List = "127.0.0.1";
unsigned short Port = 12344;
unsigned int RequestId = 1;
memcpy(payload.data(),reinterpret_cast<char*>Port,sizeof(Port));
memcpy(payload.data()+sizeof(Port),reinterpret_cast<char*>RequestId ,sizeof(RequestId ));
}
But I am getting access violation error, it seems like I can't do something like reinterpret_cast<char*>Port or reinterpret_cast<char*>RequestId.
You have to ensure that QByteArray &payload has a sufficient size to receive the data you byte copy to it:
if (payload.size()<sizeof(Port)+sizeof(RequestId))
throw exception ("Ouch !! payload too small");
memcpy(payload.data(),reinterpret_cast<char*>(&Port),sizeof(Port));
memcpy(payload.data()+sizeof(Port),reinterpret_cast<char*>(&RequestId) ,sizeof(RequestId ));
Related
I'm trying to deserialize a Json object using the ArduinoJson 6 library. The object is passing through a mqtt callback using the PubSubClient library. The payload contains the following example: "{\"action\":\"message\",\"amount\":503}" but I am unable to retrieve the amount value. Only zeros are returned when using the following:
void messageReceived(char *topic, byte *payload, unsigned int length)
{
DynamicJsonDocument doc(1024);
deserializeJson(doc, payload, length);
const int results = doc["amount"];
Serial.print(results);
}
This works and returns 503 as needed:
DynamicJsonDocument doc(1024);
char json[] = "{\"action\":\"message\",\"amount\":503}";
deserializeJson(doc, json);
const int results = doc["amount"];
Serial.print(results);
I see the results of the payload when I use the following method:
void messageReceived(char *topic, byte *payload, unsigned int length)
{
for (unsigned int i = 0; i < length; i++)
{
Serial.print((char)payload[i]);
}
}
What is preventing me from being able to parse out the amount value from the first method?
When programming in C++, it always need to be aware the type of data that you are dealing with. The payload is a byte array, which is not what deserializeJson(doc, payload, length); is expecting, see the function signature of deserializeJson().
void messageReceived(char *topic, byte *payload, unsigned int length)
{
DynamicJsonDocument doc(128);
deserializeJson(doc, (char*) payload, length);
Serial.print(doc["amount"]);
}
Update & resolution:
The first method in my original post worked fine once I fixed the data that was being sent from the Lambda function to the IOT side. (Something I didn't include in my original question and didn't think it was relevant. Turns out it was.) Here is a snippet from the Lambda function that is receiving the data. The issue was that the data was being sent as a string and not parsed. Once I stringified the response and then parsed the output, it worked. Thank you #hcheung for the assistance and helpful info. Your suggestion works as well but only after I fixed the Lambda function.
async function sendToIOT(response) {
const data = JSON.stringify(response);
const iotResponseParams = {
topic: 'mythingname/subscribe',
payload: JSON.parse(data)
};
return iotdata.publish(iotResponseParams).promise()
}
So I'm using gRPC to store data in a key-value store.
The protos look like this:
syntax = "proto3";
package keyvaluestore;
service KeyValueStore {
rpc AddUser(Credentials) returns (Response) {}
rpc Get(Request) returns (Response) {}
rpc Put(Request) returns (Response) {}
rpc Cput(Request) returns (Response) {}
rpc Delete(Request) returns (Response) {}
}
message Credentials {
string user = 1;
string passwd = 2;
}
message Request {
string user = 1;
string key = 2;
bytes val = 3;
bytes val2 = 4;
string addr = 5;
string command = 6;
}
message Response {
bytes val = 1;
uint32 nbytes = 2;
string message = 3;
}
Right now, the issue is that if we send over say, an image as byte data which can include the null byte, then when the server receives it in the Request object, it treats it as a string; when it does this it only reads it up the the first null byte.
How we pack the Request object on the client side:
bool KeyValueStoreClient::Put(const string& user, const string& key, const char* val) {
Request req;
req.set_user(user);
req.set_key(key);
req.set_val(val);
ClientContext ctx;
Response res;
Status status = stub_->Put(&ctx, req, &res);
}
Server receives req->val() as a string instead of char*:
Status KeyValueStoreServiceImpl::Put(ServerContext* ctx, const Request* req, Response* res) {
// req->val() is a string
}
In your method Put the val argument is a const char*, not a std::string.
Protobuf documentation for C++ generated code (i.e., the interface to your messages) says that when setting a value using a const char* (the void set_foo(const char* value) overload) it uses the first \0 as a terminator.
Tell it the size explicitly by using the void set_foo(const char* value, int size) overload.
So I'm currently working on a web service for Amazon Alexa.
For their request authentication, I'm downloading and validating a certificate. Afterwards I shall decrypt a signature with the certificate's public key.
Now I've tried some things with Poco and OpenSSL, never getting a fitting result.
One example as a try for OpenSSL:
void decryptWithPublicKey(const std::string & input, const std::shared_ptr<Poco::Crypto::X509Certificate> & cert, std::string & buffer)
{
RSA * decryptor = Poco::Crypto::RSAKey(*key).impl()->getRSA();
const unsigned char * from = (const unsigned char*) input.c_str();
unsigned char* to = new unsigned char[ RSA_size(decryptor)-12 ];;
int result = RSA_public_decrypt((int) input.length(), from, to, decryptor, RSA_PKCS1_PADDING);
if(result == -1)
{
// print error
}
else
{
buffer.append((char*) to);
}
delete from;
delete[] to;
}
Output is always sth like "0!0 +\n PuTTYPuTTY"
Anyone has any experience with that?
I have a sample signature generator in C which will create a hash message <count:mac-addr> and generate a signature.
When I use char *message = "120:08:00:27:7c:b6:18";
and sign, the signature is verified successfully.
But when I use
char * generate_hash()
{
xmlDoc *document;
xmlNode *root, *first_child, *node;
char *filename;
char *ap_count;
char *ap_mac_address;
char *message;
filename = "/license.xml";
document = xmlReadFile(filename, NULL, 0);
root = xmlDocGetRootElement(document);
first_child = root->children;
for (node = first_child; node; node = node->next) {
if ( strcmp((char*)node->name, "ap_count") == 0 ) {
ap_count = (char*)xmlNodeGetContent(node);
}
if ( strcmp((char*)node->name, "ap_mac_address") == 0 ){
ap_mac_address = (char*)xmlNodeGetContent(node);
}
}
message = (char *) malloc(strlen(ap_count)+ strlen(ap_mac_address) +1 );
memset(message,0x0,(1 + strlen(ap_count)+ strlen(ap_mac_address)));
strcpy(message,ap_count);
strcat(message,":");
strcat(message,ap_mac_address);
printf(" %d \n", (1 + strlen(ap_count)+ strlen(ap_mac_address)));
return message;
}
--- while verifying,
char* message;
message = generate_hash();
I am using the below function call to generate the signature in both the cases.
if(RSA_sign(NID_sha256, (unsigned char*) message, strlen(message),
signature, &slen, private_key) != 1) {
ERR_print_errors_fp(stdout);
return 1;
}
The signature verification fails with this above procedure. Not sure what I am doing wrong here.
Below is the call I am using to verify the same.
verified = RSA_verify(NID_sha256, (unsigned char*) message,
strlen(message), sign, file_len, public_key);
verified = RSA_verify(NID_sha256, (unsigned char*) message,
strlen(message), sign, file_len, public_key);
The signature could have an embedded NULL. Do not treat it like string data, and don't use strlen on it.
You have to manage a pointer and an explicit length.
The description of RSA_verify tells following:
RSA_verify() verifies that the signature sigbuf of size siglen matches
a given message digest m of size m_len. type denotes the message
digest algorithm that was used to generate the signature. rsa is the
signer's public key.
So, using RSA_verify with original message is not correct: message digest should be used instead.
I'm working with libuv (https://github.com/joyent/libuv) and nodejs v12. I I write native module, in this module i have struct:
struct Work_req
{
const char *data;
size_t data_length;
Isolate* isolate;
unsigned int callback_id;
Persistent<Function> callback;
};
Then i try to pass this structure to work:
Work_req* request = new Work_req;
request->data = buf->base;
request->data_length = (size_t)nread;
request->isolate = env->isolate();
request->callback_id = callback_id->ToNumber()->Value();
uv_work_t *req = new uv_work_t;
req->data = request;
uv_queue_work(env->event_loop(), req, findCallback, after_findCallback);
In the end of this code i passed work to loop and all is ok.
But when i'm trying to read data from uv_work_t *req in findCallback function, i get strange symbols there:
Work_req *s = ((struct Work_req*)req->data);
printf(s>data); //print char array from structure here
I see something like this:
����g�Kack_id":1,"error":null,"response":{"type":"test"}}�����
How i can fix it?
Thanks a lot.