uint32_t mqtt_encode_fixed_header(uint8_t message_type, uint32_t length, uint8_t ** pp_packet) { uint32_t packet_length = 0xFFFFFFFF; if (MQTT_MAX_PAYLOAD_SIZE >= length) { uint32_t offset = 1; MQTT_TRC("[MQTT]: >> mqtt_encode_fixed_header MT:0x%02x L:0x%08x\r\n", message_type, length); packet_length_encode(length, NULL, &offset); MQTT_TRC("[MQTT]: Remaining length size = %02x\r\n", offset); uint8_t * p_mqtt_header = ((*pp_packet) - offset); // Reset offset. offset = 0; UNUSED_VARIABLE(pack_uint8(message_type, MQTT_MAX_PACKET_LENGTH, p_mqtt_header, &offset)); packet_length_encode(length, p_mqtt_header, &offset); (* pp_packet) = p_mqtt_header; packet_length = (length + offset); } return packet_length; }
int message_serialize_response(struct message_response *res, msgpack_packer *pk) { if (!pk || !res) return (-1); msgpack_pack_array(pk, 4); pack_uint8(pk, MESSAGE_TYPE_RESPONSE); pack_uint32(pk, res->msgid); pack_nil(pk); if (pack_params(pk, res->params) == -1) return (-1); return (0); }
int message_serialize_request(struct message_request *req, msgpack_packer *pk) { if (!pk || !req) return (-1); msgpack_pack_array(pk, 4); pack_uint8(pk, MESSAGE_TYPE_REQUEST); pack_uint32(pk, req->msgid); if (req->method.str == NULL || (pack_string(pk, req->method) == -1)) return (-1); if (pack_params(pk, req->params) == -1) return (-1); return (0); }
int message_serialize_error_response(msgpack_packer *pk, struct api_error *api_error, uint32_t msgid) { struct message_object *err_data; array err_array; if (!pk || !api_error || !api_error->isset) return (-1); msgpack_pack_array(pk, 4); pack_uint8(pk, MESSAGE_TYPE_RESPONSE); pack_uint32(pk, msgid); err_array.size = 2; err_array.obj = CALLOC(2, struct message_object); if (!err_array.obj) { LOG_WARNING("Couldn't allocate memory for err_array object"); return (-1); } err_data = &err_array.obj[0]; err_data->type = OBJECT_TYPE_INT; err_data->data.integer = api_error->type; err_data = &err_array.obj[1]; err_data->type = OBJECT_TYPE_STR; err_data->data.string = cstring_to_string(api_error->msg); if (!err_data->data.string.str) { LOG_WARNING("Couldn't allocate memory for string in err_array object"); return (-1); } if (pack_params(pk, err_array) == -1) return (-1); pack_nil(pk); FREE(err_array.obj); return (0); }
serial pack_int8(int8 num, serial input) { return (pack_uint8((uint8)num, input)); }
void connect_request_encode(const mqtt_client_t * p_client, uint8_t ** pp_packet, uint32_t * p_packet_length) { uint32_t err_code; uint32_t offset = 0; uint8_t * p_payload = &p_client->p_packet[MQTT_FIXED_HEADER_EXTENDED_SIZE]; uint8_t connect_flags = p_client->clean_session << 1; // Clean session always. memset(p_payload, 0, MQTT_MAX_PACKET_LENGTH); // Pack protocol description. MQTT_TRC("[MQTT]: Encoding Protocol Description. Str:%s Size:%08x.\r\n", p_mqtt_proto_desc->p_utf_str, p_mqtt_proto_desc->utf_strlen); err_code = pack_utf8_str(p_mqtt_proto_desc, MQTT_MAX_VARIABLE_HEADER_N_PAYLOAD, p_payload, &offset); if(err_code == NRF_SUCCESS) { MQTT_TRC("[MQTT]: Encoding Protocol Version %02x.\r\n", MQTT_PROTOCOL_VERSION); // Pack protocol version. err_code = pack_uint8(MQTT_PROTOCOL_VERSION, MQTT_MAX_VARIABLE_HEADER_N_PAYLOAD, p_payload, &offset); } // Remember position of connect flag and // leave one byte for it to be packed once we determine its value. const uint32_t connect_flag_offset = MQTT_FIXED_HEADER_EXTENDED_SIZE + offset; offset++; if(err_code == NRF_SUCCESS) { MQTT_TRC("[MQTT]: Encoding Keep Alive Time %04x.\r\n", MQTT_KEEPALIVE); // Pack keep alive time. err_code = pack_uint16(MQTT_KEEPALIVE, MQTT_MAX_VARIABLE_HEADER_N_PAYLOAD, p_payload, &offset); } if(err_code == NRF_SUCCESS) { MQTT_TRC("[MQTT]: Encoding Client Id. Str:%s Size:%08x.\r\n", p_client->client_id.p_utf_str, p_client->client_id.utf_strlen); // Pack client id err_code = pack_utf8_str(&p_client->client_id, MQTT_MAX_VARIABLE_HEADER_N_PAYLOAD, p_payload, &offset); } if(err_code == NRF_SUCCESS) { // Pack will topic and QoS if (p_client->p_will_topic != NULL) { MQTT_TRC("[MQTT]: Encoding Will Topic. Str:%s Size:%08x.\r\n", p_client->p_will_topic->topic.p_utf_str, p_client->p_will_topic->topic.utf_strlen); // Set Will topic in connect flags. connect_flags |= MQTT_CONNECT_FLAG_WILL_TOPIC; err_code = pack_utf8_str(&p_client->p_will_topic->topic, MQTT_MAX_VARIABLE_HEADER_N_PAYLOAD, p_payload, &offset); if (err_code == NRF_SUCCESS) { // QoS is always 1 as of now. connect_flags |= ((p_client->p_will_topic->qos & 0x03) << 3); connect_flags |= p_client->will_retain << 5; if (p_client->p_will_message != NULL) { MQTT_TRC("[MQTT]: Encoding Will Message. Str:%s Size:%08x.\r\n", p_client->p_will_message->p_utf_str, p_client->p_will_message->utf_strlen); err_code = pack_utf8_str(p_client->p_will_message, MQTT_MAX_VARIABLE_HEADER_N_PAYLOAD, p_payload, &offset); } else { MQTT_TRC("[MQTT]: Encoding Zero Length Will Message.\r\n"); err_code = zero_len_str_encode(MQTT_MAX_VARIABLE_HEADER_N_PAYLOAD, p_payload, &offset); } } } } if (err_code == NRF_SUCCESS) { // Pack Username if any. if (p_client->p_user_name != NULL) { connect_flags |= MQTT_CONNECT_FLAG_USERNAME; MQTT_TRC("[MQTT]: Encoding Username. Str:%s, Size:%08x.\r\n", p_client->p_user_name->p_utf_str, p_client->p_user_name->utf_strlen); err_code = pack_utf8_str(p_client->p_user_name, MQTT_MAX_VARIABLE_HEADER_N_PAYLOAD, p_payload, &offset); if (err_code == NRF_SUCCESS) { // Pack Password if any. if(p_client->p_password != NULL) { MQTT_TRC("[MQTT]: Encoding Password. Str:%s Size:%08x.\r\n", p_client->p_password->p_utf_str, p_client->p_password->utf_strlen); connect_flags |= MQTT_CONNECT_FLAG_PASSWORD; err_code = pack_utf8_str(p_client->p_password, MQTT_MAX_VARIABLE_HEADER_N_PAYLOAD, p_payload, &offset); } } } } if (err_code == NRF_SUCCESS) { // Pack the connect flags. p_client->p_packet[connect_flag_offset] = connect_flags; const uint8_t message_type = MQTT_MESSAGES_OPTIONS(MQTT_PKT_TYPE_CONNECT, 0, // Duplicate flag not set. MQTT_CONNECT_PKT_QOS, 0); // Retain flag not set. offset = mqtt_encode_fixed_header(message_type, offset, &p_payload); (*p_packet_length) = offset; (*pp_packet) = p_payload; } else { (*p_packet_length) = 0; (*pp_packet) = NULL; } }