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 | 74 | while ((encodedByte & 128) != 0); |
| 75 | 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 | 82 | if (packet_length <= getBufBytesUsed()) |
| 80 | 83 | { |
| ... | ... | @@ -99,6 +102,13 @@ bool Client::bufferToMqttPackets(std::vector<MqttPacket> &packetQueueIn) |
| 99 | 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 | 7 | |
| 8 | 8 | #include "threaddata.h" |
| 9 | 9 | #include "mqttpacket.h" |
| 10 | +#include "exceptions.h" | |
| 10 | 11 | |
| 11 | 12 | #define CLIENT_BUFFER_SIZE 1024 |
| 12 | 13 | #define MQTT_HEADER_LENGH 2 |
| ... | ... | @@ -26,7 +27,9 @@ class Client |
| 26 | 27 | int ri = 0; |
| 27 | 28 | |
| 28 | 29 | bool authenticated = false; |
| 30 | + bool connectPacketSeen = false; | |
| 29 | 31 | std::string clientid; |
| 32 | + std::string username; | |
| 30 | 33 | |
| 31 | 34 | ThreadData_p threadData; |
| 32 | 35 | |
| ... | ... | @@ -55,6 +58,11 @@ public: |
| 55 | 58 | int getFd() { return fd;} |
| 56 | 59 | bool readFdIntoBuffer(); |
| 57 | 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 | 7 | sender(sender) |
| 8 | 8 | { |
| 9 | 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 | 13 | std::memcpy(&bites[0], buf, len); |
| 13 | 14 | } |
| 14 | 15 | |
| 15 | 16 | void MqttPacket::handle() |
| 16 | 17 | { |
| 17 | - pos += fixed_header_length; | |
| 18 | - | |
| 19 | 18 | if (packetType == PacketType::CONNECT) |
| 20 | 19 | handleConnect(); |
| 21 | 20 | } |
| 22 | 21 | |
| 23 | 22 | void MqttPacket::handleConnect() |
| 24 | 23 | { |
| 24 | + if (sender->hasConnectPacketSeen()) | |
| 25 | + throw ProtocolError("Client already sent a CONNECT."); | |
| 26 | + | |
| 25 | 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 | 30 | if (variable_header_length == 4) |
| 30 | 31 | { |
| ... | ... | @@ -36,12 +37,54 @@ void MqttPacket::handleConnect() |
| 36 | 37 | if (magic_marker == "MQTT" && protocol_level == 0x04) |
| 37 | 38 | { |
| 38 | 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 | 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 | 90 | char *MqttPacket::readBytes(size_t length) |
| ... | ... | @@ -59,11 +102,20 @@ char MqttPacket::readByte() |
| 59 | 102 | if (pos + 1 > bites.size()) |
| 60 | 103 | throw ProtocolError("Invalid packet: header specifies invalid length."); |
| 61 | 104 | |
| 62 | - char b = bites[pos]; | |
| 63 | - pos++; | |
| 105 | + char b = bites[pos++]; | |
| 64 | 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 | 121 | std::string MqttPacket::getClientId() | ... | ... |