/** * Sends an MQTT packet from multiple buffers in one system call write * @param socket the socket to which to write the data * @param header the one-byte MQTT header * @param count the number of buffers * @param buffers the rest of the buffers to write (not including remaining length) * @param buflens the lengths of the data in the array of buffers to be written * @return the completion code (TCPSOCKET_COMPLETE etc) */ int MQTTPacket_sends(int socket, Header header, int count, char** buffers, int* buflens) { int i, rc, buf0len, total = 0; char *buf; FUNC_ENTRY; buf = malloc(10); buf[0] = header.byte; for (i = 0; i < count; i++) total += buflens[i]; buf0len = 1 + MQTTPacket_encode(&buf[1], total); #if !defined(NO_PERSISTENCE) if (header.bits.type == PUBLISH && header.bits.qos != 0) { /* persist PUBLISH QoS1 and Qo2 */ char *ptraux = buffers[2]; int msgId = readInt(&ptraux); rc = MQTTPersistence_put(socket, buf, buf0len, count, buffers, buflens, header.bits.type, msgId, 0); } #endif rc = Socket_putdatas(socket, buf, buf0len, count, buffers, buflens); if (rc != TCPSOCKET_INTERRUPTED) free(buf); FUNC_EXIT_RC(rc); return rc; }
/** * Sends an MQTT packet in one system call write * @param socket the socket to which to write the data * @param header the one-byte MQTT header * @param buffer the rest of the buffer to write (not including remaining length) * @param buflen the length of the data in buffer to be written * @return the completion code (TCPSOCKET_COMPLETE etc) */ int MQTTPacket_send(int socket, Header header, char* buffer, int buflen) { int rc, buf0len; char *buf; FUNC_ENTRY; buf = malloc(10); buf[0] = header.byte; buf0len = 1 + MQTTPacket_encode(&buf[1], buflen); #if !defined(NO_PERSISTENCE) if (header.bits.type == PUBREL) { char* ptraux = buffer; int msgId = readInt(&ptraux); rc = MQTTPersistence_put(socket, buf, buf0len, 1, &buffer, &buflen, header.bits.type, msgId, 0); } #endif rc = Socket_putdatas(socket, buf, buf0len, 1, &buffer, &buflen); if (rc != TCPSOCKET_INTERRUPTED) free(buf); FUNC_EXIT_RC(rc); return rc; }
/** * Sends an MQTT packet from multiple buffers in one system call write * @param socket the socket to which to write the data * @param header the one-byte MQTT header * @param count the number of buffers * @param buffers the rest of the buffers to write (not including remaining length) * @param buflens the lengths of the data in the array of buffers to be written * @return the completion code (TCPSOCKET_COMPLETE etc) */ int MQTTPacket_sends(networkHandles* net, Header header, int count, char** buffers, size_t* buflens, int* frees) { int i, rc, buf0len, total = 0; char *buf; FUNC_ENTRY; buf = malloc(10); buf[0] = header.byte; for (i = 0; i < count; i++) total += buflens[i]; buf0len = 1 + MQTTPacket_encode(&buf[1], total); #if !defined(NO_PERSISTENCE) if (header.bits.type == PUBLISH && header.bits.qos != 0) { /* persist PUBLISH QoS1 and Qo2 */ char *ptraux = buffers[2]; int msgId = readInt(&ptraux); rc = MQTTPersistence_put(net->socket, buf, buf0len, count, buffers, buflens, header.bits.type, msgId, 0); } #endif #if defined(OPENSSL) if (net->ssl) rc = SSLSocket_putdatas(net->ssl, net->socket, buf, buf0len, count, buffers, buflens, frees); else #endif rc = Socket_putdatas(net->socket, buf, buf0len, count, buffers, buflens, frees); if (rc == TCPSOCKET_COMPLETE) time(&(net->lastSent)); if (rc != TCPSOCKET_INTERRUPTED) free(buf); FUNC_EXIT_RC(rc); return rc; }
/** * Sends an MQTT packet in one system call write * @param socket the socket to which to write the data * @param header the one-byte MQTT header * @param buffer the rest of the buffer to write (not including remaining length) * @param buflen the length of the data in buffer to be written * @return the completion code (TCPSOCKET_COMPLETE etc) */ int MQTTPacket_send(networkHandles* net, Header header, char* buffer, size_t buflen, int free) { int rc, buf0len; char *buf; FUNC_ENTRY; buf = malloc(10); buf[0] = header.byte; buf0len = 1 + MQTTPacket_encode(&buf[1], buflen); #if !defined(NO_PERSISTENCE) if (header.bits.type == PUBREL) { char* ptraux = buffer; int msgId = readInt(&ptraux); rc = MQTTPersistence_put(net->socket, buf, buf0len, 1, &buffer, &buflen, header.bits.type, msgId, 0); } #endif #if defined(OPENSSL) if (net->ssl) rc = SSLSocket_putdatas(net->ssl, net->socket, buf, buf0len, 1, &buffer, &buflen, &free); else #endif rc = Socket_putdatas(net->socket, buf, buf0len, 1, &buffer, &buflen, &free); if (rc == TCPSOCKET_COMPLETE) time(&(net->lastSent)); if (rc != TCPSOCKET_INTERRUPTED) free(buf); FUNC_EXIT_RC(rc); 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; }
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; }