Is there a limit on the payload in MQTT paho library? - c

Anything over 600 bytes malforms the packet and it cannot be published. MQTTSerialize_publish (library) returns the correct amount of bytes for the payload however (eg. 1260).
I can't see any apparent limit in the code or the MQTT standard.
This is how i call the function
unsigned char bufm[1500];
int bufmlen = sizeof(bufm);
rc = MQTTSerialize_publish(bufm, sizeof(bufm), dup, qos, retained, msgid, topicString[0], message, messageLen);
I get this in my console for a particular payload:
messageLen=580
sizeof bufm=1500
rc=600
The payload (bufm) is transmitted fine.
For a different payload:
messageLen=638
sizeof bufm=1500
rc=658
And since the payload is larger than 600 bytes the payload (bufm) is now only 19 bytes and only contains some parts of the message array.
Notice how the rc is correct on both occasions.
Also there is enough memory where my pointer points to unsigned char bufm[1500];
---------------------------------EDIT---------------------------------
yup.....
It was a stack issue. My pointer was pointing to the stack...so stack overflow
Sorry and thanks for the help.
thanks

yup..... It was a stack issue. My pointer was pointing to the stack...so stack overflow
Sorry and thanks for the help.

Related

How can I possibly send this struct over network?

I've got the following struct:
struct fetch_info_t {
u_int8_t grocery_type;
u_int8_t arg[1024];
} __attribute__((packed));
I'd like to send this over a socket to a server, to request data. I'd very much like to avoid any libraries, such as protobuf.
grocery_type can be any value between 1 and 255. Some grocery types, say type 128, must provide additional information. I'ts not enough to provide type 128, I'd also like to provide Cheeses as a string. Having that said, type 129 must provide a number, u_int32_t and not a string, unlike 128.
Basically I've allocated 1024 bytes for the additional information the system may require. The question is, how do I send it over a socket, or more specifically, populate arg with the right information non-system-dependant? I know htonl on the number could be used, but how do I actually set the buffer value to that?
I'd imagine that the info sending would actually eventually be casting the struct pointer to unsigned char array and send it like that over a socket. Let me please know if there's a better way.
You cannot assign directly the 32-bit value to the array
because the correct alignment is not guaranteed.
memcpy() will just replicate the bytes with not alignment problem.
u_int32_t the_value=htonl( ... );
struct fetch_info_t the_info;
the_info.grocery_type=129;
memcpy(the_info.arg, &the_value, sizeof(the_value));
Then, because your structure is packed, you can send it with
send(my_socket, &the_info,
sizeof(the_info.grocery_type)+sizeof(the_value), 0);
In case you need to send a string
char *the_text= ... ;
size_t the_size=strlen(the_text)+1;
struct fetch_info_t the_info;
the_info.grocery_type=128;
memcpy(the_info.arg, the_text, the_size);
send(my_socket, &the_info,
sizeof(the_info.grocery_type)+the_size, 0);
Note that the '\0' is transmitted here.

How does this line separation make a different?

I was doing system programming in C on creating a server. There was a bug that caused serious issues that results cannot be returned correctly. I solved the issue by doing a line separation, but did not understand why this solved the issue.
Original code that caused serious issues:
int Bytes, Size = cache[index].len;
New code that solved the issue:
int Bytes = cache[index].len;
Size = Bytes;
What is the difference between my original code and new code? Are they not identical?
They're not identical at all. The first code:
int Bytes, Size = cache[index].len;
Declares two variables, Bytes and Size, both of type int; Size is initialized to the value of cache[index].len and Bytes is uninitialized (its value is indeterminate).
The second code (I'm inserting int in the second line to make it a declaration-with-initializer, since I'm assuming this is what you meant):
int Bytes = cache[index].len;
int Size = Bytes;
Declares the same two variables of the same type; but here, it is Bytes that is initialized to the value of cache[index].len and Bytes is then copied to Size.

Need help processing CHAR strings with printf

