extra 00 Is this Struct-Packing?

Hi,
I struggled with giving this an appropriate subject. :cold_sweat:

I am using the MQTTSN library for arduino for which the developer is AWOL. I have forked his/her lib and dug into the code to determine why this messaging protocol is not working.

To explain my problem I think I need to explain the MQTTSN protocol structure quickly:

There are many message types but the one I will use as exampleis the CONNECT msg that looks like this:
[length][Msg Type][flags][protocolId][duration][clientId] and the length of each msg part in bytes being
[ 1 ][ 1 ][ 1 ][ 1 ][ 2 ][ n ]
My CONNECT data sent on the wire should be (hex)
[ 0d ][ 04 ][ 24 ][ 01 ][ 2121 ][ 6d6f74653232 ]

However it is:

[ 0d ][ 04 ] 00 [ 24 ][ 01 ][ 2121 ][ 6d6f74653232 ]

and the decoding end [server ] for this msg cant recognise it cause things are not where they should be.

So the lib constructs the message this way:

defines a struct for the HEADER - first 2 parts of the message:

struct message_header {
    uint8_t length;
    message_type type;
};

then the CONNECT struct inherits from the HEADER struct [I think] adding four other msg parts:

struct msg_connect : public message_header {
    uint8_t flags;
    uint8_t protocol_id;
    uint16_t duration;
    char client_id[0];
};

The connect method is:

void MQTTSN::connect(const uint8_t flags, const uint16_t duration, const char* client_id) {
    msg_connect* msg = reinterpret_cast<msg_connect*>(message_buffer);

    msg->length = sizeof(msg_connect) + strlen(client_id);
    msg->type = CONNECT;
    msg->flags = flags;
    msg->protocol_id = PROTOCOL_ID;
    msg->duration = bswap(duration);
    strcpy(msg->client_id, client_id);

    send_message();
    waiting_for_response = true;
}

and send_message() is:

void MQTTSN::send_message() {
    message_header* hdr = reinterpret_cast<message_header*>(message_buffer);

#ifdef USE_RF12
    while (!rf12_canSend()) {
        rf12_recvDone();
        Sleepy::loseSomeTime(32);
    }
    rf12_sendStart(_gateway_id, message_buffer, hdr->length);
    rf12_sendWait(2);
#endif
#ifdef USE_SERIAL
    //Serial.print("mqttsn-messages:send_message: message_buffer=");
    //printByteA(message_buffer);
    Serial.write(message_buffer, hdr->length);
    Serial.flush();
#endif

    if (!waiting_for_response) {
        _response_timer = millis();
        _response_retries = N_RETRY;

        // Cheesy hack to ensure two messages don't run-on into one send.
//        delay(10);
    }
}

In this case we are using SERIAL and not RF12.
The sketch is:

#include <mqttsn.h>

MQTTSNHandlers mqttsn;
int slow;
  
uint8_t flagz;
uint16_t kat;
char* clientid;
//LED
int ledPin;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  ledPin = 13;      // default arduino uno LED
  pinMode(ledPin, OUTPUT); 
  
  slow=1000;
  flagz = FLAG_QOS_0;  //0x00
  kat = 4369;  //think this is 5 sec
  clientid= "mote22";

  mqttsn.connect(flagz, kat, clientid);
  delay(50);

  mqttsn.searchgw(0xff);

  delay(50);
}

So to me all looks good in the lib but I am beginner in arduino.
I cant understand why there is that extra 00 that get placed on the wire between the msgType and flag parts of the message [or if the 00 is on fact a part of either of those]

This happends for other message types as well that have the flags message part in them.

I tried googling for solution and changed the type of the flags from uint8_t to byte but this did not help.
I also tried to compile with the -fpacked-struct but with no success.

I am out of options and pulling my hair out :~ =( and though I would ask the experts here in this forum.

Code attached.

mqttsn02.ino (1.19 KB)

mqttsn.zip (10.4 KB)

Can you post the link to the library you forked?

It looks like the design is intended to be a variable sized structure, as it uses the GCC zero sized array hack, similar to C's flexible array member.

enum message_type {
...
struct message_header {
    uint8_t length;
    message_type type;
};

enums are two bytes. message_header needs to be this...

struct message_header {
    uint8_t length;
    uint8_t type;  // message_type
};

The code doesnt reside on a web repository yet but is all in the attached MQTTSN.zip file.

I subclassed (as mqttsn-handlers) the mqttsn-messages class. I also added includes [arduino.h] in the mqttsn.h so that it would compile on the arduino IDE.

Thanks

@CodingBadly: It works after making the changes you recommended!! Thank you so much for the help on this!! :smiley: :smiley: :smiley:
I should have just asked on this forum and not wasted 2 days trying different things on this.

If you were in Cape Town I would find you and buy you a beer!!!

Thanks again
XD

You are welcome.

If you were in Cape Town I would find you and buy you a beer!!!

Excellent. If I ever make it to Cape Town I'll send you a personal message.

Which reminds me. A few others have made similar offers. I probably should jot those down somewhere or I'll forget. Seriously, who would not want to dine on lobster with Ann Harrison while discussing DEC's RDB and three-phase commits!