/** * Helper function to read packet data from some source into a buffer * @param buf the buffer into which the packet will be serialized * @param buflen the length in bytes of the supplied buffer * @param getfn pointer to a function which will read any number of bytes from the needed source * @return integer MQTT packet type, or -1 on error */ int MQTTPacket_read(unsigned char* buf, int buflen, int (*getfn)(unsigned char*, int)) { int rc = -1; MQTTHeader header = {0}; int len = 0; int rem_len = 0; /* 1. read the header byte. This has the packet type in it */ if ((*getfn)(buf, 1) != 1) goto exit; len = 1; /* 2. read the remaining length. This is variable in itself */ MQTTPacket_decode(getfn, &rem_len); len += MQTTPacket_encode(buf + 1, rem_len); /* put the original remaining length back into the buffer */ /* 3. read the rest of the buffer using a callback to supply the rest of the data */ if ((*getfn)(buf + len, rem_len) != rem_len) goto exit; header.byte = buf[0]; rc = header.bits.type; exit: return rc; }
/** * Reads one MQTT packet from a socket. * @param socket a socket from which to read an MQTT packet * @param error pointer to the error code which is completed if no packet is returned * @return the packet structure or NULL if there was an error */ void* MQTTPacket_Factory(int socket, int* error) { char* data = NULL; static Header header; int remaining_length, ptype; void* pack = NULL; int actual_len = 0; FUNC_ENTRY; *error = SOCKET_ERROR; /* indicate whether an error occurred, or not */ /* read the packet data from the socket */ if ((*error = Socket_getch(socket, &(header.byte))) != TCPSOCKET_COMPLETE) /* first byte is the header byte */ goto exit; /* packet not read, *error indicates whether SOCKET_ERROR occurred */ /* now read the remaining length, so we know how much more to read */ if ((*error = MQTTPacket_decode(socket, &remaining_length)) != TCPSOCKET_COMPLETE) goto exit; /* packet not read, *error indicates whether SOCKET_ERROR occurred */ /* now read the rest, the variable header and payload */ if ((data = Socket_getdata(socket, remaining_length, &actual_len)) == NULL) { *error = SOCKET_ERROR; goto exit; /* socket error */ } if (actual_len != remaining_length) *error = TCPSOCKET_INTERRUPTED; else { ptype = header.bits.type; if (ptype < CONNECT || ptype > DISCONNECT || new_packets[ptype] == NULL) Log(TRACE_MIN, 2, NULL, ptype); else { if ((pack = (*new_packets[ptype])(header.byte, data, remaining_length)) == NULL) *error = BAD_MQTT_PACKET; #if !defined(NO_PERSISTENCE) else if (header.bits.type == PUBLISH && header.bits.qos == 2) { int buf0len; char *buf = malloc(10); buf[0] = header.byte; buf0len = 1 + MQTTPacket_encode(&buf[1], remaining_length); *error = MQTTPersistence_put(socket, buf, buf0len, 1, &data, &remaining_length, header.bits.type, ((Publish *)pack)->msgId, 1); free(buf); } #endif } } exit: FUNC_EXIT_RC(*error); return pack; }
MQTTReturnCode MQTTPacket_decodeBuf(unsigned char *buf, uint32_t *value, uint32_t *readBytesLen) { bufptr = buf; return MQTTPacket_decode(bufchar, value, readBytesLen); }
int MQTTPacket_decodeBuf(unsigned char* buf, int* value) { bufptr = buf; return MQTTPacket_decode(bufchar, value); }
void* MQTTPacket_Factory(networkHandles* net, int* error) { static Header header; int ptype; void* pack = NULL; FUNC_ENTRY; *error = SOCKET_ERROR; // Indicate whether an error occurred, or not /* read the packet data from the socket */ #if defined(OPENSSL) *error = (net->ssl) ? SSLSocket_getch(net->ssl, net->socket, &header.byte) : Socket_getch(net->socket, &header.byte); #else *error = Socket_getch(net->socket, &header.byte); #endif if (*error != TCPSOCKET_COMPLETE) { // First byte is the header byte goto exit; // packet not read, *error indicates whether SOCKET_ERROR occurred. } // Now read the remaining length, so we know how much more to read size_t remaining_length; if ((*error = MQTTPacket_decode(net, &remaining_length)) != TCPSOCKET_COMPLETE) { goto exit; // Packet not read, *error indicates whether SOCKET_ERROR occurred. } // Now read the rest, the variable header and payload. size_t actual_len = 0; #if defined(OPENSSL) char* data = (net->ssl) ? SSLSocket_getdata(net->ssl, net->socket, remaining_length, &actual_len) : Socket_getdata(net->socket, remaining_length, &actual_len); #else char* data = Socket_getdata(net->socket, remaining_length, &actual_len); #endif if (data == NULL) { *error = SOCKET_ERROR; goto exit; // Socket error } if (actual_len != remaining_length) { *error = TCPSOCKET_INTERRUPTED; } else { ptype = header.bits.type; if (ptype < CONNECT || ptype > DISCONNECT || new_packets[ptype] == NULL) Log(TRACE_MIN, 2, NULL, ptype); else { if ((pack = (*new_packets[ptype])(header.byte, data, remaining_length)) == NULL) *error = BAD_MQTT_PACKET; #if !defined(NO_PERSISTENCE) else if (header.bits.type == PUBLISH && header.bits.qos == 2) { int buf0len; char *buf = malloc(10); buf[0] = header.byte; buf0len = 1 + MQTTPacket_encode(&buf[1], remaining_length); size_t remaining_length_new = remaining_length; *error = MQTTPersistence_put(net->socket, buf, buf0len, 1, &data, &remaining_length_new, header.bits.type, ((Publish *)pack)->msgId, 1); free(buf); } #endif } } if (pack) time(&(net->lastReceived)); exit: FUNC_EXIT_RC(*error); return pack; }