diff --git a/Adafruit_MQTT.cpp b/Adafruit_MQTT.cpp index fc6c416..a38ec80 100644 --- a/Adafruit_MQTT.cpp +++ b/Adafruit_MQTT.cpp @@ -96,6 +96,22 @@ static uint8_t *stringprint(uint8_t *p, const char *s, uint16_t maxlen = 0) { return p + len; } +// packetAdditionalLen is a helper function used to figure out +// how bigger the payload needs to be in order to account for +// its variable length field. As per +// http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Table_2.4_Size +// See also readFullPacket +static uint16_t packetAdditionalLen(uint32_t currLen) { + /* Increase length field based on current length */ + if (currLen < 128) // 7-bits + return 0; + if (currLen < 16384) // 14-bits + return 1; + if (currLen < 2097152) // 21-bits + return 2; + return 3; +} + // Adafruit_MQTT Definition //////////////////////////////////////////////////// Adafruit_MQTT::Adafruit_MQTT(const char *server, uint16_t port, const char *cid, @@ -233,7 +249,7 @@ uint16_t Adafruit_MQTT::readFullPacket(uint8_t *buffer, uint16_t maxsize, // will read a packet and Do The Right Thing with length uint8_t *pbuff = buffer; - uint8_t rlen; + uint16_t rlen; // read the packet type: rlen = readPacket(pbuff, 1, timeout); @@ -267,7 +283,8 @@ uint16_t Adafruit_MQTT::readFullPacket(uint8_t *buffer, uint16_t maxsize, DEBUG_PRINT(F("Packet Length:\t")); DEBUG_PRINTLN(value); - if (value > (maxsize - (pbuff - buffer) - 1)) { + // maxsize is limited to 65536 by 16-bit unsigned + if (value > uint32_t(maxsize - (pbuff - buffer) - 1)) { DEBUG_PRINTLN(F("Packet too big for buffer")); rlen = readPacket(pbuff, (maxsize - (pbuff - buffer) - 1), timeout); } else { @@ -492,7 +509,9 @@ Adafruit_MQTT_Subscribe *Adafruit_MQTT::handleSubscriptionPacket(uint16_t len) { } // Parse out length of packet. - topiclen = buffer[3]; + uint16_t const topicoffset = packetAdditionalLen(len); + uint16_t const topicstart = topicoffset + 4; + topiclen = buffer[3 + topicoffset]; DEBUG_PRINT(F("Looking for subscription len ")); DEBUG_PRINTLN(topiclen); @@ -505,8 +524,8 @@ Adafruit_MQTT_Subscribe *Adafruit_MQTT::handleSubscriptionPacket(uint16_t len) { continue; // Stop if the subscription topic matches the received topic. Be careful // to make comparison case insensitive. - if (strncasecmp((char *)buffer + 4, subscriptions[i]->topic, topiclen) == - 0) { + if (strncasecmp((char *)buffer + topicstart, subscriptions[i]->topic, + topiclen) == 0) { DEBUG_PRINT(F("Found sub #")); DEBUG_PRINTLN(i); break; @@ -521,21 +540,21 @@ Adafruit_MQTT_Subscribe *Adafruit_MQTT::handleSubscriptionPacket(uint16_t len) { // Check if it is QoS 1, TODO: we dont support QoS 2 if ((buffer[0] & 0x6) == 0x2) { packet_id_len = 2; - packetid = buffer[topiclen + 4]; + packetid = buffer[topiclen + topicstart]; packetid <<= 8; - packetid |= buffer[topiclen + 5]; + packetid |= buffer[topiclen + topicstart + 1]; } // zero out the old data memset(subscriptions[i]->lastread, 0, SUBSCRIPTIONDATALEN); - datalen = len - topiclen - packet_id_len - 4; + datalen = len - topiclen - packet_id_len - topicstart; if (datalen > SUBSCRIPTIONDATALEN) { datalen = SUBSCRIPTIONDATALEN - 1; // cut it off } // extract out just the data, into the subscription object itself - memmove(subscriptions[i]->lastread, buffer + 4 + topiclen + packet_id_len, - datalen); + memmove(subscriptions[i]->lastread, + buffer + topicstart + topiclen + packet_id_len, datalen); subscriptions[i]->datalen = datalen; DEBUG_PRINT(F("Data len: ")); DEBUG_PRINTLN(datalen); @@ -669,21 +688,6 @@ uint8_t Adafruit_MQTT::connectPacket(uint8_t *packet) { return len; } -// packetAdditionalLen is a helper function used to figure out -// how bigger the payload needs to be in order to account for -// its variable length field. As per -// http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Table_2.4_Size -static uint16_t packetAdditionalLen(uint16_t currLen) { - /* Increase length field based on current length */ - if (currLen < 128) - return 0; - if (currLen < 16384) - return 1; - if (currLen < 2097151) - return 2; - return 3; -} - // as per // http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718040 uint16_t Adafruit_MQTT::publishPacket(uint8_t *packet, const char *topic, diff --git a/Adafruit_MQTT_Client.cpp b/Adafruit_MQTT_Client.cpp index 560ef46..9aa136c 100644 --- a/Adafruit_MQTT_Client.cpp +++ b/Adafruit_MQTT_Client.cpp @@ -83,17 +83,18 @@ uint16_t Adafruit_MQTT_Client::readPacket(uint8_t *buffer, uint16_t maxlen, bool Adafruit_MQTT_Client::sendPacket(uint8_t *buffer, uint16_t len) { uint16_t ret = 0; - + uint16_t offset = 0; while (len > 0) { if (client->connected()) { // send 250 bytes at most at a time, can adjust this later based on Client uint16_t sendlen = len > 250 ? 250 : len; // Serial.print("Sending: "); Serial.println(sendlen); - ret = client->write(buffer, sendlen); + ret = client->write(buffer + offset, sendlen); DEBUG_PRINT(F("Client sendPacket returned: ")); DEBUG_PRINTLN(ret); len -= ret; + offset += ret; if (ret != sendlen) { DEBUG_PRINTLN("Failed to send packet."); diff --git a/library.properties b/library.properties index 230e502..d544748 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Adafruit MQTT Library -version=2.2.0 +version=2.3.0 author=Adafruit maintainer=Adafruit sentence=MQTT library that supports the FONA, ESP8266, Yun, and generic Arduino Client hardware.