Library for MQTT

Committer:
pavleradojkovic
Date:
Mon Jun 20 16:24:43 2022 +0000
Revision:
0:ba7e439238ab
Inital commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
pavleradojkovic 0:ba7e439238ab 1 """
pavleradojkovic 0:ba7e439238ab 2 *******************************************************************
pavleradojkovic 0:ba7e439238ab 3 Copyright (c) 2013, 2014 IBM Corp.
pavleradojkovic 0:ba7e439238ab 4
pavleradojkovic 0:ba7e439238ab 5 All rights reserved. This program and the accompanying materials
pavleradojkovic 0:ba7e439238ab 6 are made available under the terms of the Eclipse Public License v1.0
pavleradojkovic 0:ba7e439238ab 7 and Eclipse Distribution License v1.0 which accompany this distribution.
pavleradojkovic 0:ba7e439238ab 8
pavleradojkovic 0:ba7e439238ab 9 The Eclipse Public License is available at
pavleradojkovic 0:ba7e439238ab 10 http://www.eclipse.org/legal/epl-v10.html
pavleradojkovic 0:ba7e439238ab 11 and the Eclipse Distribution License is available at
pavleradojkovic 0:ba7e439238ab 12 http://www.eclipse.org/org/documents/edl-v10.php.
pavleradojkovic 0:ba7e439238ab 13
pavleradojkovic 0:ba7e439238ab 14 Contributors:
pavleradojkovic 0:ba7e439238ab 15 Ian Craggs - initial implementation and/or documentation
pavleradojkovic 0:ba7e439238ab 16 *******************************************************************
pavleradojkovic 0:ba7e439238ab 17 """
pavleradojkovic 0:ba7e439238ab 18 from __future__ import print_function
pavleradojkovic 0:ba7e439238ab 19
pavleradojkovic 0:ba7e439238ab 20 """
pavleradojkovic 0:ba7e439238ab 21
pavleradojkovic 0:ba7e439238ab 22 Assertions are used to validate incoming data, but are omitted from outgoing packets. This is
pavleradojkovic 0:ba7e439238ab 23 so that the tests that use this package can send invalid data for error testing.
pavleradojkovic 0:ba7e439238ab 24
pavleradojkovic 0:ba7e439238ab 25 """
pavleradojkovic 0:ba7e439238ab 26
pavleradojkovic 0:ba7e439238ab 27
pavleradojkovic 0:ba7e439238ab 28 import logging
pavleradojkovic 0:ba7e439238ab 29
pavleradojkovic 0:ba7e439238ab 30 logger = logging.getLogger("mqttsas")
pavleradojkovic 0:ba7e439238ab 31
pavleradojkovic 0:ba7e439238ab 32 # Low-level protocol interface
pavleradojkovic 0:ba7e439238ab 33
pavleradojkovic 0:ba7e439238ab 34 class MQTTException(Exception):
pavleradojkovic 0:ba7e439238ab 35 pass
pavleradojkovic 0:ba7e439238ab 36
pavleradojkovic 0:ba7e439238ab 37
pavleradojkovic 0:ba7e439238ab 38 # Message types
pavleradojkovic 0:ba7e439238ab 39 CONNECT, CONNACK, PUBLISH, PUBACK, PUBREC, PUBREL, \
pavleradojkovic 0:ba7e439238ab 40 PUBCOMP, SUBSCRIBE, SUBACK, UNSUBSCRIBE, UNSUBACK, \
pavleradojkovic 0:ba7e439238ab 41 PINGREQ, PINGRESP, DISCONNECT = range(1, 15)
pavleradojkovic 0:ba7e439238ab 42
pavleradojkovic 0:ba7e439238ab 43 packetNames = [ "reserved", \
pavleradojkovic 0:ba7e439238ab 44 "Connect", "Connack", "Publish", "Puback", "Pubrec", "Pubrel", \
pavleradojkovic 0:ba7e439238ab 45 "Pubcomp", "Subscribe", "Suback", "Unsubscribe", "Unsuback", \
pavleradojkovic 0:ba7e439238ab 46 "Pingreq", "Pingresp", "Disconnect"]
pavleradojkovic 0:ba7e439238ab 47
pavleradojkovic 0:ba7e439238ab 48 classNames = [ "reserved", \
pavleradojkovic 0:ba7e439238ab 49 "Connects", "Connacks", "Publishes", "Pubacks", "Pubrecs", "Pubrels", \
pavleradojkovic 0:ba7e439238ab 50 "Pubcomps", "Subscribes", "Subacks", "Unsubscribes", "Unsubacks", \
pavleradojkovic 0:ba7e439238ab 51 "Pingreqs", "Pingresps", "Disconnects"]
pavleradojkovic 0:ba7e439238ab 52
pavleradojkovic 0:ba7e439238ab 53
pavleradojkovic 0:ba7e439238ab 54 def MessageType(byte):
pavleradojkovic 0:ba7e439238ab 55 if byte != None:
pavleradojkovic 0:ba7e439238ab 56 rc = ord(byte[0]) >> 4
pavleradojkovic 0:ba7e439238ab 57 else:
pavleradojkovic 0:ba7e439238ab 58 rc = None
pavleradojkovic 0:ba7e439238ab 59 return rc
pavleradojkovic 0:ba7e439238ab 60
pavleradojkovic 0:ba7e439238ab 61
pavleradojkovic 0:ba7e439238ab 62 def getPacket(aSocket):
pavleradojkovic 0:ba7e439238ab 63 "receive the next packet"
pavleradojkovic 0:ba7e439238ab 64 buf = aSocket.recv(1) # get the first byte fixed header
pavleradojkovic 0:ba7e439238ab 65 if buf == b"":
pavleradojkovic 0:ba7e439238ab 66 return None
pavleradojkovic 0:ba7e439238ab 67 if str(aSocket).find("[closed]") != -1:
pavleradojkovic 0:ba7e439238ab 68 closed = True
pavleradojkovic 0:ba7e439238ab 69 else:
pavleradojkovic 0:ba7e439238ab 70 closed = False
pavleradojkovic 0:ba7e439238ab 71 if closed:
pavleradojkovic 0:ba7e439238ab 72 return None
pavleradojkovic 0:ba7e439238ab 73 # now get the remaining length
pavleradojkovic 0:ba7e439238ab 74 multiplier = 1
pavleradojkovic 0:ba7e439238ab 75 remlength = 0
pavleradojkovic 0:ba7e439238ab 76 while 1:
pavleradojkovic 0:ba7e439238ab 77 next = aSocket.recv(1)
pavleradojkovic 0:ba7e439238ab 78 while len(next) == 0:
pavleradojkovic 0:ba7e439238ab 79 next = aSocket.recv(1)
pavleradojkovic 0:ba7e439238ab 80 buf += next
pavleradojkovic 0:ba7e439238ab 81 digit = ord(buf[-1])
pavleradojkovic 0:ba7e439238ab 82 remlength += (digit & 127) * multiplier
pavleradojkovic 0:ba7e439238ab 83 if digit & 128 == 0:
pavleradojkovic 0:ba7e439238ab 84 break
pavleradojkovic 0:ba7e439238ab 85 multiplier *= 128
pavleradojkovic 0:ba7e439238ab 86 # receive the remaining length if there is any
pavleradojkovic 0:ba7e439238ab 87 rest = ''
pavleradojkovic 0:ba7e439238ab 88 if remlength > 0:
pavleradojkovic 0:ba7e439238ab 89 while len(rest) < remlength:
pavleradojkovic 0:ba7e439238ab 90 rest += aSocket.recv(remlength-len(rest))
pavleradojkovic 0:ba7e439238ab 91 assert len(rest) == remlength
pavleradojkovic 0:ba7e439238ab 92 return buf + rest
pavleradojkovic 0:ba7e439238ab 93
pavleradojkovic 0:ba7e439238ab 94
pavleradojkovic 0:ba7e439238ab 95 class FixedHeaders:
pavleradojkovic 0:ba7e439238ab 96
pavleradojkovic 0:ba7e439238ab 97 def __init__(self, aMessageType):
pavleradojkovic 0:ba7e439238ab 98 self.MessageType = aMessageType
pavleradojkovic 0:ba7e439238ab 99 self.DUP = False
pavleradojkovic 0:ba7e439238ab 100 self.QoS = 0
pavleradojkovic 0:ba7e439238ab 101 self.RETAIN = False
pavleradojkovic 0:ba7e439238ab 102 self.remainingLength = 0
pavleradojkovic 0:ba7e439238ab 103
pavleradojkovic 0:ba7e439238ab 104 def __eq__(self, fh):
pavleradojkovic 0:ba7e439238ab 105 return self.MessageType == fh.MessageType and \
pavleradojkovic 0:ba7e439238ab 106 self.DUP == fh.DUP and \
pavleradojkovic 0:ba7e439238ab 107 self.QoS == fh.QoS and \
pavleradojkovic 0:ba7e439238ab 108 self.RETAIN == fh.RETAIN # and \
pavleradojkovic 0:ba7e439238ab 109 # self.remainingLength == fh.remainingLength
pavleradojkovic 0:ba7e439238ab 110
pavleradojkovic 0:ba7e439238ab 111 def __repr__(self):
pavleradojkovic 0:ba7e439238ab 112 "return printable representation of our data"
pavleradojkovic 0:ba7e439238ab 113 return classNames[self.MessageType]+'(DUP='+repr(self.DUP)+ \
pavleradojkovic 0:ba7e439238ab 114 ", QoS="+repr(self.QoS)+", Retain="+repr(self.RETAIN)
pavleradojkovic 0:ba7e439238ab 115
pavleradojkovic 0:ba7e439238ab 116 def pack(self, length):
pavleradojkovic 0:ba7e439238ab 117 "pack data into string buffer ready for transmission down socket"
pavleradojkovic 0:ba7e439238ab 118 buffer = bytes([(self.MessageType << 4) | (self.DUP << 3) |\
pavleradojkovic 0:ba7e439238ab 119 (self.QoS << 1) | self.RETAIN])
pavleradojkovic 0:ba7e439238ab 120 self.remainingLength = length
pavleradojkovic 0:ba7e439238ab 121 buffer += self.encode(length)
pavleradojkovic 0:ba7e439238ab 122 return buffer
pavleradojkovic 0:ba7e439238ab 123
pavleradojkovic 0:ba7e439238ab 124 def encode(self, x):
pavleradojkovic 0:ba7e439238ab 125 assert 0 <= x <= 268435455
pavleradojkovic 0:ba7e439238ab 126 buffer = b''
pavleradojkovic 0:ba7e439238ab 127 while 1:
pavleradojkovic 0:ba7e439238ab 128 digit = x % 128
pavleradojkovic 0:ba7e439238ab 129 x //= 128
pavleradojkovic 0:ba7e439238ab 130 if x > 0:
pavleradojkovic 0:ba7e439238ab 131 digit |= 0x80
pavleradojkovic 0:ba7e439238ab 132 buffer += bytes([digit])
pavleradojkovic 0:ba7e439238ab 133 if x == 0:
pavleradojkovic 0:ba7e439238ab 134 break
pavleradojkovic 0:ba7e439238ab 135 return buffer
pavleradojkovic 0:ba7e439238ab 136
pavleradojkovic 0:ba7e439238ab 137 def unpack(self, buffer):
pavleradojkovic 0:ba7e439238ab 138 "unpack data from string buffer into separate fields"
pavleradojkovic 0:ba7e439238ab 139 b0 = ord(buffer[0])
pavleradojkovic 0:ba7e439238ab 140 self.MessageType = b0 >> 4
pavleradojkovic 0:ba7e439238ab 141 self.DUP = ((b0 >> 3) & 0x01) == 1
pavleradojkovic 0:ba7e439238ab 142 self.QoS = (b0 >> 1) & 0x03
pavleradojkovic 0:ba7e439238ab 143 self.RETAIN = (b0 & 0x01) == 1
pavleradojkovic 0:ba7e439238ab 144 (self.remainingLength, bytes) = self.decode(buffer[1:])
pavleradojkovic 0:ba7e439238ab 145 return bytes + 1 # length of fixed header
pavleradojkovic 0:ba7e439238ab 146
pavleradojkovic 0:ba7e439238ab 147 def decode(self, buffer):
pavleradojkovic 0:ba7e439238ab 148 multiplier = 1
pavleradojkovic 0:ba7e439238ab 149 value = 0
pavleradojkovic 0:ba7e439238ab 150 bytes = 0
pavleradojkovic 0:ba7e439238ab 151 while 1:
pavleradojkovic 0:ba7e439238ab 152 bytes += 1
pavleradojkovic 0:ba7e439238ab 153 digit = ord(buffer[0])
pavleradojkovic 0:ba7e439238ab 154 buffer = buffer[1:]
pavleradojkovic 0:ba7e439238ab 155 value += (digit & 127) * multiplier
pavleradojkovic 0:ba7e439238ab 156 if digit & 128 == 0:
pavleradojkovic 0:ba7e439238ab 157 break
pavleradojkovic 0:ba7e439238ab 158 multiplier *= 128
pavleradojkovic 0:ba7e439238ab 159 return (value, bytes)
pavleradojkovic 0:ba7e439238ab 160
pavleradojkovic 0:ba7e439238ab 161
pavleradojkovic 0:ba7e439238ab 162 def writeInt16(length):
pavleradojkovic 0:ba7e439238ab 163 return bytes([length // 256, length % 256])
pavleradojkovic 0:ba7e439238ab 164
pavleradojkovic 0:ba7e439238ab 165 def readInt16(buf):
pavleradojkovic 0:ba7e439238ab 166 return ord(buf[0])*256 + ord(buf[1])
pavleradojkovic 0:ba7e439238ab 167
pavleradojkovic 0:ba7e439238ab 168 def writeUTF(data):
pavleradojkovic 0:ba7e439238ab 169 # data could be a string, or bytes. If string, encode into bytes with utf-8
pavleradojkovic 0:ba7e439238ab 170 return writeInt16(len(data)) + (data if type(data) == type(b"") else bytes(data, "utf-8"))
pavleradojkovic 0:ba7e439238ab 171
pavleradojkovic 0:ba7e439238ab 172 def readUTF(buffer, maxlen):
pavleradojkovic 0:ba7e439238ab 173 if maxlen >= 2:
pavleradojkovic 0:ba7e439238ab 174 length = readInt16(buffer)
pavleradojkovic 0:ba7e439238ab 175 else:
pavleradojkovic 0:ba7e439238ab 176 raise MQTTException("Not enough data to read string length")
pavleradojkovic 0:ba7e439238ab 177 maxlen -= 2
pavleradojkovic 0:ba7e439238ab 178 if length > maxlen:
pavleradojkovic 0:ba7e439238ab 179 raise MQTTException("Length delimited string too long")
pavleradojkovic 0:ba7e439238ab 180 buf = buffer[2:2+length].decode("utf-8")
pavleradojkovic 0:ba7e439238ab 181 logger.info("[MQTT-4.7.3-2] topic names and filters not include null")
pavleradojkovic 0:ba7e439238ab 182 zz = buf.find("\x00") # look for null in the UTF string
pavleradojkovic 0:ba7e439238ab 183 if zz != -1:
pavleradojkovic 0:ba7e439238ab 184 raise MQTTException("[MQTT-1.5.3-2] Null found in UTF data "+buf)
pavleradojkovic 0:ba7e439238ab 185 """for c in range (0xD800, 0xDFFF):
pavleradojkovic 0:ba7e439238ab 186 zz = buf.find(chr(c)) # look for D800-DFFF in the UTF string
pavleradojkovic 0:ba7e439238ab 187 if zz != -1:
pavleradojkovic 0:ba7e439238ab 188 raise MQTTException("[MQTT-1.5.3-1] D800-DFFF found in UTF data "+buf)
pavleradojkovic 0:ba7e439238ab 189 """
pavleradojkovic 0:ba7e439238ab 190 if buf.find("\uFEFF") != -1:
pavleradojkovic 0:ba7e439238ab 191 logger.info("[MQTT-1.5.3-3] U+FEFF in UTF string")
pavleradojkovic 0:ba7e439238ab 192 return buf
pavleradojkovic 0:ba7e439238ab 193
pavleradojkovic 0:ba7e439238ab 194 def writeBytes(buffer):
pavleradojkovic 0:ba7e439238ab 195 return writeInt16(len(buffer)) + buffer
pavleradojkovic 0:ba7e439238ab 196
pavleradojkovic 0:ba7e439238ab 197 def readBytes(buffer):
pavleradojkovic 0:ba7e439238ab 198 length = readInt16(buffer)
pavleradojkovic 0:ba7e439238ab 199 return buffer[2:2+length]
pavleradojkovic 0:ba7e439238ab 200
pavleradojkovic 0:ba7e439238ab 201
pavleradojkovic 0:ba7e439238ab 202 class Packets:
pavleradojkovic 0:ba7e439238ab 203
pavleradojkovic 0:ba7e439238ab 204 def pack(self):
pavleradojkovic 0:ba7e439238ab 205 buffer = self.fh.pack(0)
pavleradojkovic 0:ba7e439238ab 206 return buffer
pavleradojkovic 0:ba7e439238ab 207
pavleradojkovic 0:ba7e439238ab 208 def __repr__(self):
pavleradojkovic 0:ba7e439238ab 209 return repr(self.fh)
pavleradojkovic 0:ba7e439238ab 210
pavleradojkovic 0:ba7e439238ab 211 def __eq__(self, packet):
pavleradojkovic 0:ba7e439238ab 212 return self.fh == packet.fh if packet else False
pavleradojkovic 0:ba7e439238ab 213
pavleradojkovic 0:ba7e439238ab 214
pavleradojkovic 0:ba7e439238ab 215 class Connects(Packets):
pavleradojkovic 0:ba7e439238ab 216
pavleradojkovic 0:ba7e439238ab 217 def __init__(self, buffer = None):
pavleradojkovic 0:ba7e439238ab 218 self.fh = FixedHeaders(CONNECT)
pavleradojkovic 0:ba7e439238ab 219
pavleradojkovic 0:ba7e439238ab 220 # variable header
pavleradojkovic 0:ba7e439238ab 221 self.ProtocolName = "MQTT"
pavleradojkovic 0:ba7e439238ab 222 self.ProtocolVersion = 4
pavleradojkovic 0:ba7e439238ab 223 self.CleanSession = True
pavleradojkovic 0:ba7e439238ab 224 self.WillFlag = False
pavleradojkovic 0:ba7e439238ab 225 self.WillQoS = 0
pavleradojkovic 0:ba7e439238ab 226 self.WillRETAIN = 0
pavleradojkovic 0:ba7e439238ab 227 self.KeepAliveTimer = 30
pavleradojkovic 0:ba7e439238ab 228 self.usernameFlag = False
pavleradojkovic 0:ba7e439238ab 229 self.passwordFlag = False
pavleradojkovic 0:ba7e439238ab 230
pavleradojkovic 0:ba7e439238ab 231 # Payload
pavleradojkovic 0:ba7e439238ab 232 self.ClientIdentifier = "" # UTF-8
pavleradojkovic 0:ba7e439238ab 233 self.WillTopic = None # UTF-8
pavleradojkovic 0:ba7e439238ab 234 self.WillMessage = None # binary
pavleradojkovic 0:ba7e439238ab 235 self.username = None # UTF-8
pavleradojkovic 0:ba7e439238ab 236 self.password = None # binary
pavleradojkovic 0:ba7e439238ab 237
pavleradojkovic 0:ba7e439238ab 238 if buffer != None:
pavleradojkovic 0:ba7e439238ab 239 self.unpack(buffer)
pavleradojkovic 0:ba7e439238ab 240
pavleradojkovic 0:ba7e439238ab 241 def pack(self):
pavleradojkovic 0:ba7e439238ab 242 connectFlags = bytes([(self.CleanSession << 1) | (self.WillFlag << 2) | \
pavleradojkovic 0:ba7e439238ab 243 (self.WillQoS << 3) | (self.WillRETAIN << 5) | \
pavleradojkovic 0:ba7e439238ab 244 (self.usernameFlag << 6) | (self.passwordFlag << 7)])
pavleradojkovic 0:ba7e439238ab 245 buffer = writeUTF(self.ProtocolName) + bytes([self.ProtocolVersion]) + \
pavleradojkovic 0:ba7e439238ab 246 connectFlags + writeInt16(self.KeepAliveTimer)
pavleradojkovic 0:ba7e439238ab 247 buffer += writeUTF(self.ClientIdentifier)
pavleradojkovic 0:ba7e439238ab 248 if self.WillFlag:
pavleradojkovic 0:ba7e439238ab 249 buffer += writeUTF(self.WillTopic)
pavleradojkovic 0:ba7e439238ab 250 buffer += writeBytes(self.WillMessage)
pavleradojkovic 0:ba7e439238ab 251 if self.usernameFlag:
pavleradojkovic 0:ba7e439238ab 252 buffer += writeUTF(self.username)
pavleradojkovic 0:ba7e439238ab 253 if self.passwordFlag:
pavleradojkovic 0:ba7e439238ab 254 buffer += writeBytes(self.password)
pavleradojkovic 0:ba7e439238ab 255 buffer = self.fh.pack(len(buffer)) + buffer
pavleradojkovic 0:ba7e439238ab 256 return buffer
pavleradojkovic 0:ba7e439238ab 257
pavleradojkovic 0:ba7e439238ab 258 def unpack(self, buffer):
pavleradojkovic 0:ba7e439238ab 259 assert len(buffer) >= 2
pavleradojkovic 0:ba7e439238ab 260 assert MessageType(buffer) == CONNECT
pavleradojkovic 0:ba7e439238ab 261
pavleradojkovic 0:ba7e439238ab 262 try:
pavleradojkovic 0:ba7e439238ab 263 fhlen = self.fh.unpack(buffer)
pavleradojkovic 0:ba7e439238ab 264 packlen = fhlen + self.fh.remainingLength
pavleradojkovic 0:ba7e439238ab 265 assert len(buffer) >= packlen, "buffer length %d packet length %d" % (len(buffer), packlen)
pavleradojkovic 0:ba7e439238ab 266 curlen = fhlen # points to after header + remaining length
pavleradojkovic 0:ba7e439238ab 267 assert self.fh.DUP == False, "[MQTT-2.1.2-1]"
pavleradojkovic 0:ba7e439238ab 268 assert self.fh.QoS == 0, "[MQTT-2.1.2-1] QoS was not 0, was %d" % self.fh.QoS
pavleradojkovic 0:ba7e439238ab 269 assert self.fh.RETAIN == False, "[MQTT-2.1.2-1]"
pavleradojkovic 0:ba7e439238ab 270
pavleradojkovic 0:ba7e439238ab 271 self.ProtocolName = readUTF(buffer[curlen:], packlen - curlen)
pavleradojkovic 0:ba7e439238ab 272 curlen += len(self.ProtocolName) + 2
pavleradojkovic 0:ba7e439238ab 273 assert self.ProtocolName == "MQTT", "Wrong protocol name %s" % self.ProtocolName
pavleradojkovic 0:ba7e439238ab 274
pavleradojkovic 0:ba7e439238ab 275 self.ProtocolVersion = ord(buffer[curlen])
pavleradojkovic 0:ba7e439238ab 276 curlen += 1
pavleradojkovic 0:ba7e439238ab 277
pavleradojkovic 0:ba7e439238ab 278 connectFlags = ord(buffer[curlen])
pavleradojkovic 0:ba7e439238ab 279 assert (connectFlags & 0x01) == 0, "[MQTT-3.1.2-3] reserved connect flag must be 0"
pavleradojkovic 0:ba7e439238ab 280 self.CleanSession = ((connectFlags >> 1) & 0x01) == 1
pavleradojkovic 0:ba7e439238ab 281 self.WillFlag = ((connectFlags >> 2) & 0x01) == 1
pavleradojkovic 0:ba7e439238ab 282 self.WillQoS = (connectFlags >> 3) & 0x03
pavleradojkovic 0:ba7e439238ab 283 self.WillRETAIN = (connectFlags >> 5) & 0x01
pavleradojkovic 0:ba7e439238ab 284 self.passwordFlag = ((connectFlags >> 6) & 0x01) == 1
pavleradojkovic 0:ba7e439238ab 285 self.usernameFlag = ((connectFlags >> 7) & 0x01) == 1
pavleradojkovic 0:ba7e439238ab 286 curlen +=1
pavleradojkovic 0:ba7e439238ab 287
pavleradojkovic 0:ba7e439238ab 288 if self.WillFlag:
pavleradojkovic 0:ba7e439238ab 289 assert self.WillQoS in [0, 1, 2], "[MQTT-3.1.2-14] will qos must not be 3"
pavleradojkovic 0:ba7e439238ab 290 else:
pavleradojkovic 0:ba7e439238ab 291 assert self.WillQoS == 0, "[MQTT-3.1.2-13] will qos must be 0, if will flag is false"
pavleradojkovic 0:ba7e439238ab 292 assert self.WillRETAIN == False, "[MQTT-3.1.2-14] will retain must be false, if will flag is false"
pavleradojkovic 0:ba7e439238ab 293
pavleradojkovic 0:ba7e439238ab 294 self.KeepAliveTimer = readInt16(buffer[curlen:])
pavleradojkovic 0:ba7e439238ab 295 curlen += 2
pavleradojkovic 0:ba7e439238ab 296 logger.info("[MQTT-3.1.3-3] Clientid must be present, and first field")
pavleradojkovic 0:ba7e439238ab 297 logger.info("[MQTT-3.1.3-4] Clientid must be Unicode, and between 0 and 65535 bytes long")
pavleradojkovic 0:ba7e439238ab 298 self.ClientIdentifier = readUTF(buffer[curlen:], packlen - curlen)
pavleradojkovic 0:ba7e439238ab 299 curlen += len(self.ClientIdentifier) + 2
pavleradojkovic 0:ba7e439238ab 300
pavleradojkovic 0:ba7e439238ab 301 if self.WillFlag:
pavleradojkovic 0:ba7e439238ab 302 self.WillTopic = readUTF(buffer[curlen:], packlen - curlen)
pavleradojkovic 0:ba7e439238ab 303 curlen += len(self.WillTopic) + 2
pavleradojkovic 0:ba7e439238ab 304 self.WillMessage = readBytes(buffer[curlen:])
pavleradojkovic 0:ba7e439238ab 305 curlen += len(self.WillMessage) + 2
pavleradojkovic 0:ba7e439238ab 306 logger.info("[[MQTT-3.1.2-9] will topic and will message fields must be present")
pavleradojkovic 0:ba7e439238ab 307 else:
pavleradojkovic 0:ba7e439238ab 308 self.WillTopic = self.WillMessage = None
pavleradojkovic 0:ba7e439238ab 309
pavleradojkovic 0:ba7e439238ab 310 if self.usernameFlag:
pavleradojkovic 0:ba7e439238ab 311 assert len(buffer) > curlen+2, "Buffer too short to read username length"
pavleradojkovic 0:ba7e439238ab 312 self.username = readUTF(buffer[curlen:], packlen - curlen)
pavleradojkovic 0:ba7e439238ab 313 curlen += len(self.username) + 2
pavleradojkovic 0:ba7e439238ab 314 logger.info("[MQTT-3.1.2-19] username must be in payload if user name flag is 1")
pavleradojkovic 0:ba7e439238ab 315 else:
pavleradojkovic 0:ba7e439238ab 316 logger.info("[MQTT-3.1.2-18] username must not be in payload if user name flag is 0")
pavleradojkovic 0:ba7e439238ab 317 assert self.passwordFlag == False, "[MQTT-3.1.2-22] password flag must be 0 if username flag is 0"
pavleradojkovic 0:ba7e439238ab 318
pavleradojkovic 0:ba7e439238ab 319 if self.passwordFlag:
pavleradojkovic 0:ba7e439238ab 320 assert len(buffer) > curlen+2, "Buffer too short to read password length"
pavleradojkovic 0:ba7e439238ab 321 self.password = readBytes(buffer[curlen:])
pavleradojkovic 0:ba7e439238ab 322 curlen += len(self.password) + 2
pavleradojkovic 0:ba7e439238ab 323 logger.info("[MQTT-3.1.2-21] password must be in payload if password flag is 0")
pavleradojkovic 0:ba7e439238ab 324 else:
pavleradojkovic 0:ba7e439238ab 325 logger.info("[MQTT-3.1.2-20] password must not be in payload if password flag is 0")
pavleradojkovic 0:ba7e439238ab 326
pavleradojkovic 0:ba7e439238ab 327 if self.WillFlag and self.usernameFlag and self.passwordFlag:
pavleradojkovic 0:ba7e439238ab 328 logger.info("[MQTT-3.1.3-1] clientid, will topic, will message, username and password all present")
pavleradojkovic 0:ba7e439238ab 329
pavleradojkovic 0:ba7e439238ab 330 assert curlen == packlen, "Packet is wrong length curlen %d != packlen %d"
pavleradojkovic 0:ba7e439238ab 331 except:
pavleradojkovic 0:ba7e439238ab 332 logger.exception("[MQTT-3.1.4-1] server must validate connect packet and close connection without connack if it does not conform")
pavleradojkovic 0:ba7e439238ab 333 raise
pavleradojkovic 0:ba7e439238ab 334
pavleradojkovic 0:ba7e439238ab 335
pavleradojkovic 0:ba7e439238ab 336
pavleradojkovic 0:ba7e439238ab 337 def __repr__(self):
pavleradojkovic 0:ba7e439238ab 338 buf = repr(self.fh)+", ProtocolName="+str(self.ProtocolName)+", ProtocolVersion=" +\
pavleradojkovic 0:ba7e439238ab 339 repr(self.ProtocolVersion)+", CleanSession="+repr(self.CleanSession) +\
pavleradojkovic 0:ba7e439238ab 340 ", WillFlag="+repr(self.WillFlag)+", KeepAliveTimer=" +\
pavleradojkovic 0:ba7e439238ab 341 repr(self.KeepAliveTimer)+", ClientId="+str(self.ClientIdentifier) +\
pavleradojkovic 0:ba7e439238ab 342 ", usernameFlag="+repr(self.usernameFlag)+", passwordFlag="+repr(self.passwordFlag)
pavleradojkovic 0:ba7e439238ab 343 if self.WillFlag:
pavleradojkovic 0:ba7e439238ab 344 buf += ", WillQoS=" + repr(self.WillQoS) +\
pavleradojkovic 0:ba7e439238ab 345 ", WillRETAIN=" + repr(self.WillRETAIN) +\
pavleradojkovic 0:ba7e439238ab 346 ", WillTopic='"+ self.WillTopic +\
pavleradojkovic 0:ba7e439238ab 347 "', WillMessage='"+str(self.WillMessage)+"'"
pavleradojkovic 0:ba7e439238ab 348 if self.username:
pavleradojkovic 0:ba7e439238ab 349 buf += ", username="+self.username
pavleradojkovic 0:ba7e439238ab 350 if self.password:
pavleradojkovic 0:ba7e439238ab 351 buf += ", password="+str(self.password)
pavleradojkovic 0:ba7e439238ab 352 return buf+")"
pavleradojkovic 0:ba7e439238ab 353
pavleradojkovic 0:ba7e439238ab 354 def __eq__(self, packet):
pavleradojkovic 0:ba7e439238ab 355 rc = Packets.__eq__(self, packet) and \
pavleradojkovic 0:ba7e439238ab 356 self.ProtocolName == packet.ProtocolName and \
pavleradojkovic 0:ba7e439238ab 357 self.ProtocolVersion == packet.ProtocolVersion and \
pavleradojkovic 0:ba7e439238ab 358 self.CleanSession == packet.CleanSession and \
pavleradojkovic 0:ba7e439238ab 359 self.WillFlag == packet.WillFlag and \
pavleradojkovic 0:ba7e439238ab 360 self.KeepAliveTimer == packet.KeepAliveTimer and \
pavleradojkovic 0:ba7e439238ab 361 self.ClientIdentifier == packet.ClientIdentifier and \
pavleradojkovic 0:ba7e439238ab 362 self.WillFlag == packet.WillFlag
pavleradojkovic 0:ba7e439238ab 363 if rc and self.WillFlag:
pavleradojkovic 0:ba7e439238ab 364 rc = self.WillQoS == packet.WillQoS and \
pavleradojkovic 0:ba7e439238ab 365 self.WillRETAIN == packet.WillRETAIN and \
pavleradojkovic 0:ba7e439238ab 366 self.WillTopic == packet.WillTopic and \
pavleradojkovic 0:ba7e439238ab 367 self.WillMessage == packet.WillMessage
pavleradojkovic 0:ba7e439238ab 368 return rc
pavleradojkovic 0:ba7e439238ab 369
pavleradojkovic 0:ba7e439238ab 370
pavleradojkovic 0:ba7e439238ab 371 class Connacks(Packets):
pavleradojkovic 0:ba7e439238ab 372
pavleradojkovic 0:ba7e439238ab 373 def __init__(self, buffer=None, DUP=False, QoS=0, Retain=False, ReturnCode=0):
pavleradojkovic 0:ba7e439238ab 374 self.fh = FixedHeaders(CONNACK)
pavleradojkovic 0:ba7e439238ab 375 self.fh.DUP = DUP
pavleradojkovic 0:ba7e439238ab 376 self.fh.QoS = QoS
pavleradojkovic 0:ba7e439238ab 377 self.fh.Retain = Retain
pavleradojkovic 0:ba7e439238ab 378 self.flags = 0
pavleradojkovic 0:ba7e439238ab 379 self.returnCode = ReturnCode
pavleradojkovic 0:ba7e439238ab 380 if buffer != None:
pavleradojkovic 0:ba7e439238ab 381 self.unpack(buffer)
pavleradojkovic 0:ba7e439238ab 382
pavleradojkovic 0:ba7e439238ab 383 def pack(self):
pavleradojkovic 0:ba7e439238ab 384 buffer = bytes([self.flags, self.returnCode])
pavleradojkovic 0:ba7e439238ab 385 buffer = self.fh.pack(len(buffer)) + buffer
pavleradojkovic 0:ba7e439238ab 386 return buffer
pavleradojkovic 0:ba7e439238ab 387
pavleradojkovic 0:ba7e439238ab 388 def unpack(self, buffer):
pavleradojkovic 0:ba7e439238ab 389 assert len(buffer) >= 4
pavleradojkovic 0:ba7e439238ab 390 assert MessageType(buffer) == CONNACK
pavleradojkovic 0:ba7e439238ab 391 self.fh.unpack(buffer)
pavleradojkovic 0:ba7e439238ab 392 assert self.fh.remainingLength == 2, "Connack packet is wrong length %d" % self.fh.remainingLength
pavleradojkovic 0:ba7e439238ab 393 assert ord(buffer[2]) in [0, 1], "Connect Acknowledge Flags"
pavleradojkovic 0:ba7e439238ab 394 self.returnCode = ord(buffer[3])
pavleradojkovic 0:ba7e439238ab 395 assert self.fh.DUP == False, "[MQTT-2.1.2-1]"
pavleradojkovic 0:ba7e439238ab 396 assert self.fh.QoS == 0, "[MQTT-2.1.2-1]"
pavleradojkovic 0:ba7e439238ab 397 assert self.fh.RETAIN == False, "[MQTT-2.1.2-1]"
pavleradojkovic 0:ba7e439238ab 398
pavleradojkovic 0:ba7e439238ab 399 def __repr__(self):
pavleradojkovic 0:ba7e439238ab 400 return repr(self.fh)+", Session present="+str((self.flags & 0x01) == 1)+", ReturnCode="+repr(self.returnCode)+")"
pavleradojkovic 0:ba7e439238ab 401
pavleradojkovic 0:ba7e439238ab 402 def __eq__(self, packet):
pavleradojkovic 0:ba7e439238ab 403 return Packets.__eq__(self, packet) and \
pavleradojkovic 0:ba7e439238ab 404 self.returnCode == packet.returnCode
pavleradojkovic 0:ba7e439238ab 405
pavleradojkovic 0:ba7e439238ab 406
pavleradojkovic 0:ba7e439238ab 407 class Disconnects(Packets):
pavleradojkovic 0:ba7e439238ab 408
pavleradojkovic 0:ba7e439238ab 409 def __init__(self, buffer=None, DUP=False, QoS=0, Retain=False):
pavleradojkovic 0:ba7e439238ab 410 self.fh = FixedHeaders(DISCONNECT)
pavleradojkovic 0:ba7e439238ab 411 self.fh.DUP = DUP
pavleradojkovic 0:ba7e439238ab 412 self.fh.QoS = QoS
pavleradojkovic 0:ba7e439238ab 413 self.fh.Retain = Retain
pavleradojkovic 0:ba7e439238ab 414 if buffer != None:
pavleradojkovic 0:ba7e439238ab 415 self.unpack(buffer)
pavleradojkovic 0:ba7e439238ab 416
pavleradojkovic 0:ba7e439238ab 417 def unpack(self, buffer):
pavleradojkovic 0:ba7e439238ab 418 assert len(buffer) >= 2
pavleradojkovic 0:ba7e439238ab 419 assert MessageType(buffer) == DISCONNECT
pavleradojkovic 0:ba7e439238ab 420 self.fh.unpack(buffer)
pavleradojkovic 0:ba7e439238ab 421 assert self.fh.remainingLength == 0, "Disconnect packet is wrong length %d" % self.fh.remainingLength
pavleradojkovic 0:ba7e439238ab 422 logger.info("[MQTT-3.14.1-1] disconnect reserved bits must be 0")
pavleradojkovic 0:ba7e439238ab 423 assert self.fh.DUP == False, "[MQTT-2.1.2-1]"
pavleradojkovic 0:ba7e439238ab 424 assert self.fh.QoS == 0, "[MQTT-2.1.2-1]"
pavleradojkovic 0:ba7e439238ab 425 assert self.fh.RETAIN == False, "[MQTT-2.1.2-1]"
pavleradojkovic 0:ba7e439238ab 426
pavleradojkovic 0:ba7e439238ab 427 def __repr__(self):
pavleradojkovic 0:ba7e439238ab 428 return repr(self.fh)+")"
pavleradojkovic 0:ba7e439238ab 429
pavleradojkovic 0:ba7e439238ab 430
pavleradojkovic 0:ba7e439238ab 431 class Publishes(Packets):
pavleradojkovic 0:ba7e439238ab 432
pavleradojkovic 0:ba7e439238ab 433 def __init__(self, buffer=None, DUP=False, QoS=0, Retain=False, MsgId=0, TopicName="", Payload=b""):
pavleradojkovic 0:ba7e439238ab 434 self.fh = FixedHeaders(PUBLISH)
pavleradojkovic 0:ba7e439238ab 435 self.fh.DUP = DUP
pavleradojkovic 0:ba7e439238ab 436 self.fh.QoS = QoS
pavleradojkovic 0:ba7e439238ab 437 self.fh.Retain = Retain
pavleradojkovic 0:ba7e439238ab 438 # variable header
pavleradojkovic 0:ba7e439238ab 439 self.topicName = TopicName
pavleradojkovic 0:ba7e439238ab 440 self.messageIdentifier = MsgId
pavleradojkovic 0:ba7e439238ab 441 # payload
pavleradojkovic 0:ba7e439238ab 442 self.data = Payload
pavleradojkovic 0:ba7e439238ab 443 if buffer != None:
pavleradojkovic 0:ba7e439238ab 444 self.unpack(buffer)
pavleradojkovic 0:ba7e439238ab 445
pavleradojkovic 0:ba7e439238ab 446 def pack(self):
pavleradojkovic 0:ba7e439238ab 447 buffer = writeUTF(self.topicName)
pavleradojkovic 0:ba7e439238ab 448 if self.fh.QoS != 0:
pavleradojkovic 0:ba7e439238ab 449 buffer += writeInt16(self.messageIdentifier)
pavleradojkovic 0:ba7e439238ab 450 buffer += self.data
pavleradojkovic 0:ba7e439238ab 451 buffer = self.fh.pack(len(buffer)) + buffer
pavleradojkovic 0:ba7e439238ab 452 return buffer
pavleradojkovic 0:ba7e439238ab 453
pavleradojkovic 0:ba7e439238ab 454 def unpack(self, buffer):
pavleradojkovic 0:ba7e439238ab 455 assert len(buffer) >= 2
pavleradojkovic 0:ba7e439238ab 456 assert MessageType(buffer) == PUBLISH
pavleradojkovic 0:ba7e439238ab 457 fhlen = self.fh.unpack(buffer)
pavleradojkovic 0:ba7e439238ab 458 assert self.fh.QoS in [0, 1, 2], "QoS in Publish must be 0, 1, or 2"
pavleradojkovic 0:ba7e439238ab 459 packlen = fhlen + self.fh.remainingLength
pavleradojkovic 0:ba7e439238ab 460 assert len(buffer) >= packlen
pavleradojkovic 0:ba7e439238ab 461 curlen = fhlen
pavleradojkovic 0:ba7e439238ab 462 try:
pavleradojkovic 0:ba7e439238ab 463 self.topicName = readUTF(buffer[fhlen:], packlen - curlen)
pavleradojkovic 0:ba7e439238ab 464 except UnicodeDecodeError:
pavleradojkovic 0:ba7e439238ab 465 logger.info("[MQTT-3.3.2-1] topic name in publish must be utf-8")
pavleradojkovic 0:ba7e439238ab 466 raise
pavleradojkovic 0:ba7e439238ab 467 curlen += len(self.topicName) + 2
pavleradojkovic 0:ba7e439238ab 468 if self.fh.QoS != 0:
pavleradojkovic 0:ba7e439238ab 469 self.messageIdentifier = readInt16(buffer[curlen:])
pavleradojkovic 0:ba7e439238ab 470 logger.info("[MQTT-2.3.1-1] packet indentifier must be in publish if QoS is 1 or 2")
pavleradojkovic 0:ba7e439238ab 471 curlen += 2
pavleradojkovic 0:ba7e439238ab 472 assert self.messageIdentifier > 0, "[MQTT-2.3.1-1] packet indentifier must be > 0"
pavleradojkovic 0:ba7e439238ab 473 else:
pavleradojkovic 0:ba7e439238ab 474 logger.info("[MQTT-2.3.1-5] no packet indentifier in publish if QoS is 0")
pavleradojkovic 0:ba7e439238ab 475 self.messageIdentifier = 0
pavleradojkovic 0:ba7e439238ab 476 self.data = buffer[curlen:fhlen + self.fh.remainingLength]
pavleradojkovic 0:ba7e439238ab 477 if self.fh.QoS == 0:
pavleradojkovic 0:ba7e439238ab 478 assert self.fh.DUP == False, "[MQTT-2.1.2-4]"
pavleradojkovic 0:ba7e439238ab 479 return fhlen + self.fh.remainingLength
pavleradojkovic 0:ba7e439238ab 480
pavleradojkovic 0:ba7e439238ab 481 def __repr__(self):
pavleradojkovic 0:ba7e439238ab 482 rc = repr(self.fh)
pavleradojkovic 0:ba7e439238ab 483 if self.fh.QoS != 0:
pavleradojkovic 0:ba7e439238ab 484 rc += ", MsgId="+repr(self.messageIdentifier)
pavleradojkovic 0:ba7e439238ab 485 rc += ", TopicName="+repr(self.topicName)+", Payload="+repr(self.data)+")"
pavleradojkovic 0:ba7e439238ab 486 return rc
pavleradojkovic 0:ba7e439238ab 487
pavleradojkovic 0:ba7e439238ab 488 def __eq__(self, packet):
pavleradojkovic 0:ba7e439238ab 489 rc = Packets.__eq__(self, packet) and \
pavleradojkovic 0:ba7e439238ab 490 self.topicName == packet.topicName and \
pavleradojkovic 0:ba7e439238ab 491 self.data == packet.data
pavleradojkovic 0:ba7e439238ab 492 if rc and self.fh.QoS != 0:
pavleradojkovic 0:ba7e439238ab 493 rc = self.messageIdentifier == packet.messageIdentifier
pavleradojkovic 0:ba7e439238ab 494 return rc
pavleradojkovic 0:ba7e439238ab 495
pavleradojkovic 0:ba7e439238ab 496
pavleradojkovic 0:ba7e439238ab 497 class Pubacks(Packets):
pavleradojkovic 0:ba7e439238ab 498
pavleradojkovic 0:ba7e439238ab 499 def __init__(self, buffer=None, DUP=False, QoS=0, Retain=False, MsgId=0):
pavleradojkovic 0:ba7e439238ab 500 self.fh = FixedHeaders(PUBACK)
pavleradojkovic 0:ba7e439238ab 501 self.fh.DUP = DUP
pavleradojkovic 0:ba7e439238ab 502 self.fh.QoS = QoS
pavleradojkovic 0:ba7e439238ab 503 self.fh.Retain = Retain
pavleradojkovic 0:ba7e439238ab 504 # variable header
pavleradojkovic 0:ba7e439238ab 505 self.messageIdentifier = MsgId
pavleradojkovic 0:ba7e439238ab 506 if buffer != None:
pavleradojkovic 0:ba7e439238ab 507 self.unpack(buffer)
pavleradojkovic 0:ba7e439238ab 508
pavleradojkovic 0:ba7e439238ab 509 def pack(self):
pavleradojkovic 0:ba7e439238ab 510 buffer = writeInt16(self.messageIdentifier)
pavleradojkovic 0:ba7e439238ab 511 buffer = self.fh.pack(len(buffer)) + buffer
pavleradojkovic 0:ba7e439238ab 512 return buffer
pavleradojkovic 0:ba7e439238ab 513
pavleradojkovic 0:ba7e439238ab 514 def unpack(self, buffer):
pavleradojkovic 0:ba7e439238ab 515 assert len(buffer) >= 2
pavleradojkovic 0:ba7e439238ab 516 assert MessageType(buffer) == PUBACK
pavleradojkovic 0:ba7e439238ab 517 fhlen = self.fh.unpack(buffer)
pavleradojkovic 0:ba7e439238ab 518 assert self.fh.remainingLength == 2, "Puback packet is wrong length %d" % self.fh.remainingLength
pavleradojkovic 0:ba7e439238ab 519 assert len(buffer) >= fhlen + self.fh.remainingLength
pavleradojkovic 0:ba7e439238ab 520 self.messageIdentifier = readInt16(buffer[fhlen:])
pavleradojkovic 0:ba7e439238ab 521 assert self.fh.DUP == False, "[MQTT-2.1.2-1] Puback reserved bits must be 0"
pavleradojkovic 0:ba7e439238ab 522 assert self.fh.QoS == 0, "[MQTT-2.1.2-1] Puback reserved bits must be 0"
pavleradojkovic 0:ba7e439238ab 523 assert self.fh.RETAIN == False, "[MQTT-2.1.2-1] Puback reserved bits must be 0"
pavleradojkovic 0:ba7e439238ab 524 return fhlen + 2
pavleradojkovic 0:ba7e439238ab 525
pavleradojkovic 0:ba7e439238ab 526 def __repr__(self):
pavleradojkovic 0:ba7e439238ab 527 return repr(self.fh)+", MsgId "+repr(self.messageIdentifier)
pavleradojkovic 0:ba7e439238ab 528
pavleradojkovic 0:ba7e439238ab 529 def __eq__(self, packet):
pavleradojkovic 0:ba7e439238ab 530 return Packets.__eq__(self, packet) and \
pavleradojkovic 0:ba7e439238ab 531 self.messageIdentifier == packet.messageIdentifier
pavleradojkovic 0:ba7e439238ab 532
pavleradojkovic 0:ba7e439238ab 533
pavleradojkovic 0:ba7e439238ab 534 class Pubrecs(Packets):
pavleradojkovic 0:ba7e439238ab 535
pavleradojkovic 0:ba7e439238ab 536 def __init__(self, buffer=None, DUP=False, QoS=0, Retain=False, MsgId=0):
pavleradojkovic 0:ba7e439238ab 537 self.fh = FixedHeaders(PUBREC)
pavleradojkovic 0:ba7e439238ab 538 self.fh.DUP = DUP
pavleradojkovic 0:ba7e439238ab 539 self.fh.QoS = QoS
pavleradojkovic 0:ba7e439238ab 540 self.fh.Retain = Retain
pavleradojkovic 0:ba7e439238ab 541 # variable header
pavleradojkovic 0:ba7e439238ab 542 self.messageIdentifier = MsgId
pavleradojkovic 0:ba7e439238ab 543 if buffer != None:
pavleradojkovic 0:ba7e439238ab 544 self.unpack(buffer)
pavleradojkovic 0:ba7e439238ab 545
pavleradojkovic 0:ba7e439238ab 546 def pack(self):
pavleradojkovic 0:ba7e439238ab 547 buffer = writeInt16(self.messageIdentifier)
pavleradojkovic 0:ba7e439238ab 548 buffer = self.fh.pack(len(buffer)) + buffer
pavleradojkovic 0:ba7e439238ab 549 return buffer
pavleradojkovic 0:ba7e439238ab 550
pavleradojkovic 0:ba7e439238ab 551 def unpack(self, buffer):
pavleradojkovic 0:ba7e439238ab 552 assert len(buffer) >= 2
pavleradojkovic 0:ba7e439238ab 553 assert MessageType(buffer) == PUBREC
pavleradojkovic 0:ba7e439238ab 554 fhlen = self.fh.unpack(buffer)
pavleradojkovic 0:ba7e439238ab 555 assert self.fh.remainingLength == 2, "Pubrec packet is wrong length %d" % self.fh.remainingLength
pavleradojkovic 0:ba7e439238ab 556 assert len(buffer) >= fhlen + self.fh.remainingLength
pavleradojkovic 0:ba7e439238ab 557 self.messageIdentifier = readInt16(buffer[fhlen:])
pavleradojkovic 0:ba7e439238ab 558 assert self.fh.DUP == False, "[MQTT-2.1.2-1] Pubrec reserved bits must be 0"
pavleradojkovic 0:ba7e439238ab 559 assert self.fh.QoS == 0, "[MQTT-2.1.2-1] Pubrec reserved bits must be 0"
pavleradojkovic 0:ba7e439238ab 560 assert self.fh.RETAIN == False, "[MQTT-2.1.2-1] Pubrec reserved bits must be 0"
pavleradojkovic 0:ba7e439238ab 561 return fhlen + 2
pavleradojkovic 0:ba7e439238ab 562
pavleradojkovic 0:ba7e439238ab 563 def __repr__(self):
pavleradojkovic 0:ba7e439238ab 564 return repr(self.fh)+", MsgId="+repr(self.messageIdentifier)+")"
pavleradojkovic 0:ba7e439238ab 565
pavleradojkovic 0:ba7e439238ab 566 def __eq__(self, packet):
pavleradojkovic 0:ba7e439238ab 567 return Packets.__eq__(self, packet) and \
pavleradojkovic 0:ba7e439238ab 568 self.messageIdentifier == packet.messageIdentifier
pavleradojkovic 0:ba7e439238ab 569
pavleradojkovic 0:ba7e439238ab 570
pavleradojkovic 0:ba7e439238ab 571 class Pubrels(Packets):
pavleradojkovic 0:ba7e439238ab 572
pavleradojkovic 0:ba7e439238ab 573 def __init__(self, buffer=None, DUP=False, QoS=1, Retain=False, MsgId=0):
pavleradojkovic 0:ba7e439238ab 574 self.fh = FixedHeaders(PUBREL)
pavleradojkovic 0:ba7e439238ab 575 self.fh.DUP = DUP
pavleradojkovic 0:ba7e439238ab 576 self.fh.QoS = QoS
pavleradojkovic 0:ba7e439238ab 577 self.fh.Retain = Retain
pavleradojkovic 0:ba7e439238ab 578 # variable header
pavleradojkovic 0:ba7e439238ab 579 self.messageIdentifier = MsgId
pavleradojkovic 0:ba7e439238ab 580 if buffer != None:
pavleradojkovic 0:ba7e439238ab 581 self.unpack(buffer)
pavleradojkovic 0:ba7e439238ab 582
pavleradojkovic 0:ba7e439238ab 583 def pack(self):
pavleradojkovic 0:ba7e439238ab 584 buffer = writeInt16(self.messageIdentifier)
pavleradojkovic 0:ba7e439238ab 585 buffer = self.fh.pack(len(buffer)) + buffer
pavleradojkovic 0:ba7e439238ab 586 return buffer
pavleradojkovic 0:ba7e439238ab 587
pavleradojkovic 0:ba7e439238ab 588 def unpack(self, buffer):
pavleradojkovic 0:ba7e439238ab 589 assert len(buffer) >= 2
pavleradojkovic 0:ba7e439238ab 590 assert MessageType(buffer) == PUBREL
pavleradojkovic 0:ba7e439238ab 591 fhlen = self.fh.unpack(buffer)
pavleradojkovic 0:ba7e439238ab 592 assert self.fh.remainingLength == 2, "Pubrel packet is wrong length %d" % self.fh.remainingLength
pavleradojkovic 0:ba7e439238ab 593 assert len(buffer) >= fhlen + self.fh.remainingLength
pavleradojkovic 0:ba7e439238ab 594 self.messageIdentifier = readInt16(buffer[fhlen:])
pavleradojkovic 0:ba7e439238ab 595 assert self.fh.DUP == False, "[MQTT-2.1.2-1] DUP should be False in PUBREL"
pavleradojkovic 0:ba7e439238ab 596 assert self.fh.QoS == 1, "[MQTT-2.1.2-1] QoS should be 1 in PUBREL"
pavleradojkovic 0:ba7e439238ab 597 assert self.fh.RETAIN == False, "[MQTT-2.1.2-1] RETAIN should be False in PUBREL"
pavleradojkovic 0:ba7e439238ab 598 logger.info("[MQTT-3.6.1-1] bits in fixed header for pubrel are ok")
pavleradojkovic 0:ba7e439238ab 599 return fhlen + 2
pavleradojkovic 0:ba7e439238ab 600
pavleradojkovic 0:ba7e439238ab 601 def __repr__(self):
pavleradojkovic 0:ba7e439238ab 602 return repr(self.fh)+", MsgId="+repr(self.messageIdentifier)+")"
pavleradojkovic 0:ba7e439238ab 603
pavleradojkovic 0:ba7e439238ab 604 def __eq__(self, packet):
pavleradojkovic 0:ba7e439238ab 605 return Packets.__eq__(self, packet) and \
pavleradojkovic 0:ba7e439238ab 606 self.messageIdentifier == packet.messageIdentifier
pavleradojkovic 0:ba7e439238ab 607
pavleradojkovic 0:ba7e439238ab 608
pavleradojkovic 0:ba7e439238ab 609 class Pubcomps(Packets):
pavleradojkovic 0:ba7e439238ab 610
pavleradojkovic 0:ba7e439238ab 611 def __init__(self, buffer=None, DUP=False, QoS=0, Retain=False, MsgId=0):
pavleradojkovic 0:ba7e439238ab 612 self.fh = FixedHeaders(PUBCOMP)
pavleradojkovic 0:ba7e439238ab 613 self.fh.DUP = DUP
pavleradojkovic 0:ba7e439238ab 614 self.fh.QoS = QoS
pavleradojkovic 0:ba7e439238ab 615 self.fh.Retain = Retain
pavleradojkovic 0:ba7e439238ab 616 # variable header
pavleradojkovic 0:ba7e439238ab 617 self.messageIdentifier = MsgId
pavleradojkovic 0:ba7e439238ab 618 if buffer != None:
pavleradojkovic 0:ba7e439238ab 619 self.unpack(buffer)
pavleradojkovic 0:ba7e439238ab 620
pavleradojkovic 0:ba7e439238ab 621 def pack(self):
pavleradojkovic 0:ba7e439238ab 622 buffer = writeInt16(self.messageIdentifier)
pavleradojkovic 0:ba7e439238ab 623 buffer = self.fh.pack(len(buffer)) + buffer
pavleradojkovic 0:ba7e439238ab 624 return buffer
pavleradojkovic 0:ba7e439238ab 625
pavleradojkovic 0:ba7e439238ab 626 def unpack(self, buffer):
pavleradojkovic 0:ba7e439238ab 627 assert len(buffer) >= 2
pavleradojkovic 0:ba7e439238ab 628 assert MessageType(buffer) == PUBCOMP
pavleradojkovic 0:ba7e439238ab 629 fhlen = self.fh.unpack(buffer)
pavleradojkovic 0:ba7e439238ab 630 assert len(buffer) >= fhlen + self.fh.remainingLength
pavleradojkovic 0:ba7e439238ab 631 assert self.fh.remainingLength == 2, "Pubcomp packet is wrong length %d" % self.fh.remainingLength
pavleradojkovic 0:ba7e439238ab 632 self.messageIdentifier = readInt16(buffer[fhlen:])
pavleradojkovic 0:ba7e439238ab 633 assert self.fh.DUP == False, "[MQTT-2.1.2-1] DUP should be False in Pubcomp"
pavleradojkovic 0:ba7e439238ab 634 assert self.fh.QoS == 0, "[MQTT-2.1.2-1] QoS should be 0 in Pubcomp"
pavleradojkovic 0:ba7e439238ab 635 assert self.fh.RETAIN == False, "[MQTT-2.1.2-1] Retain should be false in Pubcomp"
pavleradojkovic 0:ba7e439238ab 636 return fhlen + 2
pavleradojkovic 0:ba7e439238ab 637
pavleradojkovic 0:ba7e439238ab 638 def __repr__(self):
pavleradojkovic 0:ba7e439238ab 639 return repr(self.fh)+", MsgId="+repr(self.messageIdentifier)+")"
pavleradojkovic 0:ba7e439238ab 640
pavleradojkovic 0:ba7e439238ab 641 def __eq__(self, packet):
pavleradojkovic 0:ba7e439238ab 642 return Packets.__eq__(self, packet) and \
pavleradojkovic 0:ba7e439238ab 643 self.messageIdentifier == packet.messageIdentifier
pavleradojkovic 0:ba7e439238ab 644
pavleradojkovic 0:ba7e439238ab 645
pavleradojkovic 0:ba7e439238ab 646 class Subscribes(Packets):
pavleradojkovic 0:ba7e439238ab 647
pavleradojkovic 0:ba7e439238ab 648 def __init__(self, buffer=None, DUP=False, QoS=1, Retain=False, MsgId=0, Data=[]):
pavleradojkovic 0:ba7e439238ab 649 self.fh = FixedHeaders(SUBSCRIBE)
pavleradojkovic 0:ba7e439238ab 650 self.fh.DUP = DUP
pavleradojkovic 0:ba7e439238ab 651 self.fh.QoS = QoS
pavleradojkovic 0:ba7e439238ab 652 self.fh.Retain = Retain
pavleradojkovic 0:ba7e439238ab 653 # variable header
pavleradojkovic 0:ba7e439238ab 654 self.messageIdentifier = MsgId
pavleradojkovic 0:ba7e439238ab 655 # payload - list of topic, qos pairs
pavleradojkovic 0:ba7e439238ab 656 self.data = Data[:]
pavleradojkovic 0:ba7e439238ab 657 if buffer != None:
pavleradojkovic 0:ba7e439238ab 658 self.unpack(buffer)
pavleradojkovic 0:ba7e439238ab 659
pavleradojkovic 0:ba7e439238ab 660 def pack(self):
pavleradojkovic 0:ba7e439238ab 661 buffer = writeInt16(self.messageIdentifier)
pavleradojkovic 0:ba7e439238ab 662 for d in self.data:
pavleradojkovic 0:ba7e439238ab 663 buffer += writeUTF(d[0]) + bytes([d[1]])
pavleradojkovic 0:ba7e439238ab 664 buffer = self.fh.pack(len(buffer)) + buffer
pavleradojkovic 0:ba7e439238ab 665 return buffer
pavleradojkovic 0:ba7e439238ab 666
pavleradojkovic 0:ba7e439238ab 667 def unpack(self, buffer):
pavleradojkovic 0:ba7e439238ab 668 assert len(buffer) >= 2
pavleradojkovic 0:ba7e439238ab 669 assert MessageType(buffer) == SUBSCRIBE
pavleradojkovic 0:ba7e439238ab 670 fhlen = self.fh.unpack(buffer)
pavleradojkovic 0:ba7e439238ab 671 assert len(buffer) >= fhlen + self.fh.remainingLength
pavleradojkovic 0:ba7e439238ab 672 logger.info("[MQTT-2.3.1-1] packet indentifier must be in subscribe")
pavleradojkovic 0:ba7e439238ab 673 self.messageIdentifier = readInt16(buffer[fhlen:])
pavleradojkovic 0:ba7e439238ab 674 assert self.messageIdentifier > 0, "[MQTT-2.3.1-1] packet indentifier must be > 0"
pavleradojkovic 0:ba7e439238ab 675 leftlen = self.fh.remainingLength - 2
pavleradojkovic 0:ba7e439238ab 676 self.data = []
pavleradojkovic 0:ba7e439238ab 677 while leftlen > 0:
pavleradojkovic 0:ba7e439238ab 678 topic = readUTF(buffer[-leftlen:], leftlen)
pavleradojkovic 0:ba7e439238ab 679 leftlen -= len(topic) + 2
pavleradojkovic 0:ba7e439238ab 680 qos = ord(buffer[-leftlen])
pavleradojkovic 0:ba7e439238ab 681 assert qos in [0, 1, 2], "[MQTT-3-8.3-2] reserved bits must be zero"
pavleradojkovic 0:ba7e439238ab 682 leftlen -= 1
pavleradojkovic 0:ba7e439238ab 683 self.data.append((topic, qos))
pavleradojkovic 0:ba7e439238ab 684 assert len(self.data) > 0, "[MQTT-3.8.3-1] at least one topic, qos pair must be in subscribe"
pavleradojkovic 0:ba7e439238ab 685 assert leftlen == 0
pavleradojkovic 0:ba7e439238ab 686 assert self.fh.DUP == False, "[MQTT-2.1.2-1] DUP must be false in subscribe"
pavleradojkovic 0:ba7e439238ab 687 assert self.fh.QoS == 1, "[MQTT-2.1.2-1] QoS must be 1 in subscribe"
pavleradojkovic 0:ba7e439238ab 688 assert self.fh.RETAIN == False, "[MQTT-2.1.2-1] RETAIN must be false in subscribe"
pavleradojkovic 0:ba7e439238ab 689 return fhlen + self.fh.remainingLength
pavleradojkovic 0:ba7e439238ab 690
pavleradojkovic 0:ba7e439238ab 691 def __repr__(self):
pavleradojkovic 0:ba7e439238ab 692 return repr(self.fh)+", MsgId="+repr(self.messageIdentifier)+\
pavleradojkovic 0:ba7e439238ab 693 ", Data="+repr(self.data)+")"
pavleradojkovic 0:ba7e439238ab 694
pavleradojkovic 0:ba7e439238ab 695 def __eq__(self, packet):
pavleradojkovic 0:ba7e439238ab 696 return Packets.__eq__(self, packet) and \
pavleradojkovic 0:ba7e439238ab 697 self.messageIdentifier == packet.messageIdentifier and \
pavleradojkovic 0:ba7e439238ab 698 self.data == packet.data
pavleradojkovic 0:ba7e439238ab 699
pavleradojkovic 0:ba7e439238ab 700
pavleradojkovic 0:ba7e439238ab 701 class Subacks(Packets):
pavleradojkovic 0:ba7e439238ab 702
pavleradojkovic 0:ba7e439238ab 703 def __init__(self, buffer=None, DUP=False, QoS=0, Retain=False, MsgId=0, Data=[]):
pavleradojkovic 0:ba7e439238ab 704 self.fh = FixedHeaders(SUBACK)
pavleradojkovic 0:ba7e439238ab 705 self.fh.DUP = DUP
pavleradojkovic 0:ba7e439238ab 706 self.fh.QoS = QoS
pavleradojkovic 0:ba7e439238ab 707 self.fh.Retain = Retain
pavleradojkovic 0:ba7e439238ab 708 # variable header
pavleradojkovic 0:ba7e439238ab 709 self.messageIdentifier = MsgId
pavleradojkovic 0:ba7e439238ab 710 # payload - list of qos
pavleradojkovic 0:ba7e439238ab 711 self.data = Data[:]
pavleradojkovic 0:ba7e439238ab 712 if buffer != None:
pavleradojkovic 0:ba7e439238ab 713 self.unpack(buffer)
pavleradojkovic 0:ba7e439238ab 714
pavleradojkovic 0:ba7e439238ab 715 def pack(self):
pavleradojkovic 0:ba7e439238ab 716 buffer = writeInt16(self.messageIdentifier)
pavleradojkovic 0:ba7e439238ab 717 for d in self.data:
pavleradojkovic 0:ba7e439238ab 718 buffer += bytes([d])
pavleradojkovic 0:ba7e439238ab 719 buffer = self.fh.pack(len(buffer)) + buffer
pavleradojkovic 0:ba7e439238ab 720 return buffer
pavleradojkovic 0:ba7e439238ab 721
pavleradojkovic 0:ba7e439238ab 722 def unpack(self, buffer):
pavleradojkovic 0:ba7e439238ab 723 assert len(buffer) >= 2
pavleradojkovic 0:ba7e439238ab 724 assert MessageType(buffer) == SUBACK
pavleradojkovic 0:ba7e439238ab 725 fhlen = self.fh.unpack(buffer)
pavleradojkovic 0:ba7e439238ab 726 assert len(buffer) >= fhlen + self.fh.remainingLength
pavleradojkovic 0:ba7e439238ab 727 self.messageIdentifier = readInt16(buffer[fhlen:])
pavleradojkovic 0:ba7e439238ab 728 leftlen = self.fh.remainingLength - 2
pavleradojkovic 0:ba7e439238ab 729 self.data = []
pavleradojkovic 0:ba7e439238ab 730 while leftlen > 0:
pavleradojkovic 0:ba7e439238ab 731 qos = buffer[-leftlen]
pavleradojkovic 0:ba7e439238ab 732 assert ord(qos) in [0, 1, 2, 0x80], "[MQTT-3.9.3-2] return code in QoS must be 0, 1, 2 or 0x80, was "+ord(qos)
pavleradojkovic 0:ba7e439238ab 733 leftlen -= 1
pavleradojkovic 0:ba7e439238ab 734 self.data.append(qos)
pavleradojkovic 0:ba7e439238ab 735 assert leftlen == 0
pavleradojkovic 0:ba7e439238ab 736 assert self.fh.DUP == False, "[MQTT-2.1.2-1] DUP should be false in suback"
pavleradojkovic 0:ba7e439238ab 737 assert self.fh.QoS == 0, "[MQTT-2.1.2-1] QoS should be 0 in suback"
pavleradojkovic 0:ba7e439238ab 738 assert self.fh.RETAIN == False, "[MQTT-2.1.2-1] Retain should be false in suback"
pavleradojkovic 0:ba7e439238ab 739 return fhlen + self.fh.remainingLength
pavleradojkovic 0:ba7e439238ab 740
pavleradojkovic 0:ba7e439238ab 741 def __repr__(self):
pavleradojkovic 0:ba7e439238ab 742 return repr(self.fh)+", MsgId="+repr(self.messageIdentifier)+\
pavleradojkovic 0:ba7e439238ab 743 ", Data="+repr(self.data)+")"
pavleradojkovic 0:ba7e439238ab 744
pavleradojkovic 0:ba7e439238ab 745 def __eq__(self, packet):
pavleradojkovic 0:ba7e439238ab 746 return Packets.__eq__(self, packet) and \
pavleradojkovic 0:ba7e439238ab 747 self.messageIdentifier == packet.messageIdentifier and \
pavleradojkovic 0:ba7e439238ab 748 self.data == packet.data
pavleradojkovic 0:ba7e439238ab 749
pavleradojkovic 0:ba7e439238ab 750
pavleradojkovic 0:ba7e439238ab 751 class Unsubscribes(Packets):
pavleradojkovic 0:ba7e439238ab 752
pavleradojkovic 0:ba7e439238ab 753 def __init__(self, buffer=None, DUP=False, QoS=1, Retain=False, MsgId=0, Data=[]):
pavleradojkovic 0:ba7e439238ab 754 self.fh = FixedHeaders(UNSUBSCRIBE)
pavleradojkovic 0:ba7e439238ab 755 self.fh.DUP = DUP
pavleradojkovic 0:ba7e439238ab 756 self.fh.QoS = QoS
pavleradojkovic 0:ba7e439238ab 757 self.fh.Retain = Retain
pavleradojkovic 0:ba7e439238ab 758 # variable header
pavleradojkovic 0:ba7e439238ab 759 self.messageIdentifier = MsgId
pavleradojkovic 0:ba7e439238ab 760 # payload - list of topics
pavleradojkovic 0:ba7e439238ab 761 self.data = Data[:]
pavleradojkovic 0:ba7e439238ab 762 if buffer != None:
pavleradojkovic 0:ba7e439238ab 763 self.unpack(buffer)
pavleradojkovic 0:ba7e439238ab 764
pavleradojkovic 0:ba7e439238ab 765 def pack(self):
pavleradojkovic 0:ba7e439238ab 766 buffer = writeInt16(self.messageIdentifier)
pavleradojkovic 0:ba7e439238ab 767 for d in self.data:
pavleradojkovic 0:ba7e439238ab 768 buffer += writeUTF(d)
pavleradojkovic 0:ba7e439238ab 769 buffer = self.fh.pack(len(buffer)) + buffer
pavleradojkovic 0:ba7e439238ab 770 return buffer
pavleradojkovic 0:ba7e439238ab 771
pavleradojkovic 0:ba7e439238ab 772 def unpack(self, buffer):
pavleradojkovic 0:ba7e439238ab 773 assert len(buffer) >= 2
pavleradojkovic 0:ba7e439238ab 774 assert MessageType(buffer) == UNSUBSCRIBE
pavleradojkovic 0:ba7e439238ab 775 fhlen = self.fh.unpack(buffer)
pavleradojkovic 0:ba7e439238ab 776 assert len(buffer) >= fhlen + self.fh.remainingLength
pavleradojkovic 0:ba7e439238ab 777 logger.info("[MQTT-2.3.1-1] packet indentifier must be in unsubscribe")
pavleradojkovic 0:ba7e439238ab 778 self.messageIdentifier = readInt16(buffer[fhlen:])
pavleradojkovic 0:ba7e439238ab 779 assert self.messageIdentifier > 0, "[MQTT-2.3.1-1] packet indentifier must be > 0"
pavleradojkovic 0:ba7e439238ab 780 leftlen = self.fh.remainingLength - 2
pavleradojkovic 0:ba7e439238ab 781 self.data = []
pavleradojkovic 0:ba7e439238ab 782 while leftlen > 0:
pavleradojkovic 0:ba7e439238ab 783 topic = readUTF(buffer[-leftlen:], leftlen)
pavleradojkovic 0:ba7e439238ab 784 leftlen -= len(topic) + 2
pavleradojkovic 0:ba7e439238ab 785 self.data.append(topic)
pavleradojkovic 0:ba7e439238ab 786 assert leftlen == 0
pavleradojkovic 0:ba7e439238ab 787 assert self.fh.DUP == False, "[MQTT-2.1.2-1]"
pavleradojkovic 0:ba7e439238ab 788 assert self.fh.QoS == 1, "[MQTT-2.1.2-1]"
pavleradojkovic 0:ba7e439238ab 789 assert self.fh.RETAIN == False, "[MQTT-2.1.2-1]"
pavleradojkovic 0:ba7e439238ab 790 logger.info("[MQTT-3-10.1-1] fixed header bits are 0,0,1,0")
pavleradojkovic 0:ba7e439238ab 791 return fhlen + self.fh.remainingLength
pavleradojkovic 0:ba7e439238ab 792
pavleradojkovic 0:ba7e439238ab 793 def __repr__(self):
pavleradojkovic 0:ba7e439238ab 794 return repr(self.fh)+", MsgId="+repr(self.messageIdentifier)+\
pavleradojkovic 0:ba7e439238ab 795 ", Data="+repr(self.data)+")"
pavleradojkovic 0:ba7e439238ab 796
pavleradojkovic 0:ba7e439238ab 797 def __eq__(self, packet):
pavleradojkovic 0:ba7e439238ab 798 return Packets.__eq__(self, packet) and \
pavleradojkovic 0:ba7e439238ab 799 self.messageIdentifier == packet.messageIdentifier and \
pavleradojkovic 0:ba7e439238ab 800 self.data == packet.data
pavleradojkovic 0:ba7e439238ab 801
pavleradojkovic 0:ba7e439238ab 802
pavleradojkovic 0:ba7e439238ab 803 class Unsubacks(Packets):
pavleradojkovic 0:ba7e439238ab 804
pavleradojkovic 0:ba7e439238ab 805 def __init__(self, buffer=None, DUP=False, QoS=0, Retain=False, MsgId=0):
pavleradojkovic 0:ba7e439238ab 806 self.fh = FixedHeaders(UNSUBACK)
pavleradojkovic 0:ba7e439238ab 807 self.fh.DUP = DUP
pavleradojkovic 0:ba7e439238ab 808 self.fh.QoS = QoS
pavleradojkovic 0:ba7e439238ab 809 self.fh.Retain = Retain
pavleradojkovic 0:ba7e439238ab 810 # variable header
pavleradojkovic 0:ba7e439238ab 811 self.messageIdentifier = MsgId
pavleradojkovic 0:ba7e439238ab 812 if buffer != None:
pavleradojkovic 0:ba7e439238ab 813 self.unpack(buffer)
pavleradojkovic 0:ba7e439238ab 814
pavleradojkovic 0:ba7e439238ab 815 def pack(self):
pavleradojkovic 0:ba7e439238ab 816 buffer = writeInt16(self.messageIdentifier)
pavleradojkovic 0:ba7e439238ab 817 buffer = self.fh.pack(len(buffer)) + buffer
pavleradojkovic 0:ba7e439238ab 818 return buffer
pavleradojkovic 0:ba7e439238ab 819
pavleradojkovic 0:ba7e439238ab 820 def unpack(self, buffer):
pavleradojkovic 0:ba7e439238ab 821 assert len(buffer) >= 2
pavleradojkovic 0:ba7e439238ab 822 assert MessageType(buffer) == UNSUBACK
pavleradojkovic 0:ba7e439238ab 823 fhlen = self.fh.unpack(buffer)
pavleradojkovic 0:ba7e439238ab 824 assert len(buffer) >= fhlen + self.fh.remainingLength
pavleradojkovic 0:ba7e439238ab 825 self.messageIdentifier = readInt16(buffer[fhlen:])
pavleradojkovic 0:ba7e439238ab 826 assert self.messageIdentifier > 0, "[MQTT-2.3.1-1] packet indentifier must be > 0"
pavleradojkovic 0:ba7e439238ab 827 self.messageIdentifier = readInt16(buffer[fhlen:])
pavleradojkovic 0:ba7e439238ab 828 assert self.fh.DUP == False, "[MQTT-2.1.2-1]"
pavleradojkovic 0:ba7e439238ab 829 assert self.fh.QoS == 0, "[MQTT-2.1.2-1]"
pavleradojkovic 0:ba7e439238ab 830 assert self.fh.RETAIN == False, "[MQTT-2.1.2-1]"
pavleradojkovic 0:ba7e439238ab 831 return fhlen + self.fh.remainingLength
pavleradojkovic 0:ba7e439238ab 832
pavleradojkovic 0:ba7e439238ab 833 def __repr__(self):
pavleradojkovic 0:ba7e439238ab 834 return repr(self.fh)+", MsgId="+repr(self.messageIdentifier)+")"
pavleradojkovic 0:ba7e439238ab 835
pavleradojkovic 0:ba7e439238ab 836 def __eq__(self, packet):
pavleradojkovic 0:ba7e439238ab 837 return Packets.__eq__(self, packet) and \
pavleradojkovic 0:ba7e439238ab 838 self.messageIdentifier == packet.messageIdentifier
pavleradojkovic 0:ba7e439238ab 839
pavleradojkovic 0:ba7e439238ab 840
pavleradojkovic 0:ba7e439238ab 841 class Pingreqs(Packets):
pavleradojkovic 0:ba7e439238ab 842
pavleradojkovic 0:ba7e439238ab 843 def __init__(self, buffer=None, DUP=False, QoS=0, Retain=False):
pavleradojkovic 0:ba7e439238ab 844 self.fh = FixedHeaders(PINGREQ)
pavleradojkovic 0:ba7e439238ab 845 self.fh.DUP = DUP
pavleradojkovic 0:ba7e439238ab 846 self.fh.QoS = QoS
pavleradojkovic 0:ba7e439238ab 847 self.fh.Retain = Retain
pavleradojkovic 0:ba7e439238ab 848 if buffer != None:
pavleradojkovic 0:ba7e439238ab 849 self.unpack(buffer)
pavleradojkovic 0:ba7e439238ab 850
pavleradojkovic 0:ba7e439238ab 851 def unpack(self, buffer):
pavleradojkovic 0:ba7e439238ab 852 assert len(buffer) >= 2
pavleradojkovic 0:ba7e439238ab 853 assert MessageType(buffer) == PINGREQ
pavleradojkovic 0:ba7e439238ab 854 fhlen = self.fh.unpack(buffer)
pavleradojkovic 0:ba7e439238ab 855 assert self.fh.remainingLength == 0
pavleradojkovic 0:ba7e439238ab 856 assert self.fh.DUP == False, "[MQTT-2.1.2-1]"
pavleradojkovic 0:ba7e439238ab 857 assert self.fh.QoS == 0, "[MQTT-2.1.2-1]"
pavleradojkovic 0:ba7e439238ab 858 assert self.fh.RETAIN == False, "[MQTT-2.1.2-1]"
pavleradojkovic 0:ba7e439238ab 859 return fhlen
pavleradojkovic 0:ba7e439238ab 860
pavleradojkovic 0:ba7e439238ab 861 def __repr__(self):
pavleradojkovic 0:ba7e439238ab 862 return repr(self.fh)+")"
pavleradojkovic 0:ba7e439238ab 863
pavleradojkovic 0:ba7e439238ab 864
pavleradojkovic 0:ba7e439238ab 865 class Pingresps(Packets):
pavleradojkovic 0:ba7e439238ab 866
pavleradojkovic 0:ba7e439238ab 867 def __init__(self, buffer=None, DUP=False, QoS=0, Retain=False):
pavleradojkovic 0:ba7e439238ab 868 self.fh = FixedHeaders(PINGRESP)
pavleradojkovic 0:ba7e439238ab 869 self.fh.DUP = DUP
pavleradojkovic 0:ba7e439238ab 870 self.fh.QoS = QoS
pavleradojkovic 0:ba7e439238ab 871 self.fh.Retain = Retain
pavleradojkovic 0:ba7e439238ab 872 if buffer != None:
pavleradojkovic 0:ba7e439238ab 873 self.unpack(buffer)
pavleradojkovic 0:ba7e439238ab 874
pavleradojkovic 0:ba7e439238ab 875 def unpack(self, buffer):
pavleradojkovic 0:ba7e439238ab 876 assert len(buffer) >= 2
pavleradojkovic 0:ba7e439238ab 877 assert MessageType(buffer) == PINGRESP
pavleradojkovic 0:ba7e439238ab 878 fhlen = self.fh.unpack(buffer)
pavleradojkovic 0:ba7e439238ab 879 assert self.fh.remainingLength == 0
pavleradojkovic 0:ba7e439238ab 880 assert self.fh.DUP == False, "[MQTT-2.1.2-1]"
pavleradojkovic 0:ba7e439238ab 881 assert self.fh.QoS == 0, "[MQTT-2.1.2-1]"
pavleradojkovic 0:ba7e439238ab 882 assert self.fh.RETAIN == False, "[MQTT-2.1.2-1]"
pavleradojkovic 0:ba7e439238ab 883 return fhlen
pavleradojkovic 0:ba7e439238ab 884
pavleradojkovic 0:ba7e439238ab 885 def __repr__(self):
pavleradojkovic 0:ba7e439238ab 886 return repr(self.fh)+")"
pavleradojkovic 0:ba7e439238ab 887
pavleradojkovic 0:ba7e439238ab 888 classes = [None, Connects, Connacks, Publishes, Pubacks, Pubrecs,
pavleradojkovic 0:ba7e439238ab 889 Pubrels, Pubcomps, Subscribes, Subacks, Unsubscribes,
pavleradojkovic 0:ba7e439238ab 890 Unsubacks, Pingreqs, Pingresps, Disconnects]
pavleradojkovic 0:ba7e439238ab 891
pavleradojkovic 0:ba7e439238ab 892 def unpackPacket(buffer):
pavleradojkovic 0:ba7e439238ab 893 if MessageType(buffer) != None:
pavleradojkovic 0:ba7e439238ab 894 packet = classes[MessageType(buffer)]()
pavleradojkovic 0:ba7e439238ab 895 packet.unpack(buffer)
pavleradojkovic 0:ba7e439238ab 896 else:
pavleradojkovic 0:ba7e439238ab 897 packet = None
pavleradojkovic 0:ba7e439238ab 898 return packet
pavleradojkovic 0:ba7e439238ab 899
pavleradojkovic 0:ba7e439238ab 900 if __name__ == "__main__":
pavleradojkovic 0:ba7e439238ab 901 fh = FixedHeaders(CONNECT)
pavleradojkovic 0:ba7e439238ab 902 tests = [0, 56, 127, 128, 8888, 16383, 16384, 65535, 2097151, 2097152,
pavleradojkovic 0:ba7e439238ab 903 20555666, 268435454, 268435455]
pavleradojkovic 0:ba7e439238ab 904 for x in tests:
pavleradojkovic 0:ba7e439238ab 905 try:
pavleradojkovic 0:ba7e439238ab 906 assert x == fh.decode(fh.encode(x))[0]
pavleradojkovic 0:ba7e439238ab 907 except AssertionError:
pavleradojkovic 0:ba7e439238ab 908 print("Test failed for x =", x, fh.decode(fh.encode(x)))
pavleradojkovic 0:ba7e439238ab 909 try:
pavleradojkovic 0:ba7e439238ab 910 fh.decode(fh.encode(268435456))
pavleradojkovic 0:ba7e439238ab 911 print("Error")
pavleradojkovic 0:ba7e439238ab 912 except AssertionError:
pavleradojkovic 0:ba7e439238ab 913 pass
pavleradojkovic 0:ba7e439238ab 914
pavleradojkovic 0:ba7e439238ab 915 for packet in classes[1:]:
pavleradojkovic 0:ba7e439238ab 916 before = str(packet())
pavleradojkovic 0:ba7e439238ab 917 after = str(unpackPacket(packet().pack()))
pavleradojkovic 0:ba7e439238ab 918 try:
pavleradojkovic 0:ba7e439238ab 919 assert before == after
pavleradojkovic 0:ba7e439238ab 920 except:
pavleradojkovic 0:ba7e439238ab 921 print("before:", before, "\nafter:", after)
pavleradojkovic 0:ba7e439238ab 922 print("End")
pavleradojkovic 0:ba7e439238ab 923