Start implementing decoders

This commit is contained in:
Johannes Schriewer 2018-07-28 20:42:18 +02:00
parent 616a8987cb
commit 4d7690366d

View file

@ -157,111 +157,150 @@ size_t utf8_string_encode(char *string, Buffer *buffer) {
* Decoder * Decoder
*/ */
ConnectPayload *decode_connect(Buffer *buffer) { bool decode_connect(Buffer *buffer, ConnectPayload *payload) {
// Validate this is actually a connect packet
char template[] = { 0x00, 0x04, 'M', 'Q', 'T', 'T' };
if (memcmp(buffer->data + buffer->position, template, sizeof(template)) != 0) {
return false;
}
buffer->position += sizeof(template);
payload->protocol_level = buffer->data[buffer->position++];
uint8_t flags = buffer->data[buffer->position++];
payload->clean_session = ((flags & 0x02) > 0);
payload->keepalive_interval = (buffer->data[buffer->position++] << 8) + buffer->data[buffer->position++];
payload->client_id = utf8_string_decode(buffer);
// last will
if (flags & 0x04) {
payload->will_topic = utf8_string_decode(buffer);
payload->will_message = utf8_string_decode(buffer);
}
payload->will_qos = (flags & 0x18) >> 3;
payload->retain_will = (flags & 0x20) > 0;
// username
if (flags & 0x40) {
payload->username = utf8_string_decode(buffer);
} }
ConnAckPayload *decode_connack(Buffer *buffer) { // password
if (flags & 0x80) {
payload->password = utf8_string_decode(buffer);
} }
PublishPayload *decode_publish(Buffer *buffer) { return true;
} }
PubAckPayload *decode_puback(Buffer *buffer) { bool decode_connack(Buffer *buffer, ConnAckPayload *payload) {
payload->session_present = buffer->data[buffer->position++] & 0x01;
payload->status = buffer->data[buffer->position++];
return true;
} }
PubRecPayload *decode_pubrec(Buffer *buffer) { bool decode_publish(Buffer *buffer, PublishPayload *payload) {
return false;
} }
PubRelPayload *decode_pubrel(Buffer *buffer) { bool decode_puback(Buffer *buffer, PubAckPayload *payload) {
payload->packet_id = (buffer->data[buffer->position++] << 8) + buffer->data[buffer->position++];
return true;
} }
PubCompPayload *decode_pubcomp(Buffer *buffer) { bool decode_pubrec(Buffer *buffer, PubRecPayload *payload) {
payload->packet_id = (buffer->data[buffer->position++] << 8) + buffer->data[buffer->position++];
return true;
} }
SubscribePayload *decode_subscribe(Buffer *buffer) { bool decode_pubrel(Buffer *buffer, PubRelPayload *payload) {
payload->packet_id = (buffer->data[buffer->position++] << 8) + buffer->data[buffer->position++];
return true;
} }
SubAckPayload *decode_suback(Buffer *buffer) { bool decode_pubcomp(Buffer *buffer, PubCompPayload *payload) {
payload->packet_id = (buffer->data[buffer->position++] << 8) + buffer->data[buffer->position++];
return true;
} }
UnsubscribePayload *decode_unsubscribe(Buffer *buffer) { bool decode_subscribe(Buffer *buffer, SubscribePayload *payload) {
return false;
} }
UnsubAckPayload *decode_unsuback(Buffer *buffer) { bool decode_suback(Buffer *buffer, SubAckPayload *payload) {
return false;
} }
int decode_pingreq(Buffer *buffer) { bool decode_unsubscribe(Buffer *buffer, UnsubscribePayload *payload) {
return false;
} }
int decode_pingresp(Buffer *buffer) { bool decode_unsuback(Buffer *buffer, UnsubAckPayload *payload) {
return false;
} }
int decode_disconnect(Buffer *buffer) {
}
MQTTPacket *mqtt_packet_decode(Buffer *buffer) { MQTTPacket *mqtt_packet_decode(Buffer *buffer) {
MQTTControlPacketType type = (buffer->data[0] & 0xf0) >> 4; // validate that the buffer is big enough
MQTTControlPacketType type = (buffer->data[buffer->position] & 0xf0) >> 4;
buffer->position++;
size_t packet_size = variable_length_int_decode(buffer);
if (buffer_free_space(buffer) < packet_size) {
return NULL; // buffer incomplete
}
MQTTPacket *result = allocate_MQTTPacket(type); MQTTPacket *result = allocate_MQTTPacket(type);
bool valid = false;
switch (type) { switch (type) {
case PacketTypeConnect: case PacketTypeConnect:
result->payload = (void *)decode_connect(buffer); valid = decode_connect(buffer, result->payload);
break; break;
case PacketTypeConnAck: case PacketTypeConnAck:
result->payload = (void *)decode_connack(buffer); valid = decode_connack(buffer, result->payload);
break; break;
case PacketTypePublish: case PacketTypePublish:
result->payload = (void *)decode_publish(buffer); valid = decode_publish(buffer, result->payload);
break; break;
case PacketTypePubAck: case PacketTypePubAck:
result->payload = (void *)decode_puback(buffer); valid = decode_puback(buffer, result->payload);
break; break;
case PacketTypePubRec: case PacketTypePubRec:
result->payload = (void *)decode_pubrec(buffer); valid = decode_pubrec(buffer, result->payload);
break; break;
case PacketTypePubRel: case PacketTypePubRel:
result->payload = (void *)decode_pubrel(buffer); valid = decode_pubrel(buffer, result->payload);
break; break;
case PacketTypePubComp: case PacketTypePubComp:
result->payload = (void *)decode_pubcomp(buffer); valid = decode_pubcomp(buffer, result->payload);
break; break;
case PacketTypeSubscribe: case PacketTypeSubscribe:
result->payload = (void *)decode_subscribe(buffer); valid = decode_subscribe(buffer, result->payload);
break; break;
case PacketTypeSubAck: case PacketTypeSubAck:
result->payload = (void *)decode_suback(buffer); valid = decode_suback(buffer, result->payload);
break; break;
case PacketTypeUnsubscribe: case PacketTypeUnsubscribe:
result->payload = (void *)decode_unsubscribe(buffer); valid = decode_unsubscribe(buffer, result->payload);
break; break;
case PacketTypeUnsubAck: case PacketTypeUnsubAck:
result->payload = (void *)decode_unsuback(buffer); valid = decode_unsuback(buffer, result->payload);
break; break;
case PacketTypePingReq: case PacketTypePingReq:
result->payload = (void *)decode_pingreq(buffer);
break;
case PacketTypePingResp: case PacketTypePingResp:
result->payload = (void *)decode_pingresp(buffer);
break;
case PacketTypeDisconnect: case PacketTypeDisconnect:
result->payload = (void *)decode_disconnect(buffer); valid = true; // there is no payload
break; break;
} }
if (!valid) {
free_MQTTPacket(result);
return NULL;
}
return result; return result;
} }