Commit 0d676dc9b9030a7d06a57ec953c8b56ad1bd8978
1 parent
243c873f
Connect handling, mostly
Showing
4 changed files
with
80 additions
and
9 deletions
client.cpp
| @@ -74,7 +74,10 @@ bool Client::bufferToMqttPackets(std::vector<MqttPacket> &packetQueueIn) | @@ -74,7 +74,10 @@ bool Client::bufferToMqttPackets(std::vector<MqttPacket> &packetQueueIn) | ||
| 74 | while ((encodedByte & 128) != 0); | 74 | while ((encodedByte & 128) != 0); |
| 75 | packet_length += remaining_length_i; | 75 | packet_length += remaining_length_i; |
| 76 | 76 | ||
| 77 | - // TODO: unauth client can't send many bytes | 77 | + if (!authenticated && packet_length >= 1024*1024) |
| 78 | + { | ||
| 79 | + throw ProtocolError("An unauthenticated client sends a packet of 1 MB or bigger? Probably it's just random bytes."); | ||
| 80 | + } | ||
| 78 | 81 | ||
| 79 | if (packet_length <= getBufBytesUsed()) | 82 | if (packet_length <= getBufBytesUsed()) |
| 80 | { | 83 | { |
| @@ -99,6 +102,13 @@ bool Client::bufferToMqttPackets(std::vector<MqttPacket> &packetQueueIn) | @@ -99,6 +102,13 @@ bool Client::bufferToMqttPackets(std::vector<MqttPacket> &packetQueueIn) | ||
| 99 | // TODO: reset buffer to normal size after a while of not needing it, or not needing the extra space. | 102 | // TODO: reset buffer to normal size after a while of not needing it, or not needing the extra space. |
| 100 | } | 103 | } |
| 101 | 104 | ||
| 105 | +void Client::setClientProperties(const std::string &clientId, const std::string username, bool connectPacketSeen) | ||
| 106 | +{ | ||
| 107 | + this->clientid = clientId; | ||
| 108 | + this->username = username; | ||
| 109 | + this->connectPacketSeen = connectPacketSeen; | ||
| 110 | +} | ||
| 111 | + | ||
| 102 | 112 | ||
| 103 | 113 | ||
| 104 | 114 |
client.h
| @@ -7,6 +7,7 @@ | @@ -7,6 +7,7 @@ | ||
| 7 | 7 | ||
| 8 | #include "threaddata.h" | 8 | #include "threaddata.h" |
| 9 | #include "mqttpacket.h" | 9 | #include "mqttpacket.h" |
| 10 | +#include "exceptions.h" | ||
| 10 | 11 | ||
| 11 | #define CLIENT_BUFFER_SIZE 1024 | 12 | #define CLIENT_BUFFER_SIZE 1024 |
| 12 | #define MQTT_HEADER_LENGH 2 | 13 | #define MQTT_HEADER_LENGH 2 |
| @@ -26,7 +27,9 @@ class Client | @@ -26,7 +27,9 @@ class Client | ||
| 26 | int ri = 0; | 27 | int ri = 0; |
| 27 | 28 | ||
| 28 | bool authenticated = false; | 29 | bool authenticated = false; |
| 30 | + bool connectPacketSeen = false; | ||
| 29 | std::string clientid; | 31 | std::string clientid; |
| 32 | + std::string username; | ||
| 30 | 33 | ||
| 31 | ThreadData_p threadData; | 34 | ThreadData_p threadData; |
| 32 | 35 | ||
| @@ -55,6 +58,11 @@ public: | @@ -55,6 +58,11 @@ public: | ||
| 55 | int getFd() { return fd;} | 58 | int getFd() { return fd;} |
| 56 | bool readFdIntoBuffer(); | 59 | bool readFdIntoBuffer(); |
| 57 | bool bufferToMqttPackets(std::vector<MqttPacket> &packetQueueIn); | 60 | bool bufferToMqttPackets(std::vector<MqttPacket> &packetQueueIn); |
| 61 | + void setClientProperties(const std::string &clientId, const std::string username, bool connectPacketSeen); | ||
| 62 | + void setAuthenticated(bool value) { authenticated = value;} | ||
| 63 | + bool getAuthenticated() { return authenticated; } | ||
| 64 | + bool hasConnectPacketSeen() { return connectPacketSeen; } | ||
| 65 | + | ||
| 58 | 66 | ||
| 59 | }; | 67 | }; |
| 60 | 68 |
mqttpacket.cpp
| @@ -7,24 +7,25 @@ MqttPacket::MqttPacket(char *buf, size_t len, size_t fixed_header_length, Client | @@ -7,24 +7,25 @@ MqttPacket::MqttPacket(char *buf, size_t len, size_t fixed_header_length, Client | ||
| 7 | sender(sender) | 7 | sender(sender) |
| 8 | { | 8 | { |
| 9 | unsigned char _packetType = buf[0] >> 4; | 9 | unsigned char _packetType = buf[0] >> 4; |
| 10 | - packetType = (PacketType)_packetType; // TODO: veryify some other things and set to invalid if doesn't match | 10 | + packetType = (PacketType)_packetType; |
| 11 | + pos += fixed_header_length; | ||
| 11 | 12 | ||
| 12 | std::memcpy(&bites[0], buf, len); | 13 | std::memcpy(&bites[0], buf, len); |
| 13 | } | 14 | } |
| 14 | 15 | ||
| 15 | void MqttPacket::handle() | 16 | void MqttPacket::handle() |
| 16 | { | 17 | { |
| 17 | - pos += fixed_header_length; | ||
| 18 | - | ||
| 19 | if (packetType == PacketType::CONNECT) | 18 | if (packetType == PacketType::CONNECT) |
| 20 | handleConnect(); | 19 | handleConnect(); |
| 21 | } | 20 | } |
| 22 | 21 | ||
| 23 | void MqttPacket::handleConnect() | 22 | void MqttPacket::handleConnect() |
| 24 | { | 23 | { |
| 24 | + if (sender->hasConnectPacketSeen()) | ||
| 25 | + throw ProtocolError("Client already sent a CONNECT."); | ||
| 26 | + | ||
| 25 | // TODO: Do all packets have a variable header? | 27 | // TODO: Do all packets have a variable header? |
| 26 | - variable_header_length = (bites[fixed_header_length] << 8) | (bites[fixed_header_length+1]); | ||
| 27 | - pos += 2; | 28 | + variable_header_length = readTwoBytesToUInt16(); |
| 28 | 29 | ||
| 29 | if (variable_header_length == 4) | 30 | if (variable_header_length == 4) |
| 30 | { | 31 | { |
| @@ -36,12 +37,54 @@ void MqttPacket::handleConnect() | @@ -36,12 +37,54 @@ void MqttPacket::handleConnect() | ||
| 36 | if (magic_marker == "MQTT" && protocol_level == 0x04) | 37 | if (magic_marker == "MQTT" && protocol_level == 0x04) |
| 37 | { | 38 | { |
| 38 | protocolVersion = ProtocolVersion::Mqtt311; | 39 | protocolVersion = ProtocolVersion::Mqtt311; |
| 40 | + | ||
| 41 | + char flagByte = readByte(); | ||
| 42 | + bool reserved = !!(flagByte & 0b00000001); | ||
| 43 | + | ||
| 44 | + if (reserved) | ||
| 45 | + throw ProtocolError("Protocol demands reserved flag in CONNECT is 0"); | ||
| 46 | + | ||
| 47 | + | ||
| 48 | + bool user_name_flag = !!(flagByte & 0b10000000); | ||
| 49 | + bool password_flag = !!(flagByte & 0b01000000); | ||
| 50 | + bool will_retain = !!(flagByte & 0b00100000); | ||
| 51 | + char will_qos = (flagByte & 0b00011000) >> 3; | ||
| 52 | + bool will_flag = !!(flagByte & 0b00000100); | ||
| 53 | + bool clean_session = !!(flagByte & 0b00000010); | ||
| 54 | + | ||
| 55 | + uint16_t keep_alive = readTwoBytesToUInt16(); | ||
| 56 | + | ||
| 57 | + uint16_t client_id_length = readTwoBytesToUInt16(); | ||
| 58 | + std::string client_id(readBytes(client_id_length), client_id_length); | ||
| 59 | + | ||
| 60 | + std::string username; | ||
| 61 | + std::string password; | ||
| 62 | + | ||
| 63 | + if (will_flag) | ||
| 64 | + { | ||
| 65 | + | ||
| 66 | + } | ||
| 67 | + if (user_name_flag) | ||
| 68 | + { | ||
| 69 | + uint16_t user_name_length = readTwoBytesToUInt16(); | ||
| 70 | + username = std::string(readBytes(user_name_length), user_name_length); | ||
| 71 | + } | ||
| 72 | + if (password_flag) | ||
| 73 | + { | ||
| 74 | + uint16_t password_length = readTwoBytesToUInt16(); | ||
| 75 | + password = std::string(readBytes(password_length), password_length); | ||
| 76 | + } | ||
| 77 | + | ||
| 78 | + sender->setClientProperties(clientid, username, true); | ||
| 79 | + | ||
| 39 | } | 80 | } |
| 40 | } | 81 | } |
| 41 | else if (variable_header_length == 6) | 82 | else if (variable_header_length == 6) |
| 42 | { | 83 | { |
| 43 | - throw new ProtocolError("Only MQTT 3.1.1 implemented."); | 84 | + throw ProtocolError("Only MQTT 3.1.1 implemented."); |
| 44 | } | 85 | } |
| 86 | + | ||
| 87 | + throw ProtocolError("Unprogrammed sequence in CONNECT."); | ||
| 45 | } | 88 | } |
| 46 | 89 | ||
| 47 | char *MqttPacket::readBytes(size_t length) | 90 | char *MqttPacket::readBytes(size_t length) |
| @@ -59,11 +102,20 @@ char MqttPacket::readByte() | @@ -59,11 +102,20 @@ char MqttPacket::readByte() | ||
| 59 | if (pos + 1 > bites.size()) | 102 | if (pos + 1 > bites.size()) |
| 60 | throw ProtocolError("Invalid packet: header specifies invalid length."); | 103 | throw ProtocolError("Invalid packet: header specifies invalid length."); |
| 61 | 104 | ||
| 62 | - char b = bites[pos]; | ||
| 63 | - pos++; | 105 | + char b = bites[pos++]; |
| 64 | return b; | 106 | return b; |
| 65 | } | 107 | } |
| 66 | 108 | ||
| 109 | +uint16_t MqttPacket::readTwoBytesToUInt16() | ||
| 110 | +{ | ||
| 111 | + if (pos + 2 > bites.size()) | ||
| 112 | + throw ProtocolError("Invalid packet: header specifies invalid length."); | ||
| 113 | + | ||
| 114 | + uint16_t i = bites[pos] << 8 | bites[pos+1]; | ||
| 115 | + pos += 2; | ||
| 116 | + return i; | ||
| 117 | +} | ||
| 118 | + | ||
| 67 | 119 | ||
| 68 | 120 | ||
| 69 | std::string MqttPacket::getClientId() | 121 | std::string MqttPacket::getClientId() |
mqttpacket.h
| @@ -34,6 +34,7 @@ public: | @@ -34,6 +34,7 @@ public: | ||
| 34 | void handleConnect(); | 34 | void handleConnect(); |
| 35 | char *readBytes(size_t length); | 35 | char *readBytes(size_t length); |
| 36 | char readByte(); | 36 | char readByte(); |
| 37 | + uint16_t readTwoBytesToUInt16(); | ||
| 37 | }; | 38 | }; |
| 38 | 39 | ||
| 39 | #endif // MQTTPACKET_H | 40 | #endif // MQTTPACKET_H |