/** * Deserializes the supplied (wire) buffer into unsubscribe data * @param dup integer returned - the MQTT dup flag * @param packetid integer returned - the MQTT packet identifier * @param maxcount - the maximum number of members allowed in the topicFilters and requestedQoSs arrays * @param count - number of members in the topicFilters and requestedQoSs arrays * @param topicFilters - array of topic filter names * @param buf the raw buffer data, of the correct length determined by the remaining length field * @param buflen the length in bytes of the data in the supplied buffer * @return the length of the serialized data. <= 0 indicates error */ int MQTTDeserialize_unsubscribe(unsigned char* dup, unsigned short* packetid, int maxcount, int* count, MQTTString topicFilters[], unsigned char* buf, int len) { MQTTHeader header = {0}; unsigned char* curdata = buf; unsigned char* enddata = NULL; int rc = 0; int mylen = 0; header.byte = readChar(&curdata); if (header.bits.type != UNSUBSCRIBE) goto exit; *dup = header.bits.dup; curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */ enddata = curdata + mylen; *packetid = readInt(&curdata); *count = 0; while (curdata < enddata) { if (!readMQTTLenString(&topicFilters[*count], &curdata, enddata)) goto exit; (*count)++; } rc = 1; exit: return rc; }
/** * Deserializes the supplied (wire) buffer into publish data * @param dup returned integer - the MQTT dup flag * @param qos returned integer - the MQTT QoS value * @param retained returned integer - the MQTT retained flag * @param packetid returned integer - the MQTT packet identifier * @param topicName returned MQTTString - the MQTT topic in the publish * @param payload returned byte buffer - the MQTT publish payload * @param payloadlen returned integer - the length of the MQTT payload * @param buf the raw buffer data, of the correct length determined by the remaining length field * @param buflen the length in bytes of the data in the supplied buffer * @return error code. 1 is success */ int MQTTDeserialize_publish(unsigned char* dup, int* qos, unsigned char* retained, unsigned short* packetid, MQTTString* topicName, unsigned char** payload, int* payloadlen, unsigned char* buf, int buflen) { MQTTHeader header = {0}; unsigned char* curdata = buf; unsigned char* enddata = NULL; int rc = 0; int mylen = 0; header.byte = readChar(&curdata); if (header.bits.type != PUBLISH) goto exit; *dup = header.bits.dup; *qos = header.bits.qos; *retained = header.bits.retain; curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */ enddata = curdata + mylen; if (!readMQTTLenString(topicName, &curdata, enddata) || enddata - curdata < 0) /* do we have enough data to read the protocol version byte? */ goto exit; if (*qos > 0) *packetid = readInt(&curdata); *payloadlen = enddata - curdata; *payload = curdata; rc = 1; exit: return rc; }
/** * Deserializes the supplied (wire) buffer into unsubscribe data * @param dup integer returned - the MQTT dup flag * @param packetid integer returned - the MQTT packet identifier * @param maxcount - the maximum number of members allowed in the topicFilters and requestedQoSs arrays * @param count - number of members in the topicFilters and requestedQoSs arrays * @param topicFilters - array of topic filter names * @param buf the raw buffer data, of the correct length determined by the remaining length field * @param buflen the length in bytes of the data in the supplied buffer * @return the length of the serialized data. <= 0 indicates error */ int MQTTDeserialize_unsubscribe(int* dup, int* packetid, int maxcount, int* count, MQTTString topicFilters[], char* buf, int len) { MQTTHeader header; char* curdata = buf; char* enddata = NULL; int rc = 0; int mylen = 0; FUNC_ENTRY; header.byte = readChar(&curdata); *dup = header.bits.dup; curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */ enddata = curdata + mylen; *packetid = readInt(&curdata); *count = 0; while (curdata < enddata) { if (!readMQTTLenString(&topicFilters[*count], &curdata, enddata)) goto exit; (*count)++; } rc = 1; exit: FUNC_EXIT_RC(rc); return rc; }
/** * Deserializes the supplied (wire) buffer into connect data structure * @param data the connect data structure to be filled out * @param buf the raw buffer data, of the correct length determined by the remaining length field * @param len the length in bytes of the data in the supplied buffer * @return error code. 1 is success, 0 is failure */ int MQTTDeserialize_connect( MQTTPacket_connectData* data, unsigned char* buf, int len ) { MQTTHeader header = { 0 }; MQTTConnectFlags flags = { 0 }; unsigned char* curdata = buf; unsigned char* enddata = &buf[ len ]; int rc = 0; MQTTString Protocol; int version; int mylen = 0; FUNC_ENTRY; header.byte = readChar( &curdata ); if ( header.bits.type != CONNECT ) goto exit; curdata += MQTTPacket_decodeBuf( curdata, &mylen ); /* read remaining length */ if ( !readMQTTLenString( &Protocol, &curdata, enddata ) || enddata - curdata < 0 ) /* do we have enough data to read the protocol version byte? */ goto exit; version = (int) readChar( &curdata ); /* Protocol version */ /* If we don't recognize the protocol version, we don't parse the connect packet on the * basis that we don't know what the format will be. */ if ( MQTTPacket_checkVersion( &Protocol, version ) ) { flags.all = readChar( &curdata ); data->cleansession = flags.bits.cleansession; data->keepAliveInterval = readInt( &curdata ); if ( !readMQTTLenString( &data->clientID, &curdata, enddata ) ) goto exit; data->willFlag = flags.bits.will; if ( flags.bits.will ) { data->will.qos = flags.bits.willQoS; data->will.retained = flags.bits.willRetain; if ( !readMQTTLenString( &data->will.topicName, &curdata, enddata ) || !readMQTTLenString( &data->will.message, &curdata, enddata ) ) goto exit; } if ( flags.bits.username ) { if ( enddata - curdata < 3 || !readMQTTLenString( &data->username, &curdata, enddata ) ) goto exit; /* username flag set, but no username supplied - invalid */ if ( flags.bits.password && ( enddata - curdata < 3 || !readMQTTLenString( &data->password, &curdata, enddata ) ) ) goto exit; /* password flag set, but no password supplied - invalid */ } else if ( flags.bits.password ) goto exit; /* password flag set without username - invalid */ rc = 1; } exit: FUNC_EXIT_RC(rc); return rc; }
int MQTTDeserialize_publish(MQTTFixedHeaderPlusMsgId *fixedHeaderPlusMsgId, MQTTString* topicName, unsigned char** payload, int* payloadlen, unsigned char* buf, int buflen) { MQTTHeader header = {0}; unsigned char* curdata = buf; unsigned char* enddata = NULL; int rc = FAILURE; int mylen = 0; FUNC_ENTRY; header.byte = readChar(&curdata); if (header.bits.type != PUBLISH) goto exit; fillFixedHeaderFieldsFromPacketHeader(&(fixedHeaderPlusMsgId->fixedHeader), &header); curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */ enddata = curdata + mylen; if (!readMQTTLenString(topicName, &curdata, enddata) || enddata - curdata < 0) /* do we have enough data to read the protocol version byte? */ goto exit; if ((fixedHeaderPlusMsgId->fixedHeader).qos > 0) fixedHeaderPlusMsgId->msgId = readInt(&curdata); *payloadlen = enddata - curdata; *payload = curdata; rc = SUCCESS; exit: FUNC_EXIT_RC(rc); return rc; }
/** * Deserializes the supplied (wire) buffer into subscribe data * @param dup integer returned - the MQTT dup flag * @param packetid integer returned - the MQTT packet identifier * @param maxcount - the maximum number of members allowed in the topicFilters and requestedQoSs arrays * @param count - number of members in the topicFilters and requestedQoSs arrays * @param topicFilters - array of topic filter names * @param requestedQoSs - array of requested QoS * @param buf the raw buffer data, of the correct length determined by the remaining length field * @param buflen the length in bytes of the data in the supplied buffer * @return the length of the serialized data. <= 0 indicates error */ int MQTTDeserialize_subscribe(unsigned char* dup, unsigned short* packetid, int maxcount, int* count, MQTTString topicFilters[], int requestedQoSs[], unsigned char* buf, int buflen) { MQTTHeader header = {0}; unsigned char* curdata = buf; unsigned char* enddata = NULL; int rc = -1; int mylen = 0; FUNC_ENTRY; header.byte = readChar(&curdata); if (header.bits.type != SUBSCRIBE) goto exit; *dup = header.bits.dup; curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */ enddata = curdata + mylen; *packetid = readInt(&curdata); *count = 0; while (curdata < enddata) { if (!readMQTTLenString(&topicFilters[*count], &curdata, enddata)) goto exit; if (curdata >= enddata) /* do we have enough data to read the req_qos version byte? */ goto exit; requestedQoSs[*count] = readChar(&curdata); (*count)++; } rc = 1; exit: FUNC_EXIT_RC(rc); return rc; }
/** * Deserializes the supplied (wire) buffer into publish data * @param dup returned integer - the MQTT dup flag * @param qos returned integer - the MQTT QoS value * @param retained returned integer - the MQTT retained flag * @param packetid returned integer - the MQTT packet identifier * @param topicName returned MQTTString - the MQTT topic in the publish * @param payload returned byte buffer - the MQTT publish payload * @param payloadlen returned integer - the length of the MQTT payload * @param buf the raw buffer data, of the correct length determined by the remaining length field * @param buflen the length in bytes of the data in the supplied buffer * @return error code. 1 is success */ MQTTReturnCode MQTTDeserialize_publish(unsigned char *dup, QoS *qos, unsigned char *retained, uint16_t *packetid, MQTTString* topicName, unsigned char **payload, uint32_t *payloadlen, unsigned char *buf, size_t buflen) { MQTTHeader header = {0}; unsigned char *curdata = buf; unsigned char *enddata = NULL; MQTTReturnCode rc = FAILURE; uint32_t decodedLen = 0; uint32_t readBytesLen = 0; FUNC_ENTRY; if(NULL == dup || NULL == qos || NULL == retained || NULL == packetid) { FUNC_EXIT_RC(FAILURE); return FAILURE; } /* Publish header size is at least four bytes. * Fixed header is two bytes. * Variable header size depends on QoS And Topic Name. * QoS level 0 doesn't have a message identifier (0 - 2 bytes) * Topic Name length fields decide size of topic name field (at least 2 bytes) * MQTT v3.1.1 Specification 3.3.1 */ if(4 > buflen) { FUNC_EXIT_RC(MQTTPACKET_BUFFER_TOO_SHORT); return MQTTPACKET_BUFFER_TOO_SHORT; } header.byte = readChar(&curdata); if(PUBLISH != header.bits.type) { FUNC_EXIT_RC(FAILURE); return FAILURE; } *dup = header.bits.dup; *qos = (QoS)header.bits.qos; *retained = header.bits.retain; /* read remaining length */ rc = MQTTPacket_decodeBuf(curdata, &decodedLen, &readBytesLen); if(SUCCESS != rc) { FUNC_EXIT_RC(rc); return rc; } curdata += (readBytesLen); enddata = curdata + decodedLen; /* do we have enough data to read the protocol version byte? */ if(SUCCESS != readMQTTLenString(topicName, &curdata, enddata) || (0 > (enddata - curdata))) { FUNC_EXIT_RC(FAILURE); return FAILURE; } if(QOS0 != *qos) { *packetid = readPacketId(&curdata); } *payloadlen = (uint32_t)(enddata - curdata); *payload = curdata; FUNC_EXIT_RC(SUCCESS); return SUCCESS; }