From 082b4d9f3648dd0f4cacff03964646a0f66c6974 Mon Sep 17 00:00:00 2001 From: Ian Craggs Date: Tue, 15 Jul 2014 16:04:08 +0100 Subject: [PATCH] Suback, unsubscribe and unsuback --- src/MQTTSNPacket.h | 3 +- src/MQTTSNSubscribeClient.c | 2 + src/MQTTSNUnsubscribe.h | 28 ++++++ src/MQTTSNUnsubscribeClient.c | 110 +++++++++++++++++++++++ src/MQTTSNUnsubscribeServer.c | 86 ++++++++++++++++++ test/build_test | 2 +- test/test1.c | 158 ++++++++++++++++++---------------- 7 files changed, 314 insertions(+), 75 deletions(-) create mode 100644 src/MQTTSNUnsubscribe.h create mode 100644 src/MQTTSNUnsubscribeClient.c create mode 100644 src/MQTTSNUnsubscribeServer.c diff --git a/src/MQTTSNPacket.h b/src/MQTTSNPacket.h index 743295a..aff4c45 100644 --- a/src/MQTTSNPacket.h +++ b/src/MQTTSNPacket.h @@ -123,8 +123,7 @@ int MQTTstrlen(MQTTString mqttstring); #include "MQTTSNConnect.h" #include "MQTTSNPublish.h" #include "MQTTSNSubscribe.h" -/*#include "MQTTSNUnsubscribe.h" -*/ +#include "MQTTSNUnsubscribe.h" #include diff --git a/src/MQTTSNSubscribeClient.c b/src/MQTTSNSubscribeClient.c index f06a5b7..f422d7a 100644 --- a/src/MQTTSNSubscribeClient.c +++ b/src/MQTTSNSubscribeClient.c @@ -31,6 +31,8 @@ int MQTTSNSerialize_subscribeLength(MQTTSN_topicid* topicFilter) if (topicFilter->type == MQTTSN_TOPIC_TYPE_NORMAL) len += topicFilter->data.long_.len; + else if (topicFilter->type == MQTTSN_TOPIC_TYPE_SHORT || topicFilter->type == MQTTSN_TOPIC_TYPE_PREDEFINED) + len += 2; return len; } diff --git a/src/MQTTSNUnsubscribe.h b/src/MQTTSNUnsubscribe.h new file mode 100644 index 0000000..3eb4deb --- /dev/null +++ b/src/MQTTSNUnsubscribe.h @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2014 IBM Corp. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Ian Craggs - initial API and implementation and/or initial documentation + *******************************************************************************/ + +#if !defined(MQTTSNUNSUBSCRIBE_H_) +#define MQTTSNUNSUBSCRIBE_H_ + +int MQTTSNSerialize_unsubscribe(unsigned char* buf, int buflen, + unsigned short packetid, MQTTSN_topicid* topicFilter); +int MQTTSNDeserialize_unsubscribe(unsigned short* packetid, MQTTSN_topicid* topicFilter, + unsigned char* buf, int buflen); + +int MQTTSNSerialize_unsuback(unsigned char* buf, int buflen, unsigned short packetid); +int MQTTSNDeserialize_unsuback(unsigned short* packetid, unsigned char* buf, int buflen); + +#endif /* MQTTSNUNSUBSCRIBE_H_ */ diff --git a/src/MQTTSNUnsubscribeClient.c b/src/MQTTSNUnsubscribeClient.c new file mode 100644 index 0000000..1eeb8d0 --- /dev/null +++ b/src/MQTTSNUnsubscribeClient.c @@ -0,0 +1,110 @@ +/******************************************************************************* + * Copyright (c) 2014 IBM Corp. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Ian Craggs - initial API and implementation and/or initial documentation + *******************************************************************************/ + +#include "MQTTSNPacket.h" +#include "StackTrace.h" + +#include + +/** + * Determines the length of the MQTTSN subscribe packet that would be produced using the supplied parameters, + * excluding length + * @param topicName the topic name to be used in the publish + * @return the length of buffer needed to contain the serialized version of the packet + */ +int MQTTSNSerialize_unsubscribeLength(MQTTSN_topicid* topicFilter) +{ + int len = 4; + + if (topicFilter->type == MQTTSN_TOPIC_TYPE_NORMAL) + len += topicFilter->data.long_.len; + else if (topicFilter->type == MQTTSN_TOPIC_TYPE_SHORT || topicFilter->type == MQTTSN_TOPIC_TYPE_PREDEFINED) + len += 2; + + return len; +} + + +int MQTTSNSerialize_unsubscribe(unsigned char* buf, int buflen, unsigned short packetid, MQTTSN_topicid* topicFilter) +{ + unsigned char *ptr = buf; + MQTTSNFlags flags; + int len = 0; + int rc = 0; + + FUNC_ENTRY; + if ((len = MQTTSNPacket_len(MQTTSNSerialize_unsubscribeLength(topicFilter))) > buflen) + { + rc = MQTTSNPACKET_BUFFER_TOO_SHORT; + goto exit; + } + ptr += MQTTSNPacket_encode(ptr, len); /* write length */ + writeChar(&ptr, MQTTSN_UNSUBSCRIBE); /* write message type */ + + flags.all = 0; + flags.bits.topicIdType = topicFilter->type; + writeChar(&ptr, flags.all); + + writeInt(&ptr, packetid); + + /* now the topic id or name */ + if (topicFilter->type == MQTTSN_TOPIC_TYPE_NORMAL) /* means long topic name */ + { + memcpy(ptr, topicFilter->data.long_.name, topicFilter->data.long_.len); + ptr += topicFilter->data.long_.len; + } + else if (topicFilter->type == MQTTSN_TOPIC_TYPE_PREDEFINED) + writeInt(&ptr, topicFilter->data.id); + else if (topicFilter->type == MQTTSN_TOPIC_TYPE_SHORT) + { + writeChar(&ptr, topicFilter->data.short_name[0]); + writeChar(&ptr, topicFilter->data.short_name[1]); + } + + rc = ptr - buf; +exit: + FUNC_EXIT_RC(rc); + return rc; + +} + + +int MQTTSNDeserialize_unsuback(unsigned short* packetid, 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_UNSUBACK) + goto exit; + + *packetid = readInt(&curdata); + + rc = 1; +exit: + FUNC_EXIT_RC(rc); + return rc; +} + + + diff --git a/src/MQTTSNUnsubscribeServer.c b/src/MQTTSNUnsubscribeServer.c new file mode 100644 index 0000000..57dd7bc --- /dev/null +++ b/src/MQTTSNUnsubscribeServer.c @@ -0,0 +1,86 @@ +/******************************************************************************* + * Copyright (c) 2014 IBM Corp. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Ian Craggs - initial API and implementation and/or initial documentation + *******************************************************************************/ + +#include "StackTrace.h" +#include "MQTTSNPacket.h" +#include + +int MQTTSNDeserialize_unsubscribe(unsigned short* packetid, MQTTSN_topicid* topicFilter, + unsigned char* buf, int buflen) +{ + MQTTSNFlags flags; + 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_UNSUBSCRIBE) + goto exit; + + flags.all = readChar(&curdata); + *packetid = readInt(&curdata); + + topicFilter->type = flags.bits.topicIdType; + if (topicFilter->type == MQTTSN_TOPIC_TYPE_NORMAL) + { + topicFilter->data.long_.len = enddata - curdata; + topicFilter->data.long_.name = (char*)curdata; + } + else if (topicFilter->type == MQTTSN_TOPIC_TYPE_PREDEFINED) + topicFilter->data.id = readInt(&curdata); + else if (topicFilter->type == MQTTSN_TOPIC_TYPE_SHORT) + { + topicFilter->data.short_name[0] = readChar(&curdata); + topicFilter->data.short_name[1] = readChar(&curdata); + } + + rc = 1; +exit: + FUNC_EXIT_RC(rc); + return rc; +} + + +int MQTTSNSerialize_unsuback(unsigned char* buf, int buflen, unsigned short packetid) +{ + unsigned char *ptr = buf; + int len = 0; + int rc = 0; + + FUNC_ENTRY; + if ((len = MQTTSNPacket_len(7)) > buflen) + { + rc = MQTTSNPACKET_BUFFER_TOO_SHORT; + goto exit; + } + ptr += MQTTSNPacket_encode(ptr, len); /* write length */ + writeChar(&ptr, MQTTSN_UNSUBACK); /* write message type */ + + writeInt(&ptr, packetid); + + rc = ptr - buf; +exit: + FUNC_EXIT_RC(rc); + return rc; +} + + diff --git a/test/build_test b/test/build_test index 2195230..5d7bbb9 100644 --- a/test/build_test +++ b/test/build_test @@ -1,3 +1,3 @@ -gcc -Wall test1.c -o test1 -I../src ../src/MQTTSNConnectClient.c ../src/MQTTSNConnectServer.c ../src/MQTTSNPacket.c ../src/MQTTSNSerializePublish.c ../src/MQTTSNDeserializePublish.c ../src/MQTTSNSubscribeClient.c ../src/MQTTSNSubscribeServer.c +gcc -Wall test1.c -o test1 -I../src ../src/MQTTSNConnectClient.c ../src/MQTTSNConnectServer.c ../src/MQTTSNPacket.c ../src/MQTTSNSerializePublish.c ../src/MQTTSNDeserializePublish.c ../src/MQTTSNSubscribeClient.c ../src/MQTTSNSubscribeServer.c ../src/MQTTSNUnsubscribeClient.c ../src/MQTTSNUnsubscribeServer.c gcc -Wall test2.c -o test2 -I../src ../src/MQTTSNConnectClient.c ../src/MQTTSNConnectServer.c ../src/MQTTSNPacket.c ../src/MQTTSNSerializePublish.c ../src/MQTTSNDeserializePublish.c ../src/MQTTSNSubscribeClient.c diff --git a/test/test1.c b/test/test1.c index e2adf5a..10eb42f 100644 --- a/test/test1.c +++ b/test/test1.c @@ -584,6 +584,7 @@ int test3(struct Options options) + int test4(struct Options options) { int rc = 0; @@ -632,98 +633,46 @@ int test4(struct Options options) } -#if 0 -int test4(struct Options options) -{ - int i = 0; - int rc = 0; - char buf[100]; - int buflen = sizeof(buf); -#define TOPIC_COUNT 2 - - int msgid = 23; - int count = TOPIC_COUNT; - int granted_qoss[TOPIC_COUNT] = {2, 1}; -; - int msgid2 = 2223; - int count2 = 0; - int granted_qoss2[TOPIC_COUNT] = {0, 0}; - - fprintf(xml, " 0, "rc was %d\n", rc); - - rc = MQTTDeserialize_suback(&msgid2, 2, &count2, granted_qoss2, buf, buflen); - assert("good rc from deserialize suback", rc == 1, "rc was %d\n", rc); - - /* data after should be the same as data before */ - assert("msgids should be the same", msgid == msgid2, "msgids were different %d\n", msgid2); - - assert("count should be the same", count == count2, "counts were different %d\n", count2); - - for (i = 0; i < count2; ++i) - assert("qoss should be the same", granted_qoss[i] == granted_qoss2[i], "qoss were different %d\n", granted_qoss2[i]); - -/* exit: */ - MyLog(LOGA_INFO, "TEST4: test %s. %d tests run, %d failures.", - (failures == 0) ? "passed" : "failed", tests, failures); - write_test_result(); - return failures; -} - - int test5(struct Options options) { - int i = 0; int rc = 0; - char buf[100]; - int buflen = sizeof(buf); -#define TOPIC_COUNT 2 + unsigned char buf[100]; + size_t buflen = sizeof(buf); - int dup = 0; - int msgid = 23; - int count = TOPIC_COUNT; - MQTTString topicStrings[TOPIC_COUNT] = { MQTTString_initializer, MQTTString_initializer }; + unsigned short packetid = 23; + MQTTSN_topicid topicFilter; - int dup2 = 1; - int msgid2 = 2223; - int count2 = 0; - MQTTString topicStrings2[TOPIC_COUNT] = { MQTTString_initializer, MQTTString_initializer }; + unsigned short packetid2 = 2223; + MQTTSN_topicid topicFilter2; - fprintf(xml, " 0, "rc was %d\n", rc); - rc = MQTTDeserialize_unsubscribe(&dup2, &msgid2, 2, &count2, topicStrings2, buf, buflen); + rc = MQTTSNDeserialize_unsubscribe(&packetid2, &topicFilter2, buf, buflen); assert("good rc from deserialize unsubscribe", rc == 1, "rc was %d\n", rc); /* data after should be the same as data before */ - assert("dups should be the same", dup == dup2, "dups were different %d\n", dup2); - assert("msgids should be the same", msgid == msgid2, "msgids were different %d\n", msgid2); + assert("msgids should be the same", packetid == packetid2, "packetids were different %d\n", packetid2); - assert("count should be the same", count == count2, "counts were different %d\n", count2); + assert("topics should be the same", + checkMQTTSNTopics(topicFilter, topicFilter2), "topics were different %s\n", ""); - for (i = 0; i < count2; ++i) - assert("topics should be the same", - checkMQTTStrings(topicStrings[i], topicStrings2[i]), "topics were different %s\n", ""); - -/* exit: */ +/*exit:*/ MyLog(LOGA_INFO, "TEST5: test %s. %d tests run, %d failures.", (failures == 0) ? "passed" : "failed", tests, failures); write_test_result(); return failures; } -#endif int test6(struct Options options) @@ -758,10 +707,75 @@ int test6(struct Options options) } +int test7(struct Options options) +{ + int rc = 0; + unsigned char buf[100]; + int buflen = sizeof(buf); + unsigned short packetid = 255, packetid2 = 0; + int qos = 2, qos2 = 0; + unsigned short topicid = 233, topicid2 = 0; + unsigned char return_code = 32, return_code2 = 0; + + fprintf(xml, " 0, "rc was %d\n", rc); + + rc = MQTTSNDeserialize_suback(&qos2, &topicid2, &packetid2, &return_code2, buf, buflen); + assert("good rc from deserialize suback", rc == 1, "rc was %d\n", rc); + + assert("packetids should be the same", packetid == packetid2, "packetids were different %d\n", packetid2); + assert("qoss should be the same", qos == qos2, "qoss were different %d\n", qos2); + 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, "TEST7: test %s. %d tests run, %d failures.", + (failures == 0) ? "passed" : "failed", tests, failures); + write_test_result(); + return failures; +} + + +int test8(struct Options options) +{ + int rc = 0; + unsigned char buf[100]; + int buflen = sizeof(buf); + unsigned short packetid = 255, packetid2 = 0; + + fprintf(xml, " 0, "rc was %d\n", rc); + + rc = MQTTSNDeserialize_unsuback(&packetid2, buf, buflen); + assert("good rc from deserialize unsuback", rc == 1, "rc was %d\n", rc); + + assert("packetids should be the same", packetid == packetid2, "packetids were different %d\n", packetid2); + +/* exit: */ + MyLog(LOGA_INFO, "TEST8: 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, test6}; + int (*tests[])() = {NULL, test1, test2, test3, test4, test5, test6, test7}; xml = fopen("TEST-test1.xml", "w"); fprintf(xml, "\n", (int)(ARRAY_SIZE(tests) - 1));