diff --git a/src/MQTTSNConnect.h b/src/MQTTSNConnect.h index c108205..3a30c27 100644 --- a/src/MQTTSNConnect.h +++ b/src/MQTTSNConnect.h @@ -47,13 +47,28 @@ int MQTTSNDeserialize_pingreq(MQTTString* clientID, unsigned char* buf, int len) int MQTTSNSerialize_pingresp(unsigned char* buf, int buflen); int MQTTSNDeserialize_pingresp(unsigned char* buf, int buflen); -int MQTTSNSerialize_willtopicreq(unsigned char* buf, int buflen); -int MQTTSNDeserialize_willtopicreq(unsigned char* buf, int buflen); +int MQTTSNSerialize_willmsg(unsigned char* buf, int buflen, MQTTString willMsg); +int MQTTSNDeserialize_willmsg(MQTTString* willMsg, unsigned char* buf, int buflen); int MQTTSNSerialize_willmsgreq(unsigned char* buf, int buflen); int MQTTSNDeserialize_willmsgreq(unsigned char* buf, int buflen); +int MQTTSNSerialize_willmsgupd(unsigned char* buf, int buflen, MQTTString willMsg); +int MQTTSNDeserialize_willmsgupd(MQTTString* willMsg, unsigned char* buf, int buflen); + +int MQTTSNSerialize_willmsgresp(unsigned char* buf, int buflen, int resp_rc); +int MQTTSNDeserialize_willmsgresp(int* resp_rc, unsigned char* buf, int buflen); + int MQTTSNSerialize_willtopic(unsigned char* buf, int buflen, int willQoS, int willRetain, MQTTString willTopic); +int MQTTSNDeserialize_willtopic(int *willQoS, int *willRetain, MQTTString* willTopic, unsigned char* buf, int buflen); + +int MQTTSNSerialize_willtopicreq(unsigned char* buf, int buflen); +int MQTTSNDeserialize_willtopicreq(unsigned char* buf, int buflen); + int MQTTSNSerialize_willtopicupd(unsigned char* buf, int buflen, int willQoS, int willRetain, MQTTString willTopic); +int MQTTSNDeserialize_willtopicupd(int *willQoS, int *willRetain, MQTTString* willTopic, unsigned char* buf, int buflen); + +int MQTTSNSerialize_willtopicresp(unsigned char* buf, int buflen, int resp_rc); +int MQTTSNDeserialize_willtopicresp(int* resp_rc, unsigned char* buf, int buflen); #endif /* MQTTSNCONNECT_H_ */ diff --git a/src/MQTTSNConnectClient.c b/src/MQTTSNConnectClient.c index 357a06b..f19d13d 100644 --- a/src/MQTTSNConnectClient.c +++ b/src/MQTTSNConnectClient.c @@ -287,7 +287,7 @@ int MQTTSNSerialize_willtopic(unsigned char* buf, int buflen, int willQoS, int w /** * Serializes a willmsg or willmsgupd packet into the supplied buffer. * @param buf the buffer into which the packet will be serialized - * @param len the length in bytes of the supplied buffersage + * @param buflen the length in bytes of the supplied buffer * @param willMsg the will message * @return serialized length, or error if 0 */ @@ -411,5 +411,67 @@ exit: } +/** + * Deserializes the supplied (wire) buffer into willtopicresp data - return code + * @param connack_rc returned integer value of the return code + * @param buf the raw buffer data, of the correct length determined by the remaining length field + * @param len the length in bytes of the data in the supplied buffer + * @return error code. 1 is success, 0 is failure + */ +int MQTTSNDeserialize_willtopicresp(int* resp_rc, unsigned char* buf, int buflen) +{ + unsigned char* curdata = buf; + unsigned char* enddata = NULL; + int rc = 0; + int mylen; + + FUNC_ENTRY; + curdata += (rc = MQTTSNPacket_decode(curdata, buflen, &mylen)); /* read length */ + enddata = buf + mylen; + if (enddata - buf < 3) + goto exit; + + if (readChar(&curdata) != MQTTSN_WILLTOPICRESP) + goto exit; + + *resp_rc = readChar(&curdata); + + rc = 1; +exit: + FUNC_EXIT_RC(rc); + return rc; +} + + +/** + * Deserializes the supplied (wire) buffer into willmsgresp data - return code + * @param connack_rc returned integer value of the return code + * @param buf the raw buffer data, of the correct length determined by the remaining length field + * @param len the length in bytes of the data in the supplied buffer + * @return error code. 1 is success, 0 is failure + */ +int MQTTSNDeserialize_willmsgresp(int* resp_rc, unsigned char* buf, int buflen) +{ + unsigned char* curdata = buf; + unsigned char* enddata = NULL; + int rc = 0; + int mylen; + + FUNC_ENTRY; + curdata += (rc = MQTTSNPacket_decode(curdata, buflen, &mylen)); /* read length */ + enddata = buf + mylen; + if (enddata - buf < 3) + goto exit; + + if (readChar(&curdata) != MQTTSN_WILLMSGRESP) + goto exit; + + *resp_rc = readChar(&curdata); + + rc = 1; +exit: + FUNC_EXIT_RC(rc); + return rc; +} diff --git a/src/MQTTSNConnectServer.c b/src/MQTTSNConnectServer.c index c36e5b7..dfaa831 100644 --- a/src/MQTTSNConnectServer.c +++ b/src/MQTTSNConnectServer.c @@ -84,7 +84,7 @@ int MQTTSNSerialize_connack(unsigned char* buf, int buflen, int connack_rc) goto exit; } - ptr += MQTTSNPacket_encode(ptr, 4); /* write length */ + ptr += MQTTSNPacket_encode(ptr, 3); /* write length */ writeChar(&ptr, MQTTSN_CONNACK); writeChar(&ptr, connack_rc); @@ -246,3 +246,185 @@ exit: FUNC_EXIT_RC(rc); return rc; } + + +/** + * Deserializes the supplied (wire) buffer into willtopic or willtopicupd data structure + * @param data the connect data structure to be filled out + * @param buf the raw buffer data, of the correct length determined by the remaining length field + * @param len the length in bytes of the data in the supplied buffer + * @return error code. 1 is success, 0 is failure + */ +int MQTTSNDeserialize_willtopic1(int *willQoS, int *willRetain, MQTTString* willTopic, unsigned char* buf, int len, + enum MQTTSN_msgTypes packet_type) +{ + MQTTSNFlags flags; + unsigned char* curdata = buf; + unsigned char* enddata = &buf[len]; + int rc = 0; + int mylen = 0; + + FUNC_ENTRY; + curdata += (rc = MQTTSNPacket_decode(curdata, len, &mylen)); /* read length */ + enddata = buf + mylen; + if (enddata > buf + len) + goto exit; + + if (readChar(&curdata) != packet_type) + goto exit; + + flags.all = readChar(&curdata); + *willQoS = flags.bits.QoS; + *willRetain = flags.bits.retain; + + if (!readMQTTSNString(willTopic, &curdata, enddata)) + goto exit; + + rc = 1; +exit: + FUNC_EXIT_RC(rc); + return rc; +} + + +/** + * Deserializes the supplied (wire) buffer into willtopic data structure + * @param data the connect data structure to be filled out + * @param buf the raw buffer data, of the correct length determined by the remaining length field + * @param len the length in bytes of the data in the supplied buffer + * @return error code. 1 is success, 0 is failure + */ +int MQTTSNDeserialize_willtopic(int *willQoS, int *willRetain, MQTTString* willTopic, unsigned char* buf, int len) +{ + return MQTTSNDeserialize_willtopic1(willQoS, willRetain, willTopic, buf, len, MQTTSN_WILLTOPIC); +} + +/** + * Deserializes the supplied (wire) buffer into willtopic data structure + * @param data the connect data structure to be filled out + * @param buf the raw buffer data, of the correct length determined by the remaining length field + * @param len the length in bytes of the data in the supplied buffer + * @return error code. 1 is success, 0 is failure + */ +int MQTTSNDeserialize_willtopicupd(int *willQoS, int *willRetain, MQTTString* willTopic, unsigned char* buf, int len) +{ + return MQTTSNDeserialize_willtopic1(willQoS, willRetain, willTopic, buf, len, MQTTSN_WILLTOPICUPD); +} + + +/** + * Deserializes the supplied (wire) buffer into willmsg or willmsgupd data + * @param willMsg the will message to be retrieved + * @param buf the raw buffer data, of the correct length determined by the remaining length field + * @param len the length in bytes of the data in the supplied buffer + * @return error code. 1 is success, 0 is failure + */ +int MQTTSNDeserialize_willmsg1(MQTTString* willMsg, unsigned char* buf, int len, enum MQTTSN_msgTypes packet_type) +{ + unsigned char* curdata = buf; + unsigned char* enddata = &buf[len]; + int rc = 0; + int mylen = 0; + + FUNC_ENTRY; + curdata += (rc = MQTTSNPacket_decode(curdata, len, &mylen)); /* read length */ + enddata = buf + mylen; + if (enddata > buf + len) + goto exit; + + if (readChar(&curdata) != packet_type) + goto exit; + + if (!readMQTTSNString(willMsg, &curdata, enddata)) + goto exit; + + rc = 1; +exit: + FUNC_EXIT_RC(rc); + return rc; +} + + +/** + * Deserializes the supplied (wire) buffer into willmsg data + * @param willMsg the will message to be retrieved + * @param buf the raw buffer data, of the correct length determined by the remaining length field + * @param len the length in bytes of the data in the supplied buffer + * @return error code. 1 is success, 0 is failure + */ +int MQTTSNDeserialize_willmsg(MQTTString* willMsg, unsigned char* buf, int len) +{ + return MQTTSNDeserialize_willmsg1(willMsg, buf, len, MQTTSN_WILLMSG); +} + +/** + * Deserializes the supplied (wire) buffer into willmsgupd data + * @param willMsg the will message to be retrieved + * @param buf the raw buffer data, of the correct length determined by the remaining length field + * @param len the length in bytes of the data in the supplied buffer + * @return error code. 1 is success, 0 is failure + */ +int MQTTSNDeserialize_willmsgupd(MQTTString* willMsg, unsigned char* buf, int len) +{ + return MQTTSNDeserialize_willmsg1(willMsg, buf, len, MQTTSN_WILLMSGUPD); +} + + +/** + * Serializes the willtopicresp packet into the supplied buffer. + * @param buf the buffer into which the packet will be serialized + * @param buflen the length in bytes of the supplied buffer + * @param rc the integer return code to be used + * @return serialized length, or error if 0 + */ +int MQTTSNSerialize_willtopicresp(unsigned char* buf, int buflen, int resp_rc) +{ + int rc = 0; + unsigned char *ptr = buf; + + FUNC_ENTRY; + if (buflen < 3) + { + rc = MQTTSNPACKET_BUFFER_TOO_SHORT; + goto exit; + } + + ptr += MQTTSNPacket_encode(ptr, 3); /* write length */ + writeChar(&ptr, MQTTSN_WILLTOPICRESP); + writeChar(&ptr, resp_rc); + + rc = ptr - buf; +exit: + FUNC_EXIT_RC(rc); + return rc; +} + + +/** + * Serializes the willmsgresp packet into the supplied buffer. + * @param buf the buffer into which the packet will be serialized + * @param buflen the length in bytes of the supplied buffer + * @param rc the integer return code to be used + * @return serialized length, or error if 0 + */ +int MQTTSNSerialize_willmsgresp(unsigned char* buf, int buflen, int resp_rc) +{ + int rc = 0; + unsigned char *ptr = buf; + + FUNC_ENTRY; + if (buflen < 3) + { + rc = MQTTSNPACKET_BUFFER_TOO_SHORT; + goto exit; + } + + ptr += MQTTSNPacket_encode(ptr, 3); /* write length */ + writeChar(&ptr, MQTTSN_WILLMSGRESP); + writeChar(&ptr, resp_rc); + + rc = ptr - buf; +exit: + FUNC_EXIT_RC(rc); + return rc; +} diff --git a/src/MQTTSNPacket.h b/src/MQTTSNPacket.h index 1dae284..743295a 100644 --- a/src/MQTTSNPacket.h +++ b/src/MQTTSNPacket.h @@ -142,8 +142,6 @@ int readMQTTSNString(MQTTString* mqttstring, unsigned char** pptr, unsigned char void writeCString(unsigned char** pptr, char* string); void writeMQTTSNString(unsigned char** pptr, MQTTString mqttstring); -int MQTTDeserialize_ack(int* type, int* dup, int* packetid, char* buf, int buflen); - int MQTTSNPacket_read(unsigned char* buf, int buflen, int (*getfn)(unsigned char*, size_t)); #ifdef __cplusplus /* If this is a C++ compiler, use C linkage */ diff --git a/test/test1.c b/test/test1.c index cf5b4a5..f72c9f1 100644 --- a/test/test1.c +++ b/test/test1.c @@ -497,8 +497,73 @@ int test3(struct Options options) rc = MQTTSNDeserialize_willmsgreq(buf, rc); assert("good rc from deserialize willmsgreq", rc == 1, "rc was %d\n", rc); + memset(buf, '\0', sizeof(buf)); + int willQoS = 1, willRetain = 1, willQoS1 = 0, willRetain1 = 0; + MQTTString willTopic = MQTTString_initializer, willTopic1 = MQTTString_initializer; + willTopic.cstring = "a will topic"; + rc = MQTTSNSerialize_willtopic(buf, buflen, willQoS, willRetain, willTopic); + assert("good rc from serialize willtopic", rc > 0, "rc was %d\n", rc); + + rc = MQTTSNDeserialize_willtopic(&willQoS1, &willRetain1, &willTopic1, buf, rc); + assert("good rc from deserialize willtopic", rc == 1, "rc was %d\n", rc); + assert("willQoSs are the same", willQoS == willQoS1, "willQoS1 was %d\n", willQoS1); + assert("willRetains are the same", willRetain == willRetain1, "willRetain1 was %d\n", willRetain1); + assert("willTopics are the same", checkMQTTStrings(willTopic, willTopic1), "willTopic1 was %.s\n", willTopic1.lenstring.data); + + memset(buf, '\0', sizeof(buf)); + willQoS = 2; willRetain = 1; willQoS1 = 0; willRetain1 = 0; + MQTTString initTopic = MQTTString_initializer; + memcpy(&willTopic, &initTopic, sizeof(initTopic)); + memcpy(&willTopic1, &initTopic, sizeof(initTopic)); + willTopic.cstring = "a will topic update"; + rc = MQTTSNSerialize_willtopicupd(buf, buflen, willQoS, willRetain, willTopic); + assert("good rc from serialize willtopicupd", rc > 0, "rc was %d\n", rc); + + rc = MQTTSNDeserialize_willtopicupd(&willQoS1, &willRetain1, &willTopic1, buf, rc); + assert("good rc from deserialize willtopicupd", rc == 1, "rc was %d\n", rc); + assert("willQoSs are the same", willQoS == willQoS1, "willQoS1 was %d\n", willQoS1); + assert("willRetains are the same", willRetain == willRetain1, "willRetain1 was %d\n", willRetain1); + assert("willTopics are the same", checkMQTTStrings(willTopic, willTopic1), "willTopic1 was %.s\n", willTopic1.lenstring.data); + + memset(buf, '\0', sizeof(buf)); + MQTTString willMsg = MQTTString_initializer, willMsg1 = MQTTString_initializer; + willMsg.cstring = "a will message"; + rc = MQTTSNSerialize_willmsg(buf, buflen, willMsg); + assert("good rc from serialize willmsg", rc > 0, "rc was %d\n", rc); + + rc = MQTTSNDeserialize_willmsg(&willMsg1, buf, rc); + assert("good rc from deserialize willmsg", rc == 1, "rc was %d\n", rc); + assert("willMsgs are the same", checkMQTTStrings(willMsg, willMsg1), "willMsg1 was %.s\n", willMsg1.lenstring.data); + + memset(buf, '\0', sizeof(buf)); + memcpy(&willMsg, &initTopic, sizeof(initTopic)); + memcpy(&willMsg1, &initTopic, sizeof(initTopic)); + willMsg.cstring = "a will message"; + rc = MQTTSNSerialize_willmsgupd(buf, buflen, willMsg); + assert("good rc from serialize willmsgupd", rc > 0, "rc was %d\n", rc); + + rc = MQTTSNDeserialize_willmsgupd(&willMsg1, buf, rc); + assert("good rc from deserialize willmsgupd", rc == 1, "rc was %d\n", rc); + assert("willMsgs are the same", checkMQTTStrings(willMsg, willMsg1), "willMsg1 was %.s\n", willMsg1.lenstring.data); + + int resp_rc = 33, resp_rc2 = 0; + rc = MQTTSNSerialize_willmsgresp(buf, buflen, resp_rc); + assert("good rc from serialize willmsgresp", rc > 0, "rc was %d\n", rc); + + rc = MQTTSNDeserialize_willmsgresp(&resp_rc2, buf, buflen); + assert("good rc from deserialize willmsgresp", rc == 1, "rc was %d\n", rc); + assert("resp rcs should be the same", resp_rc == resp_rc2, "resp rcs were different %d\n", resp_rc2); + + resp_rc = 67, resp_rc2 = 0; + rc = MQTTSNSerialize_willtopicresp(buf, buflen, resp_rc); + assert("good rc from serialize willmsgresp", rc > 0, "rc was %d\n", rc); + + rc = MQTTSNDeserialize_willtopicresp(&resp_rc2, buf, buflen); + assert("good rc from deserialize willmsgresp", rc == 1, "rc was %d\n", rc); + assert("resp rcs should be the same", resp_rc == resp_rc2, "resp rcs were different %d\n", resp_rc2); + /* exit: */ - MyLog(LOGA_INFO, "TEST1: test %s. %d tests run, %d failures.", + MyLog(LOGA_INFO, "TEST3: test %s. %d tests run, %d failures.", (failures == 0) ? "passed" : "failed", tests, failures); write_test_result(); return failures;