void response_base< Timer >::handle_request( const json::object& request, const boost::shared_ptr< response_interface >& self, const std::string& connection_name, bool last_message ) { const json::string channel = extract_channel( request ); if ( channel == meta_handshake_channel ) { handle_handshake( request, connection_name ); return; } const json::string client_id = check_client_id( request, channel ); if ( client_id.empty() ) return; if ( !check_session( request, client_id, channel ) ) return; if ( channel == meta_connect_channel ) { handle_connect( request, self, last_message ); } else if ( channel == meta_disconnect_channel ) { handle_disconnect( request ); } else if ( channel == meta_subscribe_channel ) { handle_subscribe( request ); } else if ( channel == meta_unsubscribe_channel ) { handle_unsubscribe( request ); } else { handle_publish( channel, request ); } }
/*---------------------------------------------------------------------------*/ static int tcp_input(struct tcp_socket *s, void *ptr, const uint8_t *input_data_ptr, int input_data_len) { struct mqtt_connection *conn = ptr; uint32_t pos = 0; uint32_t copy_bytes = 0; uint8_t byte; if(input_data_len == 0) { return 0; } if(conn->in_packet.packet_received) { reset_packet(&conn->in_packet); } DBG("tcp_input with %i bytes of data:\n", input_data_len); /* Read the fixed header field, if we do not have it */ if(!conn->in_packet.fhdr) { conn->in_packet.fhdr = input_data_ptr[pos++]; conn->in_packet.byte_counter++; DBG("MQTT - Read VHDR '%02X'\n", conn->in_packet.fhdr); if(pos >= input_data_len) { return 0; } } /* Read the Remaining Length field, if we do not have it */ if(!conn->in_packet.has_remaining_length) { do { if(pos >= input_data_len) { return 0; } byte = input_data_ptr[pos++]; conn->in_packet.byte_counter++; conn->in_packet.remaining_length_bytes++; DBG("MQTT - Read Remaining Length byte\n"); if(conn->in_packet.byte_counter > 5) { call_event(conn, MQTT_EVENT_ERROR, NULL); DBG("Received more then 4 byte 'remaining lenght'."); return 0; } conn->in_packet.remaining_length += (byte & 127) * conn->in_packet.remaining_multiplier; conn->in_packet.remaining_multiplier *= 128; } while((byte & 128) != 0); DBG("MQTT - Finished reading remaining length byte\n"); conn->in_packet.has_remaining_length = 1; } /* * Check for unsupported payload length. Will read all incoming data from the * server in any case and then reset the packet. * * TODO: Decide if we, for example, want to disconnect instead. */ if((conn->in_packet.remaining_length > MQTT_INPUT_BUFF_SIZE) && (conn->in_packet.fhdr & 0xF0) != MQTT_FHDR_MSG_TYPE_PUBLISH) { PRINTF("MQTT - Error, unsupported payload size for non-PUBLISH message\n"); conn->in_packet.byte_counter += input_data_len; if(conn->in_packet.byte_counter >= (MQTT_FHDR_SIZE + conn->in_packet.remaining_length)) { conn->in_packet.packet_received = 1; } return 0; } /* * Supported payload, reads out both VHDR and Payload of all packets. * * Note: There will always be at least one byte left to read when we enter * this loop. */ while(conn->in_packet.byte_counter < (MQTT_FHDR_SIZE + conn->in_packet.remaining_length)) { if((conn->in_packet.fhdr & 0xF0) == MQTT_FHDR_MSG_TYPE_PUBLISH && conn->in_packet.topic_received == 0) { parse_publish_vhdr(conn, &pos, input_data_ptr, input_data_len); } /* Read in as much as we can into the packet payload */ copy_bytes = MIN(input_data_len - pos, MQTT_INPUT_BUFF_SIZE - conn->in_packet.payload_pos); DBG("- Copied %lu payload bytes\n", copy_bytes); memcpy(&conn->in_packet.payload[conn->in_packet.payload_pos], &input_data_ptr[pos], copy_bytes); conn->in_packet.byte_counter += copy_bytes; conn->in_packet.payload_pos += copy_bytes; pos += copy_bytes; uint8_t i; DBG("MQTT - Copied bytes: \n"); for(i = 0; i < copy_bytes; i++) { DBG("%02X ", conn->in_packet.payload[i]); } DBG("\n"); /* Full buffer, shall only happen to PUBLISH messages. */ if(MQTT_INPUT_BUFF_SIZE - conn->in_packet.payload_pos == 0) { conn->in_publish_msg.payload_chunk = conn->in_packet.payload; conn->in_publish_msg.payload_chunk_length = MQTT_INPUT_BUFF_SIZE; conn->in_publish_msg.payload_left -= MQTT_INPUT_BUFF_SIZE; handle_publish(conn); conn->in_publish_msg.payload_chunk = conn->in_packet.payload; conn->in_packet.payload_pos = 0; } if(pos >= input_data_len && (conn->in_packet.byte_counter < (MQTT_FHDR_SIZE + conn->in_packet.remaining_length))) { return 0; } } /* Debug information */ DBG("\n"); /* Take care of input */ DBG("MQTT - Finished reading packet!\n"); /* What to return? */ DBG("MQTT - total data was %i bytes of data. \n", (MQTT_FHDR_SIZE + conn->in_packet.remaining_length)); /* Handle packet here. */ switch(conn->in_packet.fhdr & 0xF0) { case MQTT_FHDR_MSG_TYPE_CONNACK: handle_connack(conn); break; case MQTT_FHDR_MSG_TYPE_PUBLISH: /* This is the only or the last chunk of publish payload */ conn->in_publish_msg.payload_chunk = conn->in_packet.payload; conn->in_publish_msg.payload_chunk_length = conn->in_packet.payload_pos; conn->in_publish_msg.payload_left = 0; handle_publish(conn); break; case MQTT_FHDR_MSG_TYPE_PUBACK: handle_puback(conn); break; case MQTT_FHDR_MSG_TYPE_SUBACK: handle_suback(conn); break; case MQTT_FHDR_MSG_TYPE_UNSUBACK: handle_unsuback(conn); break; case MQTT_FHDR_MSG_TYPE_PINGRESP: handle_pingresp(conn); break; /* QoS 2 not implemented yet */ case MQTT_FHDR_MSG_TYPE_PUBREC: case MQTT_FHDR_MSG_TYPE_PUBREL: case MQTT_FHDR_MSG_TYPE_PUBCOMP: call_event(conn, MQTT_EVENT_NOT_IMPLEMENTED_ERROR, NULL); PRINTF("MQTT - Got unhandled MQTT Message Type '%i'", (conn->in_packet.fhdr & 0xF0)); break; default: /* All server-only message */ PRINTF("MQTT - Got MQTT Message Type '%i'", (conn->in_packet.fhdr & 0xF0)); break; } conn->in_packet.packet_received = 1; return 0; }