I'm using softserial to communicate with a bluetooth modem and I am pushing strings to the serial by using the following code:
char bt_string = "test";
bluetooth_println(bt_string);
I need to be able to replace the string with
printf(" Error: cmd=%02hX, res=%02hX\n", CMD_SEND_CID, res);
I have tried the following code
char bt_string;
sprintf(bt_string, " Error: cmd=%02hX, res=%02hX\n", CMD_SEND_CID, res);
bluetooth_println(bt_string);
But it fails to output anything. I'm obviously misunderstanding something. Thanks for any help.
You need to provide a buffer for your string.
char bt_string[256]; // <-- or any size that you are sure will be enough for what you will put in.
eventually, for safety you can use snpritf to avoid any buffer overflow:
#define MAX_BT_STRING 256
char bt_string[MAX_BT_STRING];
snprintf(bt_string, MAX_BT_STRING," Error: cmd=%02hX, res=%02hX\n", CMD_SEND_CID, res);
bluetooth_println(bt_string);
char *str and char str[] are distinctly different. Check this question for more details.
In your problem, you declared bt_string as const char *bt_string = "test", where bt_string is pointer which points to the first char in string "test". This string has a size of 5 bytes(don't forget the terminator \0);
In the next step:
sprintf(bt_string, " Error: cmd=%02hX, res=%02hX\n", CMD_SEND_CID, res);
You dump more than 5 bytes to bt_string which only has 5 bytes available space. The parts beyond 5 bytes will overwrite the contents after bt_string, which may lead to some serious situation or nothing, it depends on what is followed.
To settle this problem, you have to allocate enough memory space:
allocate on stack as A.S.H answered. the content is determined after function finished.
allocate via malloc;
use static key word to force the string stored either in BSS section or DATA section.

Invoking sendto() with wrong length

ssize_t sendto(int socket, const void *message, size_t length, int flags, const struct sockaddr *dest_addr, socklen_t dest_len);
In the above sendto() synopsis, 3rd field represents length which is ideally be the size of message being sent in bytes.
What if the length field is wrong and not equivalent to size of message ?
Will sendto() succeeds sending only length bytes mentioned. If yes, what happens if the length is bigger compared to real valid message size.
sendto() has no concept of the type of buffer you use for your messages. It only knows about the parameter values you give it, so it is your responsibility to make sure they are accurate.
If the length is smaller than the actual message, length number of bytes are sent for UDP, and up to length bytes are sent for TCP.
If the length is larger than the actual message, the behavior is undefined. At best, you will likely send random data from surrounding memory. At worse, you will crash your code when trying to send bytes from invalid memory.

How to get memory block length after malloc?

I thought that I couldn't retrieve the length of an allocated memory block like the simple .length function in Java. However, I now know that when malloc() allocates the block, it allocates extra bytes to hold an integer containing the size of the block. This integer is located at the beginning of the block; the address actually returned to the caller points to the location just past this length value. The problem is, I can't access that address to retrieve the block length.
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
char *str;
str = (char*) malloc(sizeof(char)*1000);
int *length;
length = str-4; /*because on 32 bit system, an int is 4 bytes long*/
printf("Length of str:%d\n", *length);
free(str);
}
**Edit:
I finally did it. The problem is, it keeps giving 0 as the length instead of the size on my system is because my Ubuntu is 64 bit. I changed str-4 to str-8, and it works now.
If I change the size to 2000, it produces 2017 as the length. However, when I change to 3000, it gives 3009. I am using GCC.
You don't have to track it by your self!
size_t malloc_usable_size (void *ptr);
But it returns the real size of the allocated memory block!
Not the size you passed to malloc!
What you're doing is definitely wrong. While it's almost certain that the word just before the allocated block is related to the size, even so it probably contains some additional flags or information in the unused bits. Depending on the implementation, this data might even be in the high bits, which would cause you to read the entirely wrong length. Also it's possible that small allocations (e.g. 1 to 32 bytes) are packed into special small-block pages with no headers, in which case the word before the allocated block is just part of another block and has no meaning whatsoever in relation to the size of the block you're examining.
Just stop this misguided and dangerous pursuit. If you need to know the size of a block obtained by malloc, you're doing something wrong.
I would suggest you create your own malloc wrapper by compiling and linking a file which defines my_malloc() and then overwiting the default as follows:
// my_malloc.c
#define malloc(sz) my_malloc(sz)
typedef struct {
size_t size;
} Metadata;
void *my_malloc(size_t sz) {
size_t size_with_header = sz + sizeof(Metadata);
void* pointer = malloc(size_with_header);
// cast the header into a Metadata struct
Metadata* header = (Metadata*)pointer;
header->size = sz;
// return the address starting after the header
// since this is what the user needs
return pointer + sizeof(Metadata);
}
then you can always retrieve the size allocated by subtracting sizeof(Metadata), casting that pointer to Metadata and doing metadata->size:
Metadata* header = (Metadata*)(ptr - sizeof(Metadata));
printf("Size allocated is:%lu", header->size); // don't quote me on the %lu ;-)
You're not supposed to do that. If you want to know how much memory you've allocated, you need to keep track of it yourself.
Looking outside the block of memory returned to you (before the pointer returned by malloc, or after that pointer + the number of bytes you asked for) will result in undefined behavior. It might work in practice for a given malloc implementation, but it's not a good idea to depend on that.
This is not Standard C. However, it is supposed to work on Windows operatings systems and might to be available on other operating systems such as Linux (msize?) or Mac (alloc_size?), as well.
size_t _msize( void *memblock );
_msize() returns the size of a memory block allocated in the heap.
See this link:
http://msdn.microsoft.com/en-us/library/z2s077bc.aspx
This is implementation dependent
Every block you're allocating is precedeed by a block descriptor. Problem is, it dependends on system architecture.
Try to find the block descriptor size for you own system. Try take a look at you system malloc man page.

Resources