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


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