From ddfd3233bdcea565a091a6df88b2fa2a6808d06f Mon Sep 17 00:00:00 2001 From: Ian Craggs Date: Tue, 15 Jul 2014 17:02:58 +0100 Subject: [PATCH] Register and regack --- src/MQTTSNDeserializePublish.c | 77 ++++++++++++++++++++++++++++++ src/MQTTSNPublish.h | 10 ++++ src/MQTTSNSerializePublish.c | 86 ++++++++++++++++++++++++++++++++++ test/test1.c | 73 +++++++++++++++++++++++++++-- 4 files changed, 241 insertions(+), 5 deletions(-) diff --git a/src/MQTTSNDeserializePublish.c b/src/MQTTSNDeserializePublish.c index b654314..c2b6053 100644 --- a/src/MQTTSNDeserializePublish.c +++ b/src/MQTTSNDeserializePublish.c @@ -146,3 +146,80 @@ exit: FUNC_EXIT_RC(rc); return rc; } + + +/** + * Deserializes the supplied (wire) buffer into register data + * @param topicid returned topic id + * @param packetid returned integer - the MQTT packet identifier + * @param topicName returned MQTTString - the MQTT topic in the register + * @param buf the raw buffer data, of the correct length determined by the remaining length field + * @param buflen the length in bytes of the data in the supplied buffer + * @return error code. 1 is success + */ +int MQTTSNDeserialize_register(unsigned short* topicid, unsigned short* packetid, MQTTString* topicname, + unsigned char* buf, int buflen) +{ + unsigned char* curdata = buf; + unsigned char* enddata = NULL; + int rc = 0; + int mylen = 0; + + FUNC_ENTRY; + curdata += (rc = MQTTSNPacket_decode(curdata, buflen, &mylen)); /* read length */ + enddata = buf + mylen; + if (enddata - curdata > buflen) + goto exit; + + if (readChar(&curdata) != MQTTSN_REGISTER) + goto exit; + + *topicid = readInt(&curdata); + *packetid = readInt(&curdata); + + topicname->lenstring.data = (char*)curdata; + topicname->lenstring.len = enddata - curdata; + topicname->cstring = NULL; + + rc = 1; +exit: + FUNC_EXIT_RC(rc); + return rc; +} + + +/** + * Deserializes the supplied (wire) buffer into register data + * @param topicid returned topic id + * @param packetid returned integer - the MQTT packet identifier + * @param return_code returned integer return code + * @param buf the raw buffer data, of the correct length determined by the remaining length field + * @param buflen the length in bytes of the data in the supplied buffer + * @return error code. 1 is success + */ +int MQTTSNDeserialize_regack(unsigned short* topicid, unsigned short* packetid, unsigned char* return_code, + unsigned char* buf, int buflen) +{ + unsigned char* curdata = buf; + unsigned char* enddata = NULL; + int rc = 0; + int mylen = 0; + + FUNC_ENTRY; + curdata += (rc = MQTTSNPacket_decode(curdata, buflen, &mylen)); /* read length */ + enddata = buf + mylen; + if (enddata - curdata > buflen) + goto exit; + + if (readChar(&curdata) != MQTTSN_REGACK) + goto exit; + + *topicid = readInt(&curdata); + *packetid = readInt(&curdata); + *return_code = readChar(&curdata); + + rc = 1; +exit: + FUNC_EXIT_RC(rc); + return rc; +} diff --git a/src/MQTTSNPublish.h b/src/MQTTSNPublish.h index ca9a94b..ded7fdf 100644 --- a/src/MQTTSNPublish.h +++ b/src/MQTTSNPublish.h @@ -33,4 +33,14 @@ int MQTTSNSerialize_pubcomp(unsigned char* buf, int buflen, unsigned short packe int MQTTSNDeserialize_ack(unsigned char* packettype, unsigned short* packetid, unsigned char* buf, int buflen); +int MQTTSNSerialize_register(unsigned char* buf, int buflen, unsigned short topicid, unsigned short packetid, + MQTTString* topicname); +int MQTTSNDeserialize_register(unsigned short* topicid, unsigned short* packetid, MQTTString* topicname, + unsigned char* buf, int buflen); + +int MQTTSNSerialize_regack(unsigned char* buf, int buflen, unsigned short topicid, unsigned short packetid, + unsigned char return_code); +int MQTTSNDeserialize_regack(unsigned short* topicid, unsigned short* packetid, unsigned char* return_code, + unsigned char* buf, int buflen); + #endif /* MQTTSNPUBLISH_H_ */ diff --git a/src/MQTTSNSerializePublish.c b/src/MQTTSNSerializePublish.c index 45da30e..16e2528 100644 --- a/src/MQTTSNSerializePublish.c +++ b/src/MQTTSNSerializePublish.c @@ -203,3 +203,89 @@ int MQTTSNSerialize_pubcomp(unsigned char* buf, int buflen, unsigned short packe { return MQTTSNSerialize_ack(buf, buflen, MQTTSN_PUBCOMP, 0, packetid); } + + +/** + * Determines the length of the MQTT register packet that would be produced using the supplied parameters + * @param topicnamelen the length of the topic name to be used in the register + * @return the length of buffer needed to contain the serialized version of the packet + */ +int MQTTSNSerialize_registerLength(int topicnamelen) +{ + return topicnamelen + 5; +} + +/** + * Serializes the supplied register data into the supplied buffer, ready for sending + * @param buf the buffer into which the packet will be serialized + * @param buflen the length in bytes of the supplied buffer + * @param topicid if sent by a gateway, contains the id for the topicname, otherwise 0 + * @param packetid integer - the MQTT packet identifier + * @param topicname null-terminated topic name string + * @return the length of the serialized data. <= 0 indicates error + */ +int MQTTSNSerialize_register(unsigned char* buf, int buflen, unsigned short topicid, unsigned short packetid, + MQTTString* topicname) +{ + unsigned char *ptr = buf; + int len = 0; + int rc = 0; + int topicnamelen = 0; + + FUNC_ENTRY; + topicnamelen = (topicname->cstring) ? strlen(topicname->cstring) : topicname->lenstring.len; + if ((len = MQTTSNPacket_len(MQTTSNSerialize_registerLength(topicnamelen))) > buflen) + { + rc = MQTTSNPACKET_BUFFER_TOO_SHORT; + goto exit; + } + ptr += MQTTSNPacket_encode(ptr, len); /* write length */ + writeChar(&ptr, MQTTSN_REGISTER); /* write message type */ + + writeInt(&ptr, topicid); + writeInt(&ptr, packetid); + + memcpy(ptr, (topicname->cstring) ? topicname->cstring : topicname->lenstring.data, topicnamelen); + ptr += topicnamelen; + + rc = ptr - buf; +exit: + FUNC_EXIT_RC(rc); + return rc; +} + + +/** + * Serializes the supplied register data into the supplied buffer, ready for sending + * @param buf the buffer into which the packet will be serialized + * @param buflen the length in bytes of the supplied buffer + * @param topicid if sent by a gateway, contains the id for the topicname, otherwise 0 + * @param packetid integer - the MQTT packet identifier + * @param return_code integer return code + * @return the length of the serialized data. <= 0 indicates error + */ +int MQTTSNSerialize_regack(unsigned char* buf, int buflen, unsigned short topicid, unsigned short packetid, + unsigned char return_code) +{ + unsigned char *ptr = buf; + int len = 0; + int rc = 0; + + FUNC_ENTRY; + if ((len = MQTTSNPacket_len(6)) > buflen) + { + rc = MQTTSNPACKET_BUFFER_TOO_SHORT; + goto exit; + } + ptr += MQTTSNPacket_encode(ptr, len); /* write length */ + writeChar(&ptr, MQTTSN_REGACK); /* write message type */ + + writeInt(&ptr, topicid); + writeInt(&ptr, packetid); + writeChar(&ptr, return_code); + + rc = ptr - buf; +exit: + FUNC_EXIT_RC(rc); + return rc; +} diff --git a/test/test1.c b/test/test1.c index 10eb42f..5f4983c 100644 --- a/test/test1.c +++ b/test/test1.c @@ -645,10 +645,10 @@ int test5(struct Options options) unsigned short packetid2 = 2223; MQTTSN_topicid topicFilter2; - fprintf(xml, " 0, "rc was %d\n", rc); @@ -751,7 +751,7 @@ int test8(struct Options options) fprintf(xml, " 0, "rc was %d\n", rc); @@ -769,13 +769,76 @@ int test8(struct Options options) } +int test9(struct Options options) +{ + int rc = 0; + unsigned char buf[100]; + int buflen = sizeof(buf); + unsigned short packetid = 255, packetid2 = 0; + unsigned short topicid = 233, topicid2 = 0; + MQTTString topicname = MQTTString_initializer, topicname2 = MQTTString_initializer; + fprintf(xml, " 0, "rc was %d\n", rc); + + rc = MQTTSNDeserialize_register(&topicid2, &packetid2, &topicname2, buf, buflen); + assert("good rc from deserialize register", rc == 1, "rc was %d\n", rc); + + assert("packetids should be the same", packetid == packetid2, "packetids were different %d\n", packetid2); + assert("topicids should be the same", topicid == topicid2, "topicids were different %d\n", topicid2); + assert("topicnames should be the same", + checkMQTTStrings(topicname, topicname2), "topicnames were different\n", rc); + + +/* exit: */ + MyLog(LOGA_INFO, "TEST9: test %s. %d tests run, %d failures.", + (failures == 0) ? "passed" : "failed", tests, failures); + write_test_result(); + return failures; +} + + +int test10(struct Options options) +{ + int rc = 0; + unsigned char buf[100]; + int buflen = sizeof(buf); + unsigned short packetid = 255, packetid2 = 0; + unsigned short topicid = 233, topicid2 = 0; + unsigned char return_code = 127, return_code2 = 0; + + fprintf(xml, " 0, "rc was %d\n", rc); + + rc = MQTTSNDeserialize_regack(&topicid2, &packetid2, &return_code2, buf, buflen); + assert("good rc from deserialize regack", rc == 1, "rc was %d\n", rc); + + assert("packetids should be the same", packetid == packetid2, "packetids were different %d\n", packetid2); + assert("topicids should be the same", topicid == topicid2, "topicids were different %d\n", topicid2); + assert("return codes should be the same", return_code == return_code2, "return_codes were different %d\n", return_code2); + +/* exit: */ + MyLog(LOGA_INFO, "TEST10: test %s. %d tests run, %d failures.", + (failures == 0) ? "passed" : "failed", tests, failures); + write_test_result(); + return failures; +} int main(int argc, char** argv) { int rc = 0; - int (*tests[])() = {NULL, test1, test2, test3, test4, test5, test6, test7}; + int (*tests[])() = {NULL, test1, test2, test3, test4, test5, test6, test7, test8, test9, test10}; xml = fopen("TEST-test1.xml", "w"); fprintf(xml, "\n", (int)(ARRAY_SIZE(tests) - 1));