From 5811beba391baefad41cd6f8f4fa4e3862098813 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 16 Apr 2020 13:20:52 +0200 Subject: mqtt: improve the state machine To handle PUBLISH before SUBACK and more. Updated the existing tests and added three new ones. Reported-by: Christoph Krey Bug: https://curl.haxx.se/mail/lib-2020-04/0021.html Closes #5246 --- tests/data/Makefile.inc | 2 +- tests/data/test1190 | 2 +- tests/data/test1191 | 2 +- tests/data/test1192 | 2 +- tests/data/test1193 | 2 +- tests/data/test1194 | 59 +++++++++++++++++++++++++++ tests/data/test1195 | 63 +++++++++++++++++++++++++++++ tests/data/test1196 | 62 +++++++++++++++++++++++++++++ tests/server/mqttd.c | 103 ++++++++++++++++++++++++++++++++++-------------- 9 files changed, 263 insertions(+), 34 deletions(-) create mode 100644 tests/data/test1194 create mode 100644 tests/data/test1195 create mode 100644 tests/data/test1196 (limited to 'tests') diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc index 099940410..425a0c02f 100644 --- a/tests/data/Makefile.inc +++ b/tests/data/Makefile.inc @@ -139,7 +139,7 @@ test1160 test1161 test1162 test1163 test1164 test1165 test1166 test1167 \ \ test1170 test1171 test1172 test1173 test1174 test1175 test1176 test1177 \ \ -test1190 test1191 test1192 test1193 \ +test1190 test1191 test1192 test1193 test1194 test1195 test1196 \ \ test1200 test1201 test1202 test1203 test1204 test1205 test1206 test1207 \ test1208 test1209 test1210 test1211 test1212 test1213 test1214 test1215 \ diff --git a/tests/data/test1190 b/tests/data/test1190 index 491f2b843..007a15013 100644 --- a/tests/data/test1190 +++ b/tests/data/test1190 @@ -46,7 +46,7 @@ s/^(.* 00044d5154540402003c000c6375726c).*/$1/ client CONNECT 18 00044d5154540402003c000c6375726c -server CONACK 2 20020000 +server CONNACK 2 20020000 client SUBSCRIBE 9 000100043131393000 server SUBACK 3 9003000100 server PUBLISH c 300c00043131393068656c6c6f0a diff --git a/tests/data/test1191 b/tests/data/test1191 index fc8c68bb2..a36bc3113 100644 --- a/tests/data/test1191 +++ b/tests/data/test1191 @@ -42,7 +42,7 @@ s/^(.* 00044d5154540402003c000c6375726c).*/$1/ client CONNECT 18 00044d5154540402003c000c6375726c -server CONACK 2 20020000 +server CONNACK 2 20020000 client PUBLISH f 000431313931736f6d657468696e67 client DISCONNECT 0 e000 diff --git a/tests/data/test1192 b/tests/data/test1192 index 92b96c3fd..691c7783f 100644 --- a/tests/data/test1192 +++ b/tests/data/test1192 @@ -46,7 +46,7 @@ s/^(.* 00044d5154540402003c000c6375726c).*/$1/ client CONNECT 18 00044d5154540402003c000c6375726c -server CONACK 2 20020000 +server CONNACK 2 20020000 client SUBSCRIBE 80a 0001080541414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141412f3131393200 server SUBACK 3 9003000100 server PUBLISH 80d 308d10080541414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141412f3131393268656c6c6f0a diff --git a/tests/data/test1193 b/tests/data/test1193 index 479ed5fe3..8da9abb21 100644 --- a/tests/data/test1193 +++ b/tests/data/test1193 @@ -64,7 +64,7 @@ s/^(.* 00044d5154540402003c000c6375726c).*/$1/ client CONNECT 18 00044d5154540402003c000c6375726c -server CONACK 2 20020000 +server CONNACK 2 20020000 client PUBLISH 7c2 000431313933313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839 client DISCONNECT 0 e000 diff --git a/tests/data/test1194 b/tests/data/test1194 new file mode 100644 index 000000000..497891add --- /dev/null +++ b/tests/data/test1194 @@ -0,0 +1,59 @@ + + + +MQTT +MQTT SUBSCRIBE + + + +# +# Server-side + + +hello + + +00 04 31 31 39 30 68 65 6c 6c 6f 5b 4c 46 5d 0a + + +PUBLISH-before-SUBACK TRUE + + + +# +# Client-side + + +mqtt + + +mqtt + + +MQTT SUBSCRIBE with PUBLISH befoire SUBACK + + +mqtt://%HOSTIP:%MQTTPORT/1194 + + + +# +# Verify data after the test has been "shot" + +# These are hexadecimal protocol dumps from the client +# +# Strip out the random part of the client id from the CONNECT message +# before comparison + +s/^(.* 00044d5154540402003c000c6375726c).*/$1/ + + +client CONNECT 18 00044d5154540402003c000c6375726c +server CONNACK 2 20020000 +client SUBSCRIBE 9 000100043131393400 +server PUBLISH c 300c00043131393468656c6c6f0a +server SUBACK 3 9003000100 +server DISCONNECT 0 e000 + + + diff --git a/tests/data/test1195 b/tests/data/test1195 new file mode 100644 index 000000000..0dfaccd53 --- /dev/null +++ b/tests/data/test1195 @@ -0,0 +1,63 @@ + + + +MQTT +MQTT SUBSCRIBE + + + +# +# Server-side + + +hello + + +00 04 31 31 39 30 68 65 6c 6c 6f 5b 4c 46 5d 0a + + +PUBLISH-before-SUBACK TRUE +short-PUBLISH TRUE + + + +# +# Client-side + + +mqtt + + +mqtt + + +MQTT SUBSCRIBE with short PUBLISH + + +mqtt://%HOSTIP:%MQTTPORT/1195 + + + +# +# Verify data after the test has been "shot" + +# These are hexadecimal protocol dumps from the client +# +# Strip out the random part of the client id from the CONNECT message +# before comparison + +s/^(.* 00044d5154540402003c000c6375726c).*/$1/ + + +client CONNECT 18 00044d5154540402003c000c6375726c +server CONNACK 2 20020000 +client SUBSCRIBE 9 000100043131393500 +server PUBLISH c 300c00043131393568656c6c + + +# 18 is CURLE_PARTIAL_FILE + +18 + + + diff --git a/tests/data/test1196 b/tests/data/test1196 new file mode 100644 index 000000000..c07efd927 --- /dev/null +++ b/tests/data/test1196 @@ -0,0 +1,62 @@ + + + +MQTT +MQTT SUBSCRIBE + + + +# +# Server-side + + +hello + + +00 04 31 31 39 30 68 65 6c 6c 6f 5b 4c 46 5d 0a + + +# error 1 - "Connection Refused, unacceptable protocol version" + +error-CONNACK 1 + + + +# +# Client-side + + +mqtt + + +mqtt + + +MQTT with error in CONNACK + + +mqtt://%HOSTIP:%MQTTPORT/1196 + + + +# +# Verify data after the test has been "shot" + +# These are hexadecimal protocol dumps from the client +# +# Strip out the random part of the client id from the CONNECT message +# before comparison + +s/^(.* 00044d5154540402003c000c6375726c).*/$1/ + + +client CONNECT 18 00044d5154540402003c000c6375726c +server CONNACK 2 20020001 + + +# 8 is CURLE_WEIRD_SERVER_REPLY + +8 + + + diff --git a/tests/server/mqttd.c b/tests/server/mqttd.c index db5723cdd..6785b0014 100644 --- a/tests/server/mqttd.c +++ b/tests/server/mqttd.c @@ -104,6 +104,10 @@ struct configurable { unsigned char version; /* initial version byte in the request must match this */ + bool publish_before_suback; + bool short_publish; + unsigned char error_connack; + int testnum; }; #define REQUEST_DUMP "log/server.input" @@ -124,6 +128,10 @@ static void resetdefaults(void) { logmsg("Reset to defaults"); config.version = CONFIG_VERSION; + config.publish_before_suback = FALSE; + config.short_publish = FALSE; + config.error_connack = 0; + config.testnum = 0; } static unsigned char byteval(char *value) @@ -147,10 +155,29 @@ static void getconfig(void) config.version = byteval(value); logmsg("version [%d] set", config.version); } + else if(!strcmp(key, "PUBLISH-before-SUBACK")) { + logmsg("PUBLISH-before-SUBACK set"); + config.publish_before_suback = TRUE; + } + else if(!strcmp(key, "short-PUBLISH")) { + logmsg("short-PUBLISH set"); + config.short_publish = TRUE; + } + else if(!strcmp(key, "error-CONNACK")) { + config.error_connack = byteval(value); + logmsg("error-CONNACK = %d", config.error_connack); + } + else if(!strcmp(key, "Testnum")) { + config.testnum = atoi(value); + logmsg("testnum = %d", config.testnum); + } } } fclose(fp); } + else { + logmsg("No config file '%s' to read", configfile); + } } static void loghex(unsigned char *buffer, ssize_t len) @@ -209,11 +236,17 @@ static int connack(FILE *dump, curl_socket_t fd) MQTT_MSG_CONNACK, 0x02, 0x00, 0x00 }; - ssize_t rc = swrite(fd, (char *)packet, sizeof(packet)); - if(rc == sizeof(packet)) { - logmsg("WROTE %d bytes [CONACK]", rc); + ssize_t rc; + + packet[3] = config.error_connack; + + rc = swrite(fd, (char *)packet, sizeof(packet)); + if(rc > 0) { + logmsg("WROTE %d bytes [CONNACK]", rc); loghex(packet, rc); - logprotocol(FROM_SERVER, "CONACK", 2, dump, packet, sizeof(packet)); + logprotocol(FROM_SERVER, "CONNACK", 2, dump, packet, sizeof(packet)); + } + if(rc == sizeof(packet)) { return 0; } return 1; @@ -360,6 +393,7 @@ static int publish(FILE *dump, size_t payloadindex; ssize_t remaininglength = topiclen + 2 + payloadlen; ssize_t packetlen; + ssize_t sendamount; ssize_t rc; char rembuffer[4]; int encodedlen; @@ -385,13 +419,18 @@ static int publish(FILE *dump, payloadindex = 3 + topiclen + encodedlen; memcpy(&packet[payloadindex], payload, payloadlen); - rc = swrite(fd, (char *)packet, packetlen); - if(rc == packetlen) { + sendamount = packetlen; + if(config.short_publish) + sendamount -= 2; + + rc = swrite(fd, (char *)packet, sendamount); + if(rc > 0) { logmsg("WROTE %d bytes [PUBLISH]", rc); loghex(packet, rc); logprotocol(FROM_SERVER, "PUBLISH", remaininglength, dump, packet, rc); - return 0; } + if(rc == packetlen) + return 0; return 1; } @@ -459,6 +498,11 @@ static curl_socket_t mqttit(curl_socket_t fd) getconfig(); + testno = config.testnum; + + if(testno) + logmsg("Found test number %ld", testno); + do { /* get the fixed header */ rc = fixedheader(fd, &byte, &remaining_length, &bytes); @@ -506,8 +550,10 @@ static curl_socket_t mqttit(curl_socket_t fd) } } else if(byte == MQTT_MSG_SUBSCRIBE) { - char *testnop; - + FILE *stream; + int error; + char *data; + size_t datalen; logprotocol(FROM_CLIENT, "SUBSCRIBE", remaining_length, dump, buffer, rc); logmsg("Incoming SUBSCRIBE"); @@ -533,26 +579,25 @@ static curl_socket_t mqttit(curl_socket_t fd) /* there's a QoS byte (two bits) after the topic */ logmsg("SUBSCRIBE to '%s' [%d]", topic, packet_id); - if(suback(dump, fd, packet_id)) { - logmsg("failed sending SUBACK"); - goto end; - } - testnop = strrchr(topic, '/'); - if(!testnop) - testnop = topic; - else - testnop++; /* pass the slash */ - testno = strtol(testnop, NULL, 10); - if(testno) { - FILE *stream; - int error; - char *data; - size_t datalen; - logmsg("Found test number %ld", testno); - stream = test2fopen(testno); - error = getpart(&data, &datalen, "reply", "data", stream); - if(!error) - publish(dump, fd, packet_id, topic, data, datalen); + stream = test2fopen(testno); + error = getpart(&data, &datalen, "reply", "data", stream); + if(!error) { + if(!config.publish_before_suback) { + if(suback(dump, fd, packet_id)) { + logmsg("failed sending SUBACK"); + goto end; + } + } + if(publish(dump, fd, packet_id, topic, data, datalen)) { + logmsg("PUBLISH failed"); + goto end; + } + if(config.publish_before_suback) { + if(suback(dump, fd, packet_id)) { + logmsg("failed sending SUBACK"); + goto end; + } + } } else { char *def = (char *)"this is random payload yes yes it is"; -- cgit v1.2.3