Commit f11f08e8 authored by Ian Craggs's avatar Ian Craggs

Binary passwords and will messages: PR #159, issues #167 and #34

Squashed commit of the following:

commit 907b9ecdaf160bf95c17aafcaf4ab3e656ab9ccc
Author: Ian Craggs <icraggs@uk.ibm.com>
Date:   Wed Apr 5 23:33:44 2017 +0100

    Use binary passwords in tests

commit 3930b18d3835727e3cb98ef0ce1a742bd0dffab7
Author: Ian Craggs <icraggs@uk.ibm.com>
Date:   Wed Apr 5 17:15:29 2017 +0100

    Binary MQTT password support

commit 4abe6a996b1219aafa22b5dd69bf1e676d377466
Author: Ian Craggs <icraggs@uk.ibm.com>
Date:   Wed Apr 5 16:13:18 2017 +0100

    Fix test config

commit e742ed182d6de44e9afd6e9c9c03c79f359fbe29
Author: Ian Craggs <icraggs@uk.ibm.com>
Date:   Wed Apr 5 15:46:53 2017 +0100

    Async binary will message

commit 9313e66214720c285f510e325a5c942ad22f2542
Author: Ian Craggs <icraggs@uk.ibm.com>
Date:   Wed Apr 5 11:50:10 2017 +0100

    Binary will message support, take 2

commit 5cf548505a548eff394348aa7406e5a34d0f5054
Author: Ian Craggs <icraggs@uk.ibm.com>
Date:   Tue Apr 4 22:54:15 2017 +0100

    Binary will message
