From 0d676dc9b9030a7d06a57ec953c8b56ad1bd8978 Mon Sep 17 00:00:00 2001 From: Wiebe Cazemier Date: Wed, 9 Dec 2020 11:07:29 +0100 Subject: [PATCH] Connect handling, mostly --- client.cpp | 12 +++++++++++- client.h | 8 ++++++++ mqttpacket.cpp | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------- mqttpacket.h | 1 + 4 files changed, 80 insertions(+), 9 deletions(-) diff --git a/client.cpp b/client.cpp index 3d8318f..81d9087 100644 --- a/client.cpp +++ b/client.cpp @@ -74,7 +74,10 @@ bool Client::bufferToMqttPackets(std::vector &packetQueueIn) while ((encodedByte & 128) != 0); packet_length += remaining_length_i; - // TODO: unauth client can't send many bytes + if (!authenticated && packet_length >= 1024*1024) + { + throw ProtocolError("An unauthenticated client sends a packet of 1 MB or bigger? Probably it's just random bytes."); + } if (packet_length <= getBufBytesUsed()) { @@ -99,6 +102,13 @@ bool Client::bufferToMqttPackets(std::vector &packetQueueIn) // TODO: reset buffer to normal size after a while of not needing it, or not needing the extra space. } +void Client::setClientProperties(const std::string &clientId, const std::string username, bool connectPacketSeen) +{ + this->clientid = clientId; + this->username = username; + this->connectPacketSeen = connectPacketSeen; +} + diff --git a/client.h b/client.h index dbac6da..d4a7434 100644 --- a/client.h +++ b/client.h @@ -7,6 +7,7 @@ #include "threaddata.h" #include "mqttpacket.h" +#include "exceptions.h" #define CLIENT_BUFFER_SIZE 1024 #define MQTT_HEADER_LENGH 2 @@ -26,7 +27,9 @@ class Client int ri = 0; bool authenticated = false; + bool connectPacketSeen = false; std::string clientid; + std::string username; ThreadData_p threadData; @@ -55,6 +58,11 @@ public: int getFd() { return fd;} bool readFdIntoBuffer(); bool bufferToMqttPackets(std::vector &packetQueueIn); + void setClientProperties(const std::string &clientId, const std::string username, bool connectPacketSeen); + void setAuthenticated(bool value) { authenticated = value;} + bool getAuthenticated() { return authenticated; } + bool hasConnectPacketSeen() { return connectPacketSeen; } + }; diff --git a/mqttpacket.cpp b/mqttpacket.cpp index 4872d34..2c1488f 100644 --- a/mqttpacket.cpp +++ b/mqttpacket.cpp @@ -7,24 +7,25 @@ MqttPacket::MqttPacket(char *buf, size_t len, size_t fixed_header_length, Client sender(sender) { unsigned char _packetType = buf[0] >> 4; - packetType = (PacketType)_packetType; // TODO: veryify some other things and set to invalid if doesn't match + packetType = (PacketType)_packetType; + pos += fixed_header_length; std::memcpy(&bites[0], buf, len); } void MqttPacket::handle() { - pos += fixed_header_length; - if (packetType == PacketType::CONNECT) handleConnect(); } void MqttPacket::handleConnect() { + if (sender->hasConnectPacketSeen()) + throw ProtocolError("Client already sent a CONNECT."); + // TODO: Do all packets have a variable header? - variable_header_length = (bites[fixed_header_length] << 8) | (bites[fixed_header_length+1]); - pos += 2; + variable_header_length = readTwoBytesToUInt16(); if (variable_header_length == 4) { @@ -36,12 +37,54 @@ void MqttPacket::handleConnect() if (magic_marker == "MQTT" && protocol_level == 0x04) { protocolVersion = ProtocolVersion::Mqtt311; + + char flagByte = readByte(); + bool reserved = !!(flagByte & 0b00000001); + + if (reserved) + throw ProtocolError("Protocol demands reserved flag in CONNECT is 0"); + + + bool user_name_flag = !!(flagByte & 0b10000000); + bool password_flag = !!(flagByte & 0b01000000); + bool will_retain = !!(flagByte & 0b00100000); + char will_qos = (flagByte & 0b00011000) >> 3; + bool will_flag = !!(flagByte & 0b00000100); + bool clean_session = !!(flagByte & 0b00000010); + + uint16_t keep_alive = readTwoBytesToUInt16(); + + uint16_t client_id_length = readTwoBytesToUInt16(); + std::string client_id(readBytes(client_id_length), client_id_length); + + std::string username; + std::string password; + + if (will_flag) + { + + } + if (user_name_flag) + { + uint16_t user_name_length = readTwoBytesToUInt16(); + username = std::string(readBytes(user_name_length), user_name_length); + } + if (password_flag) + { + uint16_t password_length = readTwoBytesToUInt16(); + password = std::string(readBytes(password_length), password_length); + } + + sender->setClientProperties(clientid, username, true); + } } else if (variable_header_length == 6) { - throw new ProtocolError("Only MQTT 3.1.1 implemented."); + throw ProtocolError("Only MQTT 3.1.1 implemented."); } + + throw ProtocolError("Unprogrammed sequence in CONNECT."); } char *MqttPacket::readBytes(size_t length) @@ -59,11 +102,20 @@ char MqttPacket::readByte() if (pos + 1 > bites.size()) throw ProtocolError("Invalid packet: header specifies invalid length."); - char b = bites[pos]; - pos++; + char b = bites[pos++]; return b; } +uint16_t MqttPacket::readTwoBytesToUInt16() +{ + if (pos + 2 > bites.size()) + throw ProtocolError("Invalid packet: header specifies invalid length."); + + uint16_t i = bites[pos] << 8 | bites[pos+1]; + pos += 2; + return i; +} + std::string MqttPacket::getClientId() diff --git a/mqttpacket.h b/mqttpacket.h index fbba082..c61af48 100644 --- a/mqttpacket.h +++ b/mqttpacket.h @@ -34,6 +34,7 @@ public: void handleConnect(); char *readBytes(size_t length); char readByte(); + uint16_t readTwoBytesToUInt16(); }; #endif // MQTTPACKET_H -- libgit2 0.21.4