/*---------------------------------------------------------------------------*/ static PT_THREAD(pingreq_pt(struct pt* pt, struct mqtt_connection* conn)) { PT_BEGIN(pt); DBG("MQTT - Sending PINGREQ\r\n"); /* Write Fixed Header */ PT_MQTT_WRITE_BYTE(conn, MQTT_FHDR_MSG_TYPE_PINGREQ); PT_MQTT_WRITE_BYTE(conn, 0); send_out_buffer(conn); PT_WAIT_UNTIL(pt, conn->out_buffer_sent); /* Start timeout for reply. */ conn->waiting_for_pingresp = 1; /* Wait for PINGRESP * * Note that the timeout disconnect is handle in the timer callback. */ reset_packet(&conn->in_packet); do { PT_WAIT_UNTIL(pt, conn->in_packet.packet_received); } while((conn->in_packet.fhdr & 0xF0) != MQTT_FHDR_MSG_TYPE_PINGRESP); reset_packet(&conn->in_packet); conn->waiting_for_pingresp = 0; PT_END(pt); }
/*---------------------------------------------------------------------------*/ static PT_THREAD(pingreq_pt(struct pt *pt, struct mqtt_connection *conn)) { PT_BEGIN(pt); DBG("MQTT - Sending PINGREQ\n"); /* Write Fixed Header */ PT_MQTT_WRITE_BYTE(conn, MQTT_FHDR_MSG_TYPE_PINGREQ); PT_MQTT_WRITE_BYTE(conn, 0); send_out_buffer(conn); /* Start timeout for reply. */ conn->waiting_for_pingresp = 1; /* Wait for PINGRESP or timeout */ reset_packet(&conn->in_packet); timer_set(&conn->t, RESPONSE_WAIT_TIMEOUT); PT_WAIT_UNTIL(pt, conn->in_packet.packet_received || timer_expired(&conn->t)); reset_packet(&conn->in_packet); conn->waiting_for_pingresp = 0; PT_END(pt); }
/*---------------------------------------------------------------------------*/ static PT_THREAD(subscribe_pt(struct pt* pt, struct mqtt_connection* conn)) { PT_BEGIN(pt); DBG("MQTT - Sending subscribe message! topic %s topic_length %i\r\n", conn->out_packet.topic, conn->out_packet.topic_length); DBG("MQTT - Buffer space is %i \r\n", &conn->out_buffer[MQTT_TCP_OUTPUT_BUFF_SIZE] - conn->out_buffer_ptr); /* Set up FHDR */ conn->out_packet.fhdr = MQTT_FHDR_MSG_TYPE_SUBSCRIBE | MQTT_FHDR_QOS_LEVEL_1; conn->out_packet.remaining_length = MQTT_MID_SIZE + MQTT_STRING_LEN_SIZE + conn->out_packet.topic_length + MQTT_QOS_SIZE; encode_remaining_length(conn->out_packet.remaining_length_enc, &conn->out_packet.remaining_length_enc_bytes, conn->out_packet.remaining_length); if(conn->out_packet.remaining_length_enc_bytes > 4) { call_event(conn, MQTT_EVENT_PROTOCOL_ERROR, NULL); printf("MQTT - Error, remaining length > 4 bytes\r\n"); PT_EXIT(pt); } /* Write Fixed Header */ PT_MQTT_WRITE_BYTE(conn, conn->out_packet.fhdr); PT_MQTT_WRITE_BYTES(conn, conn->out_packet.remaining_length_enc, conn->out_packet.remaining_length_enc_bytes); /* Write Variable Header */ PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.mid << 8)); PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.mid & 0x00FF)); /* Write Payload */ PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.topic_length >> 8)); PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.topic_length & 0x00FF)); PT_MQTT_WRITE_BYTES(conn, conn->out_packet.topic, conn->out_packet.topic_length); PT_MQTT_WRITE_BYTE(conn, conn->out_packet.qos); /* Send out buffer */ send_out_buffer(conn); /* Wait for SUBACK. */ reset_packet(&conn->in_packet); do { PT_WAIT_UNTIL(pt, conn->out_packet.qos_state == MQTT_QOS_STATE_GOT_ACK); } while(conn->out_packet.qos_state != MQTT_QOS_STATE_GOT_ACK); reset_packet(&conn->in_packet); /* This is clear after the entire transaction is complete */ conn->out_queue_full = 0; DBG("MQTT - Done in send_subscribe!\r\n"); PT_END(pt); }
/*---------------------------------------------------------------------------*/ static PT_THREAD(disconnect_pt(struct pt* pt, struct mqtt_connection* conn)) { PT_BEGIN(pt); PT_MQTT_WRITE_BYTE(conn, MQTT_FHDR_MSG_TYPE_DISCONNECT); PT_MQTT_WRITE_BYTE(conn, 0); send_out_buffer(conn); PT_WAIT_UNTIL(pt, conn->out_buffer_sent); disconnect_tcp(conn); PT_END(pt); }
/*---------------------------------------------------------------------------*/ static PT_THREAD(disconnect_pt(struct pt *pt, struct mqtt_connection *conn)) { PT_BEGIN(pt); PT_MQTT_WRITE_BYTE(conn, MQTT_FHDR_MSG_TYPE_DISCONNECT); PT_MQTT_WRITE_BYTE(conn, 0); send_out_buffer(conn); /* * Wait a couple of seconds for a TCP ACK. We don't really need the ACK, * we do want the TCP/IP stack to actually send this disconnect before we * tear down the session. */ timer_set(&conn->t, (CLOCK_SECOND * 2)); PT_WAIT_UNTIL(pt, conn->out_buffer_sent || timer_expired(&conn->t)); PT_END(pt); }
/*---------------------------------------------------------------------------*/ static PT_THREAD(publish_pt(struct pt *pt, struct mqtt_connection *conn)) { PT_BEGIN(pt); DBG("MQTT - Sending publish message! topic %s topic_length %i\n", conn->out_packet.topic, conn->out_packet.topic_length); DBG("MQTT - Buffer space is %i \n", &conn->out_buffer[MQTT_TCP_OUTPUT_BUFF_SIZE] - conn->out_buffer_ptr); /* Set up FHDR */ conn->out_packet.fhdr = MQTT_FHDR_MSG_TYPE_PUBLISH | conn->out_packet.qos << 1; if(conn->out_packet.retain == MQTT_RETAIN_ON) { conn->out_packet.fhdr |= MQTT_FHDR_RETAIN_FLAG; } conn->out_packet.remaining_length = MQTT_STRING_LEN_SIZE + conn->out_packet.topic_length + conn->out_packet.payload_size; if(conn->out_packet.qos > MQTT_QOS_LEVEL_0) { conn->out_packet.remaining_length += MQTT_MID_SIZE; } encode_remaining_length(conn->out_packet.remaining_length_enc, &conn->out_packet.remaining_length_enc_bytes, conn->out_packet.remaining_length); if(conn->out_packet.remaining_length_enc_bytes > 4) { call_event(conn, MQTT_EVENT_PROTOCOL_ERROR, NULL); PRINTF("MQTT - Error, remaining length > 4 bytes\n"); PT_EXIT(pt); } /* Write Fixed Header */ PT_MQTT_WRITE_BYTE(conn, conn->out_packet.fhdr); PT_MQTT_WRITE_BYTES(conn, (uint8_t *)conn->out_packet.remaining_length_enc, conn->out_packet.remaining_length_enc_bytes); /* Write Variable Header */ PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.topic_length >> 8)); PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.topic_length & 0x00FF)); PT_MQTT_WRITE_BYTES(conn, (uint8_t *)conn->out_packet.topic, conn->out_packet.topic_length); if(conn->out_packet.qos > MQTT_QOS_LEVEL_0) { PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.mid << 8)); PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.mid & 0x00FF)); } /* Write Payload */ PT_MQTT_WRITE_BYTES(conn, conn->out_packet.payload, conn->out_packet.payload_size); send_out_buffer(conn); timer_set(&conn->t, RESPONSE_WAIT_TIMEOUT); /* * If QoS is zero then wait until the message has been sent, since there is * no ACK to wait for. * * Also notify the app will not be notified via PUBACK or PUBCOMP */ if(conn->out_packet.qos == 0) { process_post(conn->app_process, mqtt_update_event, NULL); } else if(conn->out_packet.qos == 1) { /* Wait for PUBACK */ reset_packet(&conn->in_packet); PT_WAIT_UNTIL(pt, conn->out_packet.qos_state == MQTT_QOS_STATE_GOT_ACK || timer_expired(&conn->t)); if(timer_expired(&conn->t)) { DBG("Timeout waiting for PUBACK\n"); } if(conn->in_packet.mid != conn->out_packet.mid) { DBG("MQTT - Warning, got PUBACK with none matching MID. Currently there " "is no support for several concurrent PUBLISH messages.\n"); } } else if(conn->out_packet.qos == 2) { DBG("MQTT - QoS not implemented yet.\n"); /* Should wait for PUBREC, send PUBREL and then wait for PUBCOMP */ } reset_packet(&conn->in_packet); /* This is clear after the entire transaction is complete */ conn->out_queue_full = 0; DBG("MQTT - Publish Enqueued\n"); PT_END(pt); }
/*---------------------------------------------------------------------------*/ static PT_THREAD(unsubscribe_pt(struct pt *pt, struct mqtt_connection *conn)) { PT_BEGIN(pt); DBG("MQTT - Sending unsubscribe message on topic %s topic_length %i\n", conn->out_packet.topic, conn->out_packet.topic_length); DBG("MQTT - Buffer space is %i \n", &conn->out_buffer[MQTT_TCP_OUTPUT_BUFF_SIZE] - conn->out_buffer_ptr); /* Set up FHDR */ conn->out_packet.fhdr = MQTT_FHDR_MSG_TYPE_UNSUBSCRIBE | MQTT_FHDR_QOS_LEVEL_1; conn->out_packet.remaining_length = MQTT_MID_SIZE + MQTT_STRING_LEN_SIZE + conn->out_packet.topic_length; encode_remaining_length(conn->out_packet.remaining_length_enc, &conn->out_packet.remaining_length_enc_bytes, conn->out_packet.remaining_length); if(conn->out_packet.remaining_length_enc_bytes > 4) { call_event(conn, MQTT_EVENT_PROTOCOL_ERROR, NULL); PRINTF("MQTT - Error, remaining length > 4 bytes\n"); PT_EXIT(pt); } /* Write Fixed Header */ PT_MQTT_WRITE_BYTE(conn, conn->out_packet.fhdr); PT_MQTT_WRITE_BYTES(conn, (uint8_t *)conn->out_packet.remaining_length_enc, conn->out_packet.remaining_length_enc_bytes); /* Write Variable Header */ PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.mid << 8)); PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.mid & 0x00FF)); /* Write Payload */ PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.topic_length >> 8)); PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.topic_length & 0x00FF)); PT_MQTT_WRITE_BYTES(conn, (uint8_t *)conn->out_packet.topic, conn->out_packet.topic_length); /* Send out buffer */ send_out_buffer(conn); timer_set(&conn->t, RESPONSE_WAIT_TIMEOUT); /* Wait for UNSUBACK */ reset_packet(&conn->in_packet); PT_WAIT_UNTIL(pt, conn->out_packet.qos_state == MQTT_QOS_STATE_GOT_ACK || timer_expired(&conn->t)); if(timer_expired(&conn->t)) { DBG("Timeout waiting for UNSUBACK\n"); } reset_packet(&conn->in_packet); /* This is clear after the entire transaction is complete */ conn->out_queue_full = 0; DBG("MQTT - Done writing subscribe message to out buffer!\n"); PT_END(pt); }
/*---------------------------------------------------------------------------*/ static PT_THREAD(connect_pt(struct pt *pt, struct mqtt_connection *conn)) { PT_BEGIN(pt); DBG("MQTT - Sending CONNECT message...\n"); /* Set up FHDR */ conn->out_packet.fhdr = MQTT_FHDR_MSG_TYPE_CONNECT; conn->out_packet.remaining_length = 0; conn->out_packet.remaining_length += MQTT_CONNECT_VHDR_FLAGS_SIZE; conn->out_packet.remaining_length += MQTT_STRING_LENGTH(&conn->client_id); conn->out_packet.remaining_length += MQTT_STRING_LENGTH(&conn->credentials.username); conn->out_packet.remaining_length += MQTT_STRING_LENGTH(&conn->credentials.password); conn->out_packet.remaining_length += MQTT_STRING_LENGTH(&conn->will.topic); conn->out_packet.remaining_length += MQTT_STRING_LENGTH(&conn->will.message); encode_remaining_length(conn->out_packet.remaining_length_enc, &conn->out_packet.remaining_length_enc_bytes, conn->out_packet.remaining_length); if(conn->out_packet.remaining_length_enc_bytes > 4) { call_event(conn, MQTT_EVENT_PROTOCOL_ERROR, NULL); PRINTF("MQTT - Error, remaining length > 4 bytes\n"); PT_EXIT(pt); } /* Write Fixed Header */ PT_MQTT_WRITE_BYTE(conn, conn->out_packet.fhdr); PT_MQTT_WRITE_BYTES(conn, conn->out_packet.remaining_length_enc, conn->out_packet.remaining_length_enc_bytes); PT_MQTT_WRITE_BYTE(conn, 0); PT_MQTT_WRITE_BYTE(conn, 6); PT_MQTT_WRITE_BYTES(conn, (uint8_t *)MQTT_PROTOCOL_NAME, 6); PT_MQTT_WRITE_BYTE(conn, MQTT_PROTOCOL_VERSION); PT_MQTT_WRITE_BYTE(conn, conn->connect_vhdr_flags); PT_MQTT_WRITE_BYTE(conn, (conn->keep_alive >> 8)); PT_MQTT_WRITE_BYTE(conn, (conn->keep_alive & 0x00FF)); PT_MQTT_WRITE_BYTE(conn, conn->client_id.length << 8); PT_MQTT_WRITE_BYTE(conn, conn->client_id.length & 0x00FF); PT_MQTT_WRITE_BYTES(conn, (uint8_t *)conn->client_id.string, conn->client_id.length); if(conn->connect_vhdr_flags & MQTT_VHDR_WILL_FLAG) { PT_MQTT_WRITE_BYTE(conn, conn->will.topic.length << 8); PT_MQTT_WRITE_BYTE(conn, conn->will.topic.length & 0x00FF); PT_MQTT_WRITE_BYTES(conn, (uint8_t *)conn->will.topic.string, conn->will.topic.length); PT_MQTT_WRITE_BYTE(conn, conn->will.message.length << 8); PT_MQTT_WRITE_BYTE(conn, conn->will.message.length & 0x00FF); PT_MQTT_WRITE_BYTES(conn, (uint8_t *)conn->will.message.string, conn->will.message.length); DBG("MQTT - Setting will topic to '%s' %u bytes and message to '%s' %u bytes\n", conn->will.topic.string, conn->will.topic.length, conn->will.message.string, conn->will.message.length); } if(conn->connect_vhdr_flags & MQTT_VHDR_USERNAME_FLAG) { PT_MQTT_WRITE_BYTE(conn, conn->credentials.username.length << 8); PT_MQTT_WRITE_BYTE(conn, conn->credentials.username.length & 0x00FF); PT_MQTT_WRITE_BYTES(conn, (uint8_t *)conn->credentials.username.string, conn->credentials.username.length); } if(conn->connect_vhdr_flags & MQTT_VHDR_PASSWORD_FLAG) { PT_MQTT_WRITE_BYTE(conn, conn->credentials.password.length << 8); PT_MQTT_WRITE_BYTE(conn, conn->credentials.password.length & 0x00FF); PT_MQTT_WRITE_BYTES(conn, (uint8_t *)conn->credentials.password.string, conn->credentials.password.length); } /* Send out buffer */ send_out_buffer(conn); conn->state = MQTT_CONN_STATE_CONNECTING_TO_BROKER; timer_set(&conn->t, RESPONSE_WAIT_TIMEOUT); /* Wait for CONNACK */ reset_packet(&conn->in_packet); PT_WAIT_UNTIL(pt, conn->out_packet.qos_state == MQTT_QOS_STATE_GOT_ACK || timer_expired(&conn->t)); if(timer_expired(&conn->t)) { DBG("Timeout waiting for CONNACK\n"); /* We stick to the letter of the spec here: Tear the connection down */ mqtt_disconnect(conn); } reset_packet(&conn->in_packet); DBG("MQTT - Done sending CONNECT\n"); #if DEBUG_MQTT == 1 DBG("MQTT - CONNECT message sent: \n"); uint16_t i; for(i = 0; i < (conn->out_buffer_ptr - conn->out_buffer); i++) { DBG("%02X ", conn->out_buffer[i]); } DBG("\n"); #endif PT_END(pt); }
/*---------------------------------------------------------------------------*/ static PT_THREAD(connect_pt(struct pt* pt, struct mqtt_connection* conn)) { PT_BEGIN(pt); DBG("MQTT - Sending CONNECT message...\r\n"); /* Set up FHDR */ conn->out_packet.fhdr = MQTT_FHDR_MSG_TYPE_CONNECT; conn->out_packet.remaining_length = 0; conn->out_packet.remaining_length += MQTT_connect_vhdr_flags_SIZE; conn->out_packet.remaining_length += MQTT_STRING_LENGTH(&conn->client_id); conn->out_packet.remaining_length += MQTT_STRING_LENGTH(&conn->credentials.username); conn->out_packet.remaining_length += MQTT_STRING_LENGTH(&conn->credentials.password); conn->out_packet.remaining_length += MQTT_STRING_LENGTH(&conn->will.topic); conn->out_packet.remaining_length += MQTT_STRING_LENGTH(&conn->will.message); encode_remaining_length(conn->out_packet.remaining_length_enc, &conn->out_packet.remaining_length_enc_bytes, conn->out_packet.remaining_length); if(conn->out_packet.remaining_length_enc_bytes > 4) { call_event(conn, MQTT_EVENT_PROTOCOL_ERROR, NULL); printf("MQTT - Error, remaining length > 4 bytes\r\n"); PT_EXIT(pt); } /* Write Fixed Header */ PT_MQTT_WRITE_BYTE(conn, conn->out_packet.fhdr); PT_MQTT_WRITE_BYTES(conn, conn->out_packet.remaining_length_enc, conn->out_packet.remaining_length_enc_bytes); PT_MQTT_WRITE_BYTE(conn, 0); PT_MQTT_WRITE_BYTE(conn, 6); PT_MQTT_WRITE_BYTES(conn, (uint8_t*)MQTT_PROTOCOL_NAME, 6); PT_MQTT_WRITE_BYTE(conn, MQTT_PROTOCOL_VERSION); PT_MQTT_WRITE_BYTE(conn, conn->connect_vhdr_flags); PT_MQTT_WRITE_BYTE(conn, (conn->keep_alive >> 8)); PT_MQTT_WRITE_BYTE(conn, (conn->keep_alive & 0x00FF)); PT_MQTT_WRITE_BYTE(conn, conn->client_id.length << 8); PT_MQTT_WRITE_BYTE(conn, conn->client_id.length & 0x00FF); PT_MQTT_WRITE_BYTES(conn, conn->client_id.string, conn->client_id.length); if(conn->connect_vhdr_flags & MQTT_VHDR_WILL_FLAG) { PT_MQTT_WRITE_BYTE(conn, conn->will.topic.length << 8); PT_MQTT_WRITE_BYTE(conn, conn->will.topic.length & 0x00FF); PT_MQTT_WRITE_BYTES(conn, conn->will.topic.string, conn->will.topic.length); PT_MQTT_WRITE_BYTE(conn, conn->will.message.length << 8); PT_MQTT_WRITE_BYTE(conn, conn->will.message.length & 0x00FF); PT_MQTT_WRITE_BYTES(conn, conn->will.message.string, conn->will.message.length); DBG("MQTT - Setting will topic to '%s' %i bytes and message to '%s' %i bytes\r\n", conn->will.topic.string, conn->will.topic.length, conn->will.message.string, conn->will.message.length); } if(conn->connect_vhdr_flags & MQTT_VHDR_USERNAME_FLAG) { DBG("MQTT - Setting username\r\n"); PT_MQTT_WRITE_BYTE(conn, conn->credentials.username.length << 8); PT_MQTT_WRITE_BYTE(conn, conn->credentials.username.length & 0x00FF); PT_MQTT_WRITE_BYTES(conn, conn->credentials.username.string, conn->credentials.username.length); } if(conn->connect_vhdr_flags & MQTT_VHDR_PASSWORD_FLAG) { DBG("MQTT - Setting password\r\n"); PT_MQTT_WRITE_BYTE(conn, conn->credentials.password.length << 8); PT_MQTT_WRITE_BYTE(conn, conn->credentials.password.length & 0x00FF); PT_MQTT_WRITE_BYTES(conn, conn->credentials.password.string, conn->credentials.password.length); } /* Send out buffer */ send_out_buffer(conn); conn->state = MQTT_CONN_STATE_CONNECTING_TO_BROKER; /* Wait for CONNACK */ reset_packet(&conn->in_packet); do { PT_WAIT_UNTIL(pt, conn->out_packet.qos_state == MQTT_QOS_STATE_GOT_ACK); } while(conn->out_packet.qos_state != MQTT_QOS_STATE_GOT_ACK); reset_packet(&conn->in_packet); DBG("MQTT - Done sending CONNECT since we got CONNACK!\r\n"); #if DEBUG_MQTT == 1 DBG("MQTT - Sending CONNECT message: \r\n"); uint16_t i; for( i = 0; i < (conn->out_buffer_ptr - conn->out_buffer); i++ ) { DBG( "%02X ", conn->out_buffer[i] ); } DBG("\r\n"); #endif PT_END(pt); }