parent 966d6b96
/*******************************************************************************
* Copyright (c) 2009, 2014 IBM Corp.
* Copyright (c) 2009, 2017 IBM Corp.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
......@@ -14,6 +14,8 @@
* Ian Craggs - initial API and implementation and/or initial documentation
* Ian Craggs - add SSL support
* Ian Craggs - fix for bug 413429 - connectionLost not called
* Ian Craggs - change will payload to binary
* Ian Craggs - password to binary
*******************************************************************************/
#if !defined(CLIENTS_H)
......@@ -107,7 +109,8 @@ BE*/
typedef struct
{
char *topic;
char *msg;
int payloadlen;
void *payload;
int retained;
int qos;
} willMessages;
......@@ -162,12 +165,13 @@ typedef struct
*/
typedef struct
{
char* clientID; /**< the string id of the client */
char* clientID; /**< the string id of the client */
const char* username; /**< MQTT v3.1 user name */
const char* password; /**< MQTT v3.1 password */
int passwordlen; /**< MQTT password length */
const void* password; /**< MQTT v3.1 binary password */
unsigned int cleansession : 1; /**< MQTT clean session flag */
unsigned int connected : 1; /**< whether it is currently connected */
unsigned int good : 1; /**< if we have an error on the socket we turn this off */
unsigned int good : 1; /**< if we have an error on the socket we turn this off */
unsigned int ping_outstanding : 1;
int connect_state : 4;
networkHandles net;
......
......@@ -2175,14 +2175,14 @@ int MQTTAsync_connect(MQTTAsync handle, const MQTTAsync_connectOptions* options)
goto exit;
}
if (strncmp(options->struct_id, "MQTC", 4) != 0 || options->struct_version < 0 || options->struct_version > 4)
if (strncmp(options->struct_id, "MQTC", 4) != 0 || options->struct_version < 0 || options->struct_version > 5)
{
rc = MQTTASYNC_BAD_STRUCTURE;
goto exit;
}
if (options->will) /* check validity of will options structure */
{
if (strncmp(options->will->struct_id, "MQTW", 4) != 0 || options->will->struct_version != 0)
if (strncmp(options->will->struct_id, "MQTW", 4) != 0 || (options->will->struct_version != 0 && options->will->struct_version != 1))
{
rc = MQTTASYNC_BAD_STRUCTURE;
goto exit;
......@@ -2245,16 +2245,37 @@ int MQTTAsync_connect(MQTTAsync handle, const MQTTAsync_connectOptions* options)
if (m->c->will)
{
free(m->c->will->msg);
free(m->c->will->payload);
free(m->c->will->topic);
free(m->c->will);
m->c->will = NULL;
}
if (options->will && options->will->struct_version == 0)
if (options->will && (options->will->struct_version == 0 || options->will->struct_version == 1))
{
const void* source = NULL;
m->c->will = malloc(sizeof(willMessages));
m->c->will->msg = MQTTStrdup(options->will->message);
if (options->will->message || (options->will->struct_version == 1 && options->will->payload.data))
{
if (options->will->struct_version == 1 && options->will->payload.data)
{
m->c->will->payloadlen = options->will->payload.len;
source = options->will->payload.data;
}
else
{
m->c->will->payloadlen = strlen(options->will->message);
source = (void*)options->will->message;
}
m->c->will->payload = malloc(m->c->will->payloadlen);
memcpy(m->c->will->payload, source, m->c->will->payloadlen);
}
else
{
m->c->will->payload = NULL;
m->c->will->payloadlen = 0;
}
m->c->will->qos = options->will->qos;
m->c->will->retained = options->will->retained;
m->c->will->topic = MQTTStrdup(options->will->topicName);
......@@ -2297,6 +2318,14 @@ int MQTTAsync_connect(MQTTAsync handle, const MQTTAsync_connectOptions* options)
m->c->username = options->username;
m->c->password = options->password;
if (options->password)
m->c->passwordlen = strlen(options->password) + 1;
else if (options->struct_version >= 5 && options->binarypwd.data)
{
m->c->password = options->binarypwd.data;
m->c->passwordlen = options->binarypwd.len;
}
m->c->retryInterval = options->retryInterval;
m->shouldBeConnected = 1;
......
......@@ -17,6 +17,8 @@
* Ian Craggs - MQTT 3.1.1 support
* Ian Craggs - fix for bug 444103 - success/failure callbacks not invoked
* Ian Craggs - automatic reconnect and offline buffering (send while disconnected)
* Ian Craggs - binary will message
* Ian Craggs - binary password
*******************************************************************************/
/********************************************************************/
......@@ -568,7 +570,9 @@ typedef struct
{
/** The eyecatcher for this structure. must be MQTW. */
const char struct_id[4];
/** The version number of this structure. Must be 0 */
/** The version number of this structure. Must be 0 or 1
0 indicates no binary will message support
*/
int struct_version;
/** The LWT topic to which the LWT message will be published. */
const char* topicName;
......@@ -583,9 +587,15 @@ typedef struct
* MQTTAsync_message.qos and @ref qos).
*/
int qos;
/** The LWT payload in binary form. This is only checked and used if the message option is NULL */
struct
{
int len; /**< binary payload length */
const void* data; /**< binary payload data */
} payload;
} MQTTAsync_willOptions;
#define MQTTAsync_willOptions_initializer { {'M', 'Q', 'T', 'W'}, 0, NULL, NULL, 0, 0 }
#define MQTTAsync_willOptions_initializer { {'M', 'Q', 'T', 'W'}, 1, NULL, NULL, 0, 0 }
/**
* MQTTAsync_sslProperties defines the settings to establish an SSL/TLS connection using the
......@@ -647,11 +657,12 @@ typedef struct
{
/** The eyecatcher for this structure. must be MQTC. */
const char struct_id[4];
/** The version number of this structure. Must be 0, 1, 2, 3 or 4.
/** The version number of this structure. Must be 0, 1, 2, 3 4 or 5.
* 0 signifies no SSL options and no serverURIs
* 1 signifies no serverURIs
* 2 signifies no MQTTVersion
* 3 signifies no automatic reconnect options
* 2 signifies no MQTTVersion
* 3 signifies no automatic reconnect options
* 4 signifies no binary password option (just string)
*/
int struct_version;
/** The "keep alive" interval, measured in seconds, defines the maximum time
......@@ -772,11 +783,18 @@ typedef struct
* Maximum retry interval in seconds. The doubling stops here on failed retries.
*/
int maxRetryInterval;
/**
* Optional binary password. Only checked and used if the password option is NULL
*/
struct {
int len; /**< binary password length */
const void* data; /**< binary password data */
} binarypwd;
} MQTTAsync_connectOptions;
#define MQTTAsync_connectOptions_initializer { {'M', 'Q', 'T', 'C'}, 4, 60, 1, 10, NULL, NULL, NULL, 30, 0,\
NULL, NULL, NULL, NULL, 0, NULL, 0, 0, 1, 60}
#define MQTTAsync_connectOptions_initializer { {'M', 'Q', 'T', 'C'}, 5, 60, 1, 10, NULL, NULL, NULL, 30, 0,\
NULL, NULL, NULL, NULL, 0, NULL, 0, 0, 1, 60, {0, NULL}}
/**
* This function attempts to connect a previously-created client (see
......
......@@ -30,6 +30,7 @@
* Ian Craggs - fix for bug 474905 - insufficient synchronization for subscribe, unsubscribe, connect
* Ian Craggs - make it clear that yield and receive are not intended for multi-threaded mode (bug 474748)
* Ian Craggs - SNI support, message queue unpersist bug
* Ian Craggs - binary will message support
*******************************************************************************/
/**
......@@ -1011,16 +1012,37 @@ static int MQTTClient_connectURI(MQTTClient handle, MQTTClient_connectOptions* o
if (m->c->will)
{
free(m->c->will->msg);
free(m->c->will->payload);
free(m->c->will->topic);
free(m->c->will);
m->c->will = NULL;
}
if (options->will && options->will->struct_version == 0)
if (options->will && (options->will->struct_version == 0 || options->will->struct_version == 1))
{
const void* source = NULL;
m->c->will = malloc(sizeof(willMessages));
m->c->will->msg = MQTTStrdup(options->will->message);
if (options->will->message || (options->will->struct_version == 1 && options->will->payload.data))
{
if (options->will->struct_version == 1 && options->will->payload.data)
{
m->c->will->payloadlen = options->will->payload.len;
source = options->will->payload.data;
}
else
{
m->c->will->payloadlen = strlen(options->will->message);
source = (void*)options->will->message;
}
m->c->will->payload = malloc(m->c->will->payloadlen);
memcpy(m->c->will->payload, source, m->c->will->payloadlen);
}
else
{
m->c->will->payload = NULL;
m->c->will->payloadlen = 0;
}
m->c->will->qos = options->will->qos;
m->c->will->retained = options->will->retained;
m->c->will->topic = MQTTStrdup(options->will->topicName);
......@@ -1063,6 +1085,13 @@ static int MQTTClient_connectURI(MQTTClient handle, MQTTClient_connectOptions* o
m->c->username = options->username;
m->c->password = options->password;
if (options->password)
m->c->passwordlen = strlen(options->password) + 1;
else if (options->struct_version >= 5 && options->binarypwd.data)
{
m->c->password = options->binarypwd.data;
m->c->passwordlen = options->binarypwd.len;
}
m->c->retryInterval = options->retryInterval;
if (options->struct_version >= 3)
......@@ -1098,9 +1127,7 @@ int MQTTClient_connect(MQTTClient handle, MQTTClient_connectOptions* options)
goto exit;
}
if (strncmp(options->struct_id, "MQTC", 4) != 0 ||
(options->struct_version != 0 && options->struct_version != 1 && options->struct_version != 2
&& options->struct_version != 3 && options->struct_version != 4))
if (strncmp(options->struct_id, "MQTC", 4) != 0 || options->struct_version < 0 || options->struct_version > 5)
{
rc = MQTTCLIENT_BAD_STRUCTURE;
goto exit;
......@@ -1108,7 +1135,7 @@ int MQTTClient_connect(MQTTClient handle, MQTTClient_connectOptions* options)
if (options->will) /* check validity of will options structure */
{
if (strncmp(options->will->struct_id, "MQTW", 4) != 0 || options->will->struct_version != 0)
if (strncmp(options->will->struct_id, "MQTW", 4) != 0 || (options->will->struct_version != 0 && options->will->struct_version != 1))
{
rc = MQTTCLIENT_BAD_STRUCTURE;
goto exit;
......@@ -1160,6 +1187,10 @@ int MQTTClient_connect(MQTTClient handle, MQTTClient_connectOptions* options)
exit:
if (m->c->will)
{
if (m->c->will->payload)
free(m->c->will->payload);
if (m->c->will->topic)
free(m->c->will->topic);
free(m->c->will);
m->c->will = NULL;
}
......
......@@ -425,24 +425,32 @@ typedef struct
{
/** The eyecatcher for this structure. must be MQTW. */
const char struct_id[4];
/** The version number of this structure. Must be 0 */
/** The version number of this structure. Must be 0 or 1
0 means there is no binary payload option
*/
int struct_version;
/** The LWT topic to which the LWT message will be published. */
const char* topicName;
/** The LWT payload. */
/** The LWT payload in string form. */
const char* message;
/**
* The retained flag for the LWT message (see MQTTClient_message.retained).
*/
* The retained flag for the LWT message (see MQTTClient_message.retained).
*/
int retained;
/**
* The quality of service setting for the LWT message (see
* MQTTClient_message.qos and @ref qos).
*/
* The quality of service setting for the LWT message (see
* MQTTClient_message.qos and @ref qos).
*/
int qos;
/** The LWT payload in binary form. This is only checked and used if the message option is NULL */
struct
{
int len; /**< binary payload length */
const void* data; /**< binary payload data */
} payload;
} MQTTClient_willOptions;
#define MQTTClient_willOptions_initializer { {'M', 'Q', 'T', 'W'}, 0, NULL, NULL, 0, 0 }
#define MQTTClient_willOptions_initializer { {'M', 'Q', 'T', 'W'}, 1, NULL, NULL, 0, 0, {0, NULL} }
/**
* MQTTClient_sslProperties defines the settings to establish an SSL/TLS connection using the
......@@ -513,11 +521,12 @@ typedef struct
{
/** The eyecatcher for this structure. must be MQTC. */
const char struct_id[4];
/** The version number of this structure. Must be 0, 1, 2, 3 or 4.
/** The version number of this structure. Must be 0, 1, 2, 3, 4 or 5.
* 0 signifies no SSL options and no serverURIs
* 1 signifies no serverURIs
* 2 signifies no MQTTVersion
* 3 signifies no returned values
* 4 signifies no binary password option
*/
int struct_version;
/** The "keep alive" interval, measured in seconds, defines the maximum time
......@@ -624,9 +633,16 @@ typedef struct
int MQTTVersion; /**< the MQTT version used to connect with */
int sessionPresent; /**< if the MQTT version is 3.1.1, the value of sessionPresent returned in the connack */
} returned;
/**
* Optional binary password. Only checked and used if the password option is NULL
*/
struct {
int len; /**< binary password length */
const void* data; /**< binary password data */
} binarypwd;
} MQTTClient_connectOptions;
#define MQTTClient_connectOptions_initializer { {'M', 'Q', 'T', 'C'}, 4, 60, 1, 1, NULL, NULL, NULL, 30, 20, NULL, 0, NULL, 0, {NULL, 0, 0} }
#define MQTTClient_connectOptions_initializer { {'M', 'Q', 'T', 'C'}, 5, 60, 1, 1, NULL, NULL, NULL, 30, 20, NULL, 0, NULL, 0, {NULL, 0, 0}, {0, NULL} }
/**
* MQTTClient_libraryInfo is used to store details relating to the currently used
......
......@@ -440,6 +440,20 @@ void writeUTF(char** pptr, const char* string)
}
/**
* Writes length delimited data to an output buffer
* @param pptr pointer to the output buffer - incremented by the number of bytes used & returned
* @param data the data to write
* @param datalen the length of the data to write
*/
void writeData(char** pptr, const void* data, int datalen)
{
writeInt(pptr, datalen);
memcpy(*pptr, data, datalen);
*pptr += datalen;
}
/**
* Function used in the new packets table to create packets which have only a header.
* @param aHeader the MQTT header byte
......
......@@ -224,6 +224,7 @@ unsigned char readChar(char** pptr);
void writeChar(char** pptr, char c);
void writeInt(char** pptr, int anInt);
void writeUTF(char** pptr, const char* string);
void writeData(char** pptr, const void* data, int datalen);
const char* MQTTPacket_name(int ptype);
......
/*******************************************************************************
* Copyright (c) 2009, 2014 IBM Corp.
* Copyright (c) 2009, 2017 IBM Corp.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
......@@ -15,6 +15,7 @@
* Ian Craggs, Allan Stockdill-Mander - SSL updates
* Ian Craggs - MQTT 3.1.1 support
* Rong Xiang, Ian Craggs - C++ compatibility
* Ian Craggs - binary password and will payload
*******************************************************************************/
/**
......@@ -53,11 +54,11 @@ int MQTTPacket_send_connect(Clients* client, int MQTTVersion)
len = ((MQTTVersion == 3) ? 12 : 10) + (int)strlen(client->clientID)+2;
if (client->will)
len += (int)strlen(client->will->topic)+2 + (int)strlen(client->will->msg)+2;
len += (int)strlen(client->will->topic)+2 + client->will->payloadlen+2;
if (client->username)
len += (int)strlen(client->username)+2;
if (client->password)
len += (int)strlen(client->password)+2;
len += client->passwordlen+2;
ptr = buf = malloc(len);
if (MQTTVersion == 3)
......@@ -93,12 +94,12 @@ int MQTTPacket_send_connect(Clients* client, int MQTTVersion)
if (client->will)
{
writeUTF(&ptr, client->will->topic);
writeUTF(&ptr, client->will->msg);
writeData(&ptr, client->will->payload, client->will->payloadlen);
}
if (client->username)
writeUTF(&ptr, client->username);
if (client->password)
writeUTF(&ptr, client->password);
writeData(&ptr, client->password, client->passwordlen);
rc = MQTTPacket_send(&client->net, packet.header, buf, len, 1);
Log(LOG_PROTOCOL, 0, NULL, client->net.socket, client->clientID, client->cleansession, rc);
......
......@@ -669,7 +669,7 @@ void MQTTProtocol_freeClient(Clients* client)
free(client->clientID);
if (client->will)
{
free(client->will->msg);
free(client->will->payload);
free(client->will->topic);
free(client->will);
}
......
......@@ -82,6 +82,11 @@ ADD_TEST(
COMMAND "test1" "--test_no" "6" "--connection" ${MQTT_TEST_BROKER} "--proxy_connection" ${MQTT_TEST_PROXY}
)
ADD_TEST(
NAME test1-7-connlost-binary-will-message
COMMAND "test1" "--test_no" "7" "--connection" ${MQTT_TEST_BROKER} "--proxy_connection" ${MQTT_TEST_PROXY}
)
SET_TESTS_PROPERTIES(
test1-1-single-thread-client
test1-2-multithread-callbacks
......@@ -89,6 +94,7 @@ SET_TESTS_PROPERTIES(
test1-4-client-persistence
test1-5-disconnect-with-quiesce
test1-6-connlost-will-message
test1-7-connlost-binary-will-message
PROPERTIES TIMEOUT 540
)
......@@ -405,11 +411,17 @@ ADD_TEST(
COMMAND test9 "--test_no" "5" "--connection" ${MQTT_TEST_BROKER} "--proxy_connection" ${MQTT_TEST_PROXY}
)
ADD_TEST(
NAME test9-6-offline-buffering-max-buffered-binary-will
COMMAND test9 "--test_no" "6" "--connection" ${MQTT_TEST_BROKER} "--proxy_connection" ${MQTT_TEST_PROXY}
)
SET_TESTS_PROPERTIES(
test9-1-offline-buffering-send-disconnected
test9-2-offline-buffering-send-disconnected-serverURIs
test9-3-offline-buffering-auto-reconnect
test9-4-offline-buffering-auto-reconnect-serverURIs
test9-5-offline-buffering-max-buffered
test9-6-offline-buffering-max-buffered-binary-will
PROPERTIES TIMEOUT 540
)
......@@ -545,6 +545,9 @@ int test2(struct Options options)
opts.keepAliveInterval = 20;
opts.cleansession = 1;
opts.MQTTVersion = options.MQTTVersion;
opts.username = "testuser";
opts.binarypwd.data = "testpassword";
opts.binarypwd.len = strlen(opts.binarypwd.data);
if (options.haconnections != NULL)
{
opts.serverURIs = options.haconnections;
......@@ -1045,10 +1048,118 @@ exit:
return failures;
}
int test6a(struct Options options)
{
char* testname = "test6a";
MQTTClient_connectOptions opts = MQTTClient_connectOptions_initializer;
MQTTClient_willOptions wopts = MQTTClient_willOptions_initializer;
MQTTClient_connectOptions opts2 = MQTTClient_connectOptions_initializer;
int rc, count;
char* mqttsas_topic = "MQTTSAS topic";
failures = 0;
MyLog(LOGA_INFO, "Starting test 6 - connectionLost and binary will messages");
fprintf(xml, "<testcase classname=\"test1\" name=\"connectionLost and binary will messages\"");
global_start_time = start_clock();
opts.keepAliveInterval = 2;
opts.cleansession = 1;
opts.MQTTVersion = MQTTVERSION_3_1_1;
opts.will = &wopts;
opts.will->payload.data = test6_will_message;
opts.will->payload.len = strlen(test6_will_message) + 1;
opts.will->qos = 1;
opts.will->retained = 0;
opts.will->topicName = test6_will_topic;
if (options.haconnections != NULL)
{
opts.serverURIs = options.haconnections;
opts.serverURIcount = options.hacount;
}
/* Client-1 with Will options */
rc = MQTTClient_create(&test6_c1, options.proxy_connection, "Client_1", MQTTCLIENT_PERSISTENCE_DEFAULT, NULL);
assert("good rc from create", rc == MQTTCLIENT_SUCCESS, "rc was %d\n", rc);
if (rc != MQTTCLIENT_SUCCESS)
goto exit;
rc = MQTTClient_setCallbacks(test6_c1, (void*)test6_c1, test6_connectionLost, test6_messageArrived, test6_deliveryComplete);
assert("good rc from setCallbacks", rc == MQTTCLIENT_SUCCESS, "rc was %d\n", rc);
if (rc != MQTTCLIENT_SUCCESS)
goto exit;
/* Connect to the broker */
rc = MQTTClient_connect(test6_c1, &opts);
assert("good rc from connect", rc == MQTTCLIENT_SUCCESS, "rc was %d\n", rc);
if (rc != MQTTCLIENT_SUCCESS)
goto exit;
/* Client - 2 (multi-threaded) */
rc = MQTTClient_create(&test6_c2, options.connection, "Client_2", MQTTCLIENT_PERSISTENCE_DEFAULT, NULL);
assert("good rc from create", rc == MQTTCLIENT_SUCCESS, "rc was %d\n", rc);
/* Set the callback functions for the client */
rc = MQTTClient_setCallbacks(test6_c2, (void*)test6_c2, test6_connectionLost, test6_messageArrived, test6_deliveryComplete);
assert("good rc from setCallbacks", rc == MQTTCLIENT_SUCCESS, "rc was %d\n", rc);
/* Connect to the broker */
opts2.keepAliveInterval = 20;
opts2.cleansession = 1;
MyLog(LOGA_INFO, "Connecting Client_2 ...");
rc = MQTTClient_connect(test6_c2, &opts2);
assert("Good rc from connect", rc == MQTTCLIENT_SUCCESS, "rc was %d\n", rc);
rc = MQTTClient_subscribe(test6_c2, test6_will_topic, 2);
assert("Good rc from subscribe", rc == MQTTCLIENT_SUCCESS, "rc was %d\n", rc);
/* now send the command which will break the connection and cause the will message to be sent */
rc = MQTTClient_publish(test6_c1, mqttsas_topic, (int)strlen("TERMINATE"), "TERMINATE", 0, 0, NULL);
assert("Good rc from publish", rc == MQTTCLIENT_SUCCESS, "rc was %d\n", rc);
MyLog(LOGA_INFO, "Waiting to receive the will message");
count = 0;
while (++count < 40)
{
#if defined(WIN32)
Sleep(1000L);
#else
sleep(1);
#endif
if (test6_will_message_arrived == 1 && test6_connection_lost_called == 1)
break;
}
assert("will message arrived", test6_will_message_arrived == 1,
"will_message_arrived was %d\n", test6_will_message_arrived);
assert("connection lost called", test6_connection_lost_called == 1,
"connection_lost_called %d\n", test6_connection_lost_called);
rc = MQTTClient_unsubscribe(test6_c2, test6_will_topic);
assert("Good rc from unsubscribe", rc == MQTTCLIENT_SUCCESS, "rc was %d", rc);
rc = MQTTClient_isConnected(test6_c2);
assert("Client-2 still connected", rc == 1, "isconnected is %d", rc);
rc = MQTTClient_isConnected(test6_c1);
assert("Client-1 not connected", rc == 0, "isconnected is %d", rc);
rc = MQTTClient_disconnect(test6_c2, 100L);
assert("Good rc from disconnect", rc == MQTTCLIENT_SUCCESS, "rc was %d", rc);
MQTTClient_destroy(&test6_c1);
MQTTClient_destroy(&test6_c2);
exit:
MyLog(LOGA_INFO, "%s: test %s. %d tests run, %d failures.\n",
(failures == 0) ? "passed" : "failed", testname, 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};
int (*tests[])() = {NULL, test1, test2, test3, test4, test5, test6, test6a};
int i;
xml = fopen("TEST-test1.xml", "w");
......
......@@ -470,7 +470,8 @@ int test2(struct Options options)
opts.keepAliveInterval = 20;
opts.cleansession = 1;
opts.username = "testuser";
opts.password = "testpassword";
opts.binarypwd.data = "testpassword";
opts.binarypwd.len = strlen(opts.binarypwd.data);
opts.MQTTVersion = options.MQTTVersion;
opts.will = &wopts;
......
......@@ -13,6 +13,7 @@
* Contributors:
* Ian Craggs - initial API and implementation and/or initial documentation
* Ian Craggs - correct some compile warnings
* Ian Craggs - add binary will message test
*******************************************************************************/
......@@ -803,6 +804,7 @@ int test2(struct Options options)
assert("Good rc from disconnect", rc == MQTTASYNC_SUCCESS, "rc was %d ", rc);
exit:
MySleep(200);
MQTTAsync_destroy(&c);
MQTTAsync_destroy(&d);
MyLog(LOGA_INFO, "%s: test %s. %d tests run, %d failures.",
......@@ -1077,6 +1079,7 @@ int test3(struct Options options)
assert("Good rc from disconnect", rc == MQTTASYNC_SUCCESS, "rc was %d ", rc);
exit:
MySleep(200);
MQTTAsync_destroy(&c);
MQTTAsync_destroy(&d);
MyLog(LOGA_INFO, "%s: test %s. %d tests run, %d failures.",
......@@ -1351,6 +1354,7 @@ int test4(struct Options options)
assert("Good rc from disconnect", rc == MQTTASYNC_SUCCESS, "rc was %d ", rc);
exit:
MySleep(200);
MQTTAsync_destroy(&c);
MQTTAsync_destroy(&d);
MyLog(LOGA_INFO, "%s: test %s. %d tests run, %d failures.",
......@@ -1373,6 +1377,9 @@ exit:
int test5_will_message_received = 0;
int test5_messages_received = 0;
int test5Finished = 0;
int test5OnFailureCalled = 0;
int test5c_connected = 0;
int test5_messageArrived(void* context, char* topicName, int topicLen, MQTTAsync_message* message)
{
......@@ -1392,10 +1399,6 @@ int test5_messageArrived(void* context, char* topicName, int topicLen, MQTTAsync
return 1;
}
int test5Finished = 0;
int test5OnFailureCalled = 0;
void test5cOnFailure(void* context, MQTTAsync_failureData* response)
{
MyLog(LOGA_DEBUG, "In connect onFailure callback, context %p", context);
......@@ -1459,8 +1462,6 @@ void test5dOnConnect(void* context, MQTTAsync_successData* response)
test5Finished = 1;
}
int test5c_connected = 0;
void test5cConnected(void* context, char* cause)
{
MQTTAsync c = (MQTTAsync)context;
......@@ -1631,6 +1632,185 @@ int test5(struct Options options)
assert("Good rc from disconnect", rc == MQTTASYNC_SUCCESS, "rc was %d ", rc);
exit:
MySleep(200);
MQTTAsync_destroy(&c);
MQTTAsync_destroy(&d);
MyLog(LOGA_INFO, "%s: test %s. %d tests run, %d failures.",
(failures == 0) ? "passed" : "failed", testname, tests, failures);
write_test_result();
return failures;
}
int test6(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;
MQTTAsync_token *tokens;
test5_will_message_received = 0;
test5_messages_received = 0;
test5Finished = 0;
test5OnFailureCalled = 0;
test5c_connected = 0;
sprintf(willTopic, "paho-test9-6-%s", unique);
sprintf(clientidc, "paho-test9-6-c-%s", unique);
sprintf(clientidd, "paho-test9-6-d-%s", unique);
sprintf(test_topic, "paho-test9-6-test topic %s", unique);
test5Finished = 0;
failures = 0;
MyLog(LOGA_INFO, "Starting Offline buffering 6 - max buffered with binary will");
fprintf(xml, "<testcase classname=\"test6\" name=\"%s\"", testname);
global_start_time = start_clock();
createOptions.sendWhileDisconnected = 1;
createOptions.maxBufferedMessages = 3;
rc = MQTTAsync_createWithOptions(&c, options.proxy_connection, clientidc, MQTTCLIENT_PERSISTENCE_DEFAULT,
NULL, &createOptions);
assert("good rc from create", rc == MQTTASYNC_SUCCESS, "rc was %d \n", rc);
if (rc != MQTTASYNC_SUCCESS)
{
MQTTAsync_destroy(&c);
goto exit;
}
rc = MQTTAsync_create(&d, options.connection, clientidd, MQTTCLIENT_PERSISTENCE_DEFAULT, NULL);
assert("good rc from create", rc == MQTTASYNC_SUCCESS, "rc was %d \n", rc);
if (rc != MQTTASYNC_SUCCESS)
{
MQTTAsync_destroy(&c);
goto exit;
}
opts.keepAliveInterval = 20;
opts.cleansession = 1;
//opts.username = "testuser";
//opts.password = "testpassword";
rc = MQTTAsync_setCallbacks(d, d, NULL, test5_messageArrived, NULL);
assert("Good rc from setCallbacks", rc == MQTTASYNC_SUCCESS, "rc was %d", rc);
opts.will = NULL; /* don't need will for this client, as it's going to be connected all the time */
opts.context = d;
opts.onSuccess = test5dOnConnect;
opts.onFailure = test5dOnFailure;
MyLog(LOGA_DEBUG, "Connecting client d");
rc = MQTTAsync_connect(d, &opts);
assert("Good rc from connect", rc == MQTTASYNC_SUCCESS, "rc was %d ", rc);
if (rc != MQTTASYNC_SUCCESS)
{
failures++;
goto exit;
}
/* wait until d is ready: connected and subscribed */
count = 0;
while (!test5dReady && ++count < 10000)
MySleep(100);
assert("Count should be less than 10000", count < 10000, "count was %d", count); /* wrong */
rc = MQTTAsync_setConnected(c, c, test5cConnected);
assert("Good rc from setConnectedCallback", rc == MQTTASYNC_SUCCESS, "rc was %d", rc);
/* let client c go: connect, and send disconnect command to proxy */
opts.will = &wopts;
opts.will->payload.data = "will message";
opts.will->payload.len = strlen(opts.will->payload.data) + 1;
opts.will->qos = 1;
opts.will->retained = 0;
opts.will->topicName = willTopic;
opts.onSuccess = test5cOnConnect;
opts.onFailure = test5cOnFailure;
opts.context = c;
opts.cleansession = 0;
MyLog(LOGA_DEBUG, "Connecting client c");
rc = MQTTAsync_connect(c, &opts);
assert("Good rc from connect", rc == MQTTASYNC_SUCCESS, "rc was %d ", rc);
if (rc != MQTTASYNC_SUCCESS)
{
failures++;
goto exit;
}
/* wait for will message */
while (!test5_will_message_received && ++count < 10000)
MySleep(100);
MyLog(LOGA_DEBUG, "Now we can send some messages to be buffered");
test5c_connected = 0;
/* send some messages. Then reconnect (check connected callback), and check that those messages are received */
for (i = 0; i < 5; ++i)
{
char buf[50];
MQTTAsync_message pubmsg = MQTTAsync_message_initializer;
MQTTAsync_responseOptions opts = MQTTAsync_responseOptions_initializer;
sprintf(buf, "QoS %d message", i);
pubmsg.payload = buf;
pubmsg.payloadlen = (int)(strlen(pubmsg.payload) + 1);
pubmsg.qos = i % 3;
pubmsg.retained = 0;
rc = MQTTAsync_sendMessage(c, test_topic, &pubmsg, &opts);
if (i <= 2)
assert("Good rc from sendMessage", rc == MQTTASYNC_SUCCESS, "rc was %d ", rc);
else
assert("Bad rc from sendMessage", rc == MQTTASYNC_MAX_BUFFERED_MESSAGES, "rc was %d ", rc);
}
rc = MQTTAsync_getPendingTokens(c, &tokens);
assert("Good rc from getPendingTokens", rc == MQTTASYNC_SUCCESS, "rc was %d ", rc);
i = 0;
if (tokens)
{
while (tokens[i] != -1)
++i;
MQTTAsync_free(tokens);
}
assert("Number of getPendingTokens should be 3", i == 3, "i was %d ", i);
rc = MQTTAsync_reconnect(c);
assert("Good rc from reconnect", rc == MQTTASYNC_SUCCESS, "rc was %d ", rc);
/* wait for client to be reconnected */
while (!test5c_connected && ++count < 10000)
MySleep(100);
/* wait for success or failure callback */
while (test5_messages_received < 3 && ++count < 10000)
MySleep(100);
rc = MQTTAsync_getPendingTokens(c, &tokens);
assert("Good rc from getPendingTokens", rc == MQTTASYNC_SUCCESS, "rc was %d ", rc);
i = 0;
if (tokens)
{
while (tokens[i] != -1)
++i;
MQTTAsync_free(tokens);
}
assert("Number of getPendingTokens should be 0", i == 0, "i was %d ", i);
rc = MQTTAsync_disconnect(c, NULL);
assert("Good rc from disconnect", rc == MQTTASYNC_SUCCESS, "rc was %d ", rc);
rc = MQTTAsync_disconnect(d, NULL);
assert("Good rc from disconnect", rc == MQTTASYNC_SUCCESS, "rc was %d ", rc);
exit:
MySleep(200);
MQTTAsync_destroy(&c);
MQTTAsync_destroy(&d);
MyLog(LOGA_INFO, "%s: test %s. %d tests run, %d failures.",
......@@ -1640,6 +1820,7 @@ exit:
}
void handleTrace(enum MQTTASYNC_TRACE_LEVELS level, char* message)
{
printf("%s\n", message);
......@@ -1650,7 +1831,7 @@ int main(int argc, char** argv)
{
int* numtests = &tests;
int rc = 0;
int (*tests[])() = { NULL, test1, test2, test3, test4, test5};
int (*tests[])() = { NULL, test1, test2, test3, test4, test5, test6};
sprintf(unique, "%u", rand());
MyLog(LOGA_INFO, "Random prefix/suffix is %s", unique);
......
......@@ -7,6 +7,7 @@ log_type information
#log_dest file /var/log/mosquitto/tls-testing.log
allow_anonymous true
password_file test/tls-testing/mosquitto.pw
#message_size_limit 5000000
......
test_user:$6$PY1pf+FdPmONSyhb$gC0yIykOSqj5x2rY7odzhNqLrQJ1S7dpQAgvxK+DXKquw1Yp5whSSgfcv24xTIotm3KCt1D6vcISOq/m3OhGEg==
testuser:$6$VsVwgoeK2yQI5QTo$2fSqD6qUgMvfSOQQxRm7aQH1sA2oqGmdbNFM86GBbjWja7sN5wxOQHIjk/B8PeOqmMOee5UWX2faXy+X9fPZ4w==
Admin:$6$OAKIhJgkrZUTDSbN$AmKUUznotPbGl5XaFbs8wqw4OyWFkjOgxJfJ4C/9vaknsouvR4RmsEozCee2SPwFaXSR52QRype/9+iSvU7y5w==
export TRAVIS_OS_NAME=linux
export TRAVIS_BUILD_DIR=/home/icraggs/git/paho.mqtt.c
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment