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


plotjuggler
Author(s): Davide Faconti
autogenerated on Sun Dec 6 2020 03:48:09