diff --git a/src/MQTTAsync.c b/src/MQTTAsync.c index cc6ebdc3..85bcba1f 100644 --- a/src/MQTTAsync.c +++ b/src/MQTTAsync.c @@ -609,7 +609,7 @@ int MQTTAsync_createWithOptions(MQTTAsync* handle, const char* serverURI, const } if (options && (strncmp(options->struct_id, "MQCO", 4) != 0 || - options->struct_version < 0 || options->struct_version > 1)) + options->struct_version < 0 || options->struct_version > 2)) { rc = MQTTASYNC_BAD_STRUCTURE; goto exit; @@ -3737,10 +3737,20 @@ int MQTTAsync_send(MQTTAsync handle, const char* destinationName, int payloadlen FUNC_ENTRY; if (m == NULL || m->c == NULL) rc = MQTTASYNC_FAILURE; - else if (m->c->connected == 0 && (m->createOptions == NULL || - m->createOptions->sendWhileDisconnected == 0 || m->shouldBeConnected == 0)) - rc = MQTTASYNC_DISCONNECTED; - else if (!UTF8_validateString(destinationName)) + else if (m->c->connected == 0) + { + if (m->createOptions == NULL) + rc = MQTTASYNC_DISCONNECTED; + else if (m->createOptions->sendWhileDisconnected == 0) + rc = MQTTASYNC_DISCONNECTED; + else if (m->shouldBeConnected == 0 && (m->createOptions->struct_version < 2 || m->createOptions->allowDisconnectedSendAtAnyTime == 0)) + rc = MQTTASYNC_DISCONNECTED; + } + + if (rc != MQTTASYNC_SUCCESS) + goto exit; + + if (!UTF8_validateString(destinationName)) rc = MQTTASYNC_BAD_UTF8_STRING; else if (qos < 0 || qos > 2) rc = MQTTASYNC_BAD_QOS; diff --git a/src/MQTTAsync.h b/src/MQTTAsync.h index cf0b35a5..635d9a68 100644 --- a/src/MQTTAsync.h +++ b/src/MQTTAsync.h @@ -863,13 +863,14 @@ typedef struct { /** The eyecatcher for this structure. must be MQCO. */ char struct_id[4]; - /** The version number of this structure. Must be 0 or 1 + /** The version number of this structure. Must be 0, 1 or 2 * 0 means no MQTTVersion + * 1 means no allowDisconnectedSendAtAnyTime */ int struct_version; /** Whether to allow messages to be sent when the client library is not connected. */ int sendWhileDisconnected; - /** the maximum number of messages allowed to be buffered while not connected. */ + /** The maximum number of messages allowed to be buffered while not connected. */ int maxBufferedMessages; /** Whether the MQTT version is 3.1, 3.1.1, or 5. To use V5, this must be set. * MQTT V5 has to be chosen here, because during the create call the message persistence @@ -877,11 +878,15 @@ typedef struct * is appropriate for the MQTT version we are going to connect with. Selecting 3.1 or * 3.1.1 and attempting to read 5.0 persisted messages will result in an error on create. */ int MQTTVersion; + /** + * Allow sending of messages while disconnected before a first successful connect. + */ + int allowDisconnectedSendAtAnyTime; } MQTTAsync_createOptions; -#define MQTTAsync_createOptions_initializer { {'M', 'Q', 'C', 'O'}, 1, 0, 100, MQTTVERSION_DEFAULT } +#define MQTTAsync_createOptions_initializer { {'M', 'Q', 'C', 'O'}, 2, 0, 100, MQTTVERSION_DEFAULT, 0 } -#define MQTTAsync_createOptions_initializer5 { {'M', 'Q', 'C', 'O'}, 1, 0, 100, MQTTVERSION_5 } +#define MQTTAsync_createOptions_initializer5 { {'M', 'Q', 'C', 'O'}, 2, 0, 100, MQTTVERSION_5, 0 } LIBMQTT_API int MQTTAsync_createWithOptions(MQTTAsync* handle, const char* serverURI, const char* clientId, diff --git a/test/test9.c b/test/test9.c index 0e037359..087390ce 100644 --- a/test/test9.c +++ b/test/test9.c @@ -300,7 +300,10 @@ void assert3PendingTokens(MQTTAsync c) *********************************************************************/ - +void handleTrace(enum MQTTASYNC_TRACE_LEVELS level, char* message) +{ + printf("%s\n", message); +} /********************************************************************* @@ -2036,9 +2039,235 @@ exit: -void handleTrace(enum MQTTASYNC_TRACE_LEVELS level, char* message) +/********************************************************************* + +Test8: send buffered messages before connect + +*********************************************************************/ +int test8_messages_received = 0; +int test8Finished = 0; +int test8OnFailureCalled = 0; +int test8cConnected = 0; +int test8dConnected = 0; +int test8dSubscribed = 0; + +int test8_messageArrived(void* context, char* topicName, int topicLen, MQTTAsync_message* message) { - printf("%s\n", message); + MQTTAsync c = (MQTTAsync)context; + static int message_count = 0; + + MyLog(LOGA_DEBUG, "Message received on topic %s, \"%.*s\"", topicName, message->payloadlen, message->payload); + + test8_messages_received++; + + MQTTAsync_freeMessage(&message); + MQTTAsync_free(topicName); + + return 1; +} + +void test8donSubscribe(void* context, MQTTAsync_successData* response) +{ + MQTTAsync c = (MQTTAsync)context; + MyLog(LOGA_DEBUG, "In subscribe onSuccess callback for client d, %p granted qos %d", c, response->alt.qos); + test8dSubscribed = 1; +} + +void test8dOnConnect(void* context, MQTTAsync_successData* response) +{ + MQTTAsync c = (MQTTAsync)context; + MQTTAsync_responseOptions opts = MQTTAsync_responseOptions_initializer; + int rc; + + MyLog(LOGA_DEBUG, "In connect onSuccess callback for client c, context %p\n", context); + test8dConnected = 1; + + opts.onSuccess = test8donSubscribe; + opts.context = c; + + rc = MQTTAsync_subscribe(c, test_topic, 2, &opts); + assert("Good rc from subscribe", rc == MQTTASYNC_SUCCESS, "rc was %d", rc); + if (rc != MQTTASYNC_SUCCESS) + test8Finished = 1; +} + + +void test8OnFailure(void* context, MQTTAsync_failureData* response) +{ + MyLog(LOGA_DEBUG, "In connect onFailure callback, context %p", context); + + test8OnFailureCalled++; + test8Finished = 1; +} + +void test8cOnConnect(void* context, MQTTAsync_successData* response) +{ + MQTTAsync c = (MQTTAsync)context; + int rc; + + MyLog(LOGA_DEBUG, "In connect onSuccess callback for client c, context %p\n", context); + test8cConnected = 1; +} + + +int test8(struct Options options) +{ + char* testname = "test6"; + int subsqos = 2; + MQTTAsync c, d; + MQTTAsync_connectOptions opts = MQTTAsync_connectOptions_initializer; + MQTTAsync_willOptions wopts = MQTTAsync_willOptions_initializer; + MQTTAsync_createOptions createOptions = MQTTAsync_createOptions_initializer; + int rc = 0; + int count = 0; + char clientidc[50]; + char clientidd[50]; + int i = 0; + + sprintf(willTopic, "paho-test9-8-%s", unique); + sprintf(clientidc, "paho-test9-8-c-%s", unique); + sprintf(clientidd, "paho-test9-8-d-%s", unique); + sprintf(test_topic, "paho-test9-8-test topic %s", unique); + + test5Finished = 0; + failures = 0; + MyLog(LOGA_INFO, "Starting Offline buffering 8 - send messages before successful connect"); + fprintf(xml, "