static void deliver_publish(lmqtt_userdata * mud, uint8_t* message, int length) { NODE_DBG("enter deliver_publish.\n"); if(mud == NULL) return; mqtt_event_data_t event_data; event_data.topic_length = length; event_data.topic = mqtt_get_publish_topic(message, &event_data.topic_length); event_data.data_length = length; event_data.data = mqtt_get_publish_data(message, &event_data.data_length); if(mud->cb_message_ref == LUA_NOREF) return; if(mud->self_ref == LUA_NOREF) return; if(mud->L == NULL) return; if(event_data.topic && (event_data.topic_length > 0)){ lua_rawgeti(mud->L, LUA_REGISTRYINDEX, mud->cb_message_ref); lua_rawgeti(mud->L, LUA_REGISTRYINDEX, mud->self_ref); // pass the userdata to callback func in lua lua_pushlstring(mud->L, event_data.topic, event_data.topic_length); } else { NODE_DBG("get wrong packet.\n"); return; } if(event_data.data && (event_data.data_length > 0)){ lua_pushlstring(mud->L, event_data.data, event_data.data_length); lua_call(mud->L, 3, 0); } else { lua_call(mud->L, 2, 0); } NODE_DBG("leave deliver_publish.\n"); }
LOCAL void ICACHE_FLASH_ATTR deliver_publish(MQTT_Client * client, uint8_t * message, int length) { mqtt_event_data_t event_data; event_data.topic_length = length; event_data.topic = mqtt_get_publish_topic(message, &event_data.topic_length); event_data.data_length = length; event_data.data = mqtt_get_publish_data(message, &event_data.data_length); if (client->dataCb) client->dataCb((uint32_t *) client, event_data.topic, event_data.topic_length, event_data.data, event_data.data_length); }
static void FUNCTION_ATTRIBUTE deliver_publish(MQTT_Client* client, uint8_t* message, int length) { mqtt_event_data_t event_data; event_data.topic_length = length; event_data.topic = mqtt_get_publish_topic(message, &event_data.topic_length); event_data.data_length = length; event_data.data = mqtt_get_publish_data(message, &event_data.data_length); if(client->dataCb) client->dataCb((uint32_t*)client, event_data.topic, event_data.topic_length, event_data.data, event_data.data_length); }
// Deliver a publish message to the client static void ICACHE_FLASH_ATTR deliver_publish(MQTT_Client* client, uint8_t* message, uint16_t length) { // parse the message into topic and data uint16_t topic_length = length; const char *topic = mqtt_get_publish_topic(message, &topic_length); uint16_t data_length = length; const char *data = mqtt_get_publish_data(message, &data_length); // callback to client if (client->dataCb) client->dataCb((uint32_t*)client, topic, topic_length, data, data_length); if (client->cmdDataCb) client->cmdDataCb((uint32_t*)client, topic, topic_length, data, data_length); }
static void deliver_publish(mqtt_state_t* state, uint8_t* message, int length) { mqtt_event_data_t event_data; event_data.type = MQTT_EVENT_TYPE_PUBLISH; event_data.topic_length = length; event_data.topic = mqtt_get_publish_topic(message, &event_data.topic_length); event_data.data_length = length; event_data.data = mqtt_get_publish_data(message, &event_data.data_length); memmove((char*)event_data.data + 1, (char*)event_data.data, event_data.data_length); event_data.data += 1; ((char*)event_data.topic)[event_data.topic_length] = '\0'; ((char*)event_data.data)[event_data.data_length] = '\0'; process_post_synch(state->calling_process, mqtt_event, &event_data); }
/** * @brief Client received callback function. * @param arg: contain the ip link information * @param pdata: received data * @param len: the lenght of received data * @retval None */ void ICACHE_FLASH_ATTR mqtt_tcpclient_recv(void *arg, char *pdata, unsigned short len) { uint8_t msg_type; uint8_t msg_qos; uint16_t msg_id; struct espconn *pCon = (struct espconn*)arg; MQTT_Client *client = (MQTT_Client *)pCon->reverse; //spam INFO("TCP: data received\r\n"); if(len < MQTT_BUF_SIZE && len > 0){ memcpy(client->mqtt_state.in_buffer, pdata, len); switch(client->connState){ case MQTT_CONNECT_SENDING: if(mqtt_get_type(client->mqtt_state.in_buffer) != MQTT_MSG_TYPE_CONNACK){ //spam INFO("MQTT: Invalid packet\r\n"); if(client->security){ espconn_secure_disconnect(client->pCon); } else { espconn_disconnect(client->pCon); } } else { //spam INFO("MQTT: Connected to %s:%d\r\n", client->host, client->port); client->connState = MQTT_DATA; if(client->connectedCb) client->connectedCb((uint32_t*)client); } break; case MQTT_DATA: client->mqtt_state.message_length_read = len; client->mqtt_state.message_length = mqtt_get_total_length(client->mqtt_state.in_buffer, client->mqtt_state.message_length_read); msg_type = mqtt_get_type(client->mqtt_state.in_buffer); msg_qos = mqtt_get_qos(client->mqtt_state.in_buffer); msg_id = mqtt_get_id(client->mqtt_state.in_buffer, client->mqtt_state.in_buffer_length); switch(msg_type) { case MQTT_MSG_TYPE_SUBACK: //spam if(client->mqtt_state.pending_msg_type == MQTT_MSG_TYPE_SUBSCRIBE && client->mqtt_state.pending_msg_id == msg_id) //spam INFO("MQTT: Subscribe successful to %s:%d\r\n", client->host, client->port); break; case MQTT_MSG_TYPE_UNSUBACK: //spam if(client->mqtt_state.pending_msg_type == MQTT_MSG_TYPE_UNSUBSCRIBE && client->mqtt_state.pending_msg_id == msg_id) //spam INFO("MQTT: UnSubscribe successful\r\n"); break; case MQTT_MSG_TYPE_PUBLISH: if(msg_qos == 1) client->mqtt_state.outbound_message = mqtt_msg_puback(&client->mqtt_state.mqtt_connection, msg_id); else if(msg_qos == 2) client->mqtt_state.outbound_message = mqtt_msg_pubrec(&client->mqtt_state.mqtt_connection, msg_id); deliver_publish(client, client->mqtt_state.in_buffer, client->mqtt_state.message_length_read); break; case MQTT_MSG_TYPE_PUBACK: if(client->mqtt_state.pending_msg_type == MQTT_MSG_TYPE_PUBLISH && client->mqtt_state.pending_msg_id == msg_id){ //spam INFO("MQTT: Publish successful\r\n"); if(client->publishedCb) client->publishedCb((uint32_t*)client); } break; case MQTT_MSG_TYPE_PUBREC: client->mqtt_state.outbound_message = mqtt_msg_pubrel(&client->mqtt_state.mqtt_connection, msg_id); break; case MQTT_MSG_TYPE_PUBREL: client->mqtt_state.outbound_message = mqtt_msg_pubcomp(&client->mqtt_state.mqtt_connection, msg_id); break; case MQTT_MSG_TYPE_PUBCOMP: if(client->mqtt_state.pending_msg_type == MQTT_MSG_TYPE_PUBLISH && client->mqtt_state.pending_msg_id == msg_id){ //spam INFO("MQTT: Public successful\r\n"); if(client->publishedCb) client->publishedCb((uint32_t*)client); } break; case MQTT_MSG_TYPE_PINGREQ: client->mqtt_state.outbound_message = mqtt_msg_pingresp(&client->mqtt_state.mqtt_connection); break; case MQTT_MSG_TYPE_PINGRESP: // Ignore break; } // NOTE: this is done down here and not in the switch case above // because the PSOCK_READBUF_LEN() won't work inside a switch // statement due to the way protothreads resume. if(msg_type == MQTT_MSG_TYPE_PUBLISH) { uint16_t len; // adjust message_length and message_length_read so that // they only account for the publish data and not the rest of the // message, this is done so that the offset passed with the // continuation event is the offset within the publish data and // not the offset within the message as a whole. len = client->mqtt_state.message_length_read; mqtt_get_publish_data(client->mqtt_state.in_buffer, &len); len = client->mqtt_state.message_length_read - len; client->mqtt_state.message_length -= len; client->mqtt_state.message_length_read -= len; if(client->mqtt_state.message_length_read < client->mqtt_state.message_length) { //client->connState = MQTT_PUBLISH_RECV; } } break; case MQTT_PUBLISH_RECV: /* * Long publish message, not implement yet * TODO: Implement method used deliver_publish_continuation */ break; } } system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client); }
static PT_THREAD(handle_mqtt_connection(mqtt_state_t* state)) { static struct etimer keepalive_timer; uint8_t msg_type; uint8_t msg_qos; uint16_t msg_id; PSOCK_BEGIN(&state->ps); // Initialise and send CONNECT message mqtt_msg_init(&state->mqtt_connection, state->out_buffer, state->out_buffer_length); state->outbound_message = mqtt_msg_connect(&state->mqtt_connection, state->connect_info); PSOCK_SEND(&state->ps, state->outbound_message->data, state->outbound_message->length); state->outbound_message = NULL; // Wait for CONACK message PSOCK_READBUF_LEN(&state->ps, 2); if(mqtt_get_type(state->in_buffer) != MQTT_MSG_TYPE_CONNACK) PSOCK_CLOSE_EXIT(&state->ps); // Tell the client we're connected mqtt_flags |= MQTT_FLAG_CONNECTED; complete_pending(state, MQTT_EVENT_TYPE_CONNECTED); // Setup the keep alive timer and enter main message processing loop etimer_set(&keepalive_timer, CLOCK_SECOND * state->connect_info->keepalive); while(1) { // Wait for something to happen: // new incoming data, // new outgoing data, // keep alive timer expired PSOCK_WAIT_UNTIL(&state->ps, PSOCK_NEWDATA(&state->ps) || state->outbound_message != NULL || etimer_expired(&keepalive_timer)); // If there's a new message waiting to go out, then send it if(state->outbound_message != NULL) { PSOCK_SEND(&state->ps, state->outbound_message->data, state->outbound_message->length); state->outbound_message = NULL; // If it was a PUBLISH message with QoS-0 then tell the client it's done if(state->pending_msg_type == MQTT_MSG_TYPE_PUBLISH && state->pending_msg_id == 0) complete_pending(state, MQTT_EVENT_TYPE_PUBLISHED); // Reset the keepalive timer as we've just sent some data etimer_restart(&keepalive_timer); continue; } // If the keep-alive timer expired then prepare a ping for sending // and reset the timer if(etimer_expired(&keepalive_timer)) { state->outbound_message = mqtt_msg_pingreq(&state->mqtt_connection); etimer_reset(&keepalive_timer); continue; } // If we get here we must have woken for new incoming data, // read and process it. PSOCK_READBUF_LEN(&state->ps, 2); state->message_length_read = PSOCK_DATALEN(&state->ps); state->message_length = mqtt_get_total_length(state->in_buffer, state->message_length_read); msg_type = mqtt_get_type(state->in_buffer); msg_qos = mqtt_get_qos(state->in_buffer); msg_id = mqtt_get_id(state->in_buffer, state->in_buffer_length); switch(msg_type) { case MQTT_MSG_TYPE_SUBACK: if(state->pending_msg_type == MQTT_MSG_TYPE_SUBSCRIBE && state->pending_msg_id == msg_id) complete_pending(state, MQTT_EVENT_TYPE_SUBSCRIBED); break; case MQTT_MSG_TYPE_UNSUBACK: if(state->pending_msg_type == MQTT_MSG_TYPE_UNSUBSCRIBE && state->pending_msg_id == msg_id) complete_pending(state, MQTT_EVENT_TYPE_UNSUBSCRIBED); break; case MQTT_MSG_TYPE_PUBLISH: if(msg_qos == 1) state->outbound_message = mqtt_msg_puback(&state->mqtt_connection, msg_id); else if(msg_qos == 2) state->outbound_message = mqtt_msg_pubrec(&state->mqtt_connection, msg_id); deliver_publish(state, state->in_buffer, state->message_length_read); break; case MQTT_MSG_TYPE_PUBACK: if(state->pending_msg_type == MQTT_MSG_TYPE_PUBLISH && state->pending_msg_id == msg_id) complete_pending(state, MQTT_EVENT_TYPE_PUBLISHED); break; case MQTT_MSG_TYPE_PUBREC: state->outbound_message = mqtt_msg_pubrel(&state->mqtt_connection, msg_id); break; case MQTT_MSG_TYPE_PUBREL: state->outbound_message = mqtt_msg_pubcomp(&state->mqtt_connection, msg_id); break; case MQTT_MSG_TYPE_PUBCOMP: if(state->pending_msg_type == MQTT_MSG_TYPE_PUBLISH && state->pending_msg_id == msg_id) complete_pending(state, MQTT_EVENT_TYPE_PUBLISHED); break; case MQTT_MSG_TYPE_PINGREQ: state->outbound_message = mqtt_msg_pingresp(&state->mqtt_connection); break; case MQTT_MSG_TYPE_PINGRESP: // Ignore break; } // NOTE: this is done down here and not in the switch case above // because the PSOCK_READBUF_LEN() won't work inside a switch // statement due to the way protothreads resume. if(msg_type == MQTT_MSG_TYPE_PUBLISH) { uint16_t len; // adjust message_length and message_length_read so that // they only account for the publish data and not the rest of the // message, this is done so that the offset passed with the // continuation event is the offset within the publish data and // not the offset within the message as a whole. len = state->message_length_read; mqtt_get_publish_data(state->in_buffer, &len); len = state->message_length_read - len; state->message_length -= len; state->message_length_read -= len; while(state->message_length_read < state->message_length) { PSOCK_READBUF_LEN(&state->ps, state->message_length - state->message_length_read); deliver_publish_continuation(state, state->message_length_read, state->in_buffer, PSOCK_DATALEN(&state->ps)); state->message_length_read += PSOCK_DATALEN(&state->ps); } } } PSOCK_END(&state->ps); }