2014-06-26 22:12:55 +00:00
|
|
|
import errno
|
|
|
|
import os
|
2014-05-07 22:27:00 +00:00
|
|
|
import socket
|
2014-06-26 22:12:55 +00:00
|
|
|
import subprocess
|
2014-05-07 22:27:00 +00:00
|
|
|
import struct
|
2018-04-13 21:02:53 +00:00
|
|
|
import sys
|
2014-06-26 22:12:55 +00:00
|
|
|
import time
|
|
|
|
|
2018-04-13 21:02:53 +00:00
|
|
|
def start_broker(filename, cmd=None, port=0, use_conf=False):
|
2014-06-26 22:12:55 +00:00
|
|
|
delay = 0.1
|
2018-04-13 21:02:53 +00:00
|
|
|
|
|
|
|
if use_conf == True:
|
2014-06-26 22:12:55 +00:00
|
|
|
cmd = ['../../src/mosquitto', '-v', '-c', filename.replace('.py', '.conf')]
|
2018-04-13 21:02:53 +00:00
|
|
|
|
|
|
|
if port == 0:
|
|
|
|
port = 1888
|
|
|
|
else:
|
|
|
|
if cmd is None and port != 0:
|
|
|
|
cmd = ['../../src/mosquitto', '-v', '-p', str(port)]
|
|
|
|
elif cmd is None and port == 0:
|
|
|
|
port = 1888
|
|
|
|
cmd = ['../../src/mosquitto', '-v', '-c', filename.replace('.py', '.conf')]
|
|
|
|
elif cmd is not None and port == 0:
|
|
|
|
port = 1888
|
|
|
|
|
2014-06-26 22:12:55 +00:00
|
|
|
if os.environ.get('MOSQ_USE_VALGRIND') is not None:
|
2016-07-19 14:05:53 +00:00
|
|
|
cmd = ['valgrind', '--trace-children=yes', '--leak-check=full', '--show-leak-kinds=all', '--log-file='+filename+'.vglog'] + cmd
|
2014-06-30 21:55:56 +00:00
|
|
|
delay = 1
|
2014-06-26 22:12:55 +00:00
|
|
|
|
2018-04-15 22:25:04 +00:00
|
|
|
#print(port)
|
|
|
|
#print(cmd)
|
2014-06-26 22:12:55 +00:00
|
|
|
broker = subprocess.Popen(cmd, stderr=subprocess.PIPE)
|
|
|
|
for i in range(0, 20):
|
|
|
|
time.sleep(delay)
|
|
|
|
c = None
|
|
|
|
try:
|
|
|
|
c = socket.create_connection(("localhost", port))
|
|
|
|
except socket.error as err:
|
|
|
|
if err.errno != errno.ECONNREFUSED:
|
|
|
|
raise
|
|
|
|
|
|
|
|
if c is not None:
|
|
|
|
c.close()
|
2014-07-03 16:37:31 +00:00
|
|
|
time.sleep(delay)
|
2014-06-26 22:12:55 +00:00
|
|
|
return broker
|
|
|
|
raise IOError
|
2014-05-07 22:27:00 +00:00
|
|
|
|
2018-04-16 09:02:22 +00:00
|
|
|
def start_client(filename, cmd, env, port=1888):
|
2014-07-01 21:02:06 +00:00
|
|
|
if cmd is None:
|
|
|
|
raise ValueError
|
|
|
|
if os.environ.get('MOSQ_USE_VALGRIND') is not None:
|
|
|
|
cmd = ['valgrind', '-q', '--log-file='+filename+'.vglog'] + cmd
|
|
|
|
|
2018-04-16 09:02:22 +00:00
|
|
|
cmd = cmd + [str(port)]
|
2014-07-01 21:02:06 +00:00
|
|
|
return subprocess.Popen(cmd, env=env)
|
|
|
|
|
2018-08-01 18:26:12 +00:00
|
|
|
|
2014-05-07 22:27:00 +00:00
|
|
|
def expect_packet(sock, name, expected):
|
|
|
|
if len(expected) > 0:
|
|
|
|
rlen = len(expected)
|
|
|
|
else:
|
|
|
|
rlen = 1
|
|
|
|
|
|
|
|
packet_recvd = sock.recv(rlen)
|
|
|
|
return packet_matches(name, packet_recvd, expected)
|
|
|
|
|
2018-08-01 18:26:12 +00:00
|
|
|
|
2014-05-07 22:27:00 +00:00
|
|
|
def packet_matches(name, recvd, expected):
|
|
|
|
if recvd != expected:
|
|
|
|
print("FAIL: Received incorrect "+name+".")
|
|
|
|
try:
|
|
|
|
print("Received: "+to_string(recvd))
|
|
|
|
except struct.error:
|
2018-04-13 11:30:41 +00:00
|
|
|
print("Received (not decoded, len=%d): %s" % (len(recvd), recvd))
|
2018-10-25 13:43:43 +00:00
|
|
|
for i in range(0, len(recvd)):
|
|
|
|
print('%c'%(recvd[i]),)
|
2014-05-07 22:27:00 +00:00
|
|
|
try:
|
|
|
|
print("Expected: "+to_string(expected))
|
|
|
|
except struct.error:
|
2018-04-13 11:30:41 +00:00
|
|
|
print("Expected (not decoded, len=%d): %s" % (len(expected), expected))
|
2018-11-09 22:23:11 +00:00
|
|
|
for i in range(0, len(expected)):
|
|
|
|
print('%c'%(expected[i]),)
|
2014-05-07 22:27:00 +00:00
|
|
|
|
|
|
|
return 0
|
|
|
|
else:
|
|
|
|
return 1
|
|
|
|
|
|
|
|
|
2018-08-01 18:26:12 +00:00
|
|
|
def do_send_receive(sock, send_packet, receive_packet, error_string="send receive error"):
|
|
|
|
sock.send(send_packet)
|
|
|
|
|
|
|
|
if expect_packet(sock, error_string, receive_packet):
|
2014-05-07 22:27:00 +00:00
|
|
|
return sock
|
|
|
|
else:
|
|
|
|
sock.close()
|
|
|
|
raise ValueError
|
|
|
|
|
2018-08-01 18:26:12 +00:00
|
|
|
|
|
|
|
def do_client_connect(connect_packet, connack_packet, hostname="localhost", port=1888, timeout=60, connack_error="connack"):
|
|
|
|
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
|
|
sock.settimeout(timeout)
|
|
|
|
sock.connect((hostname, port))
|
|
|
|
|
|
|
|
return do_send_receive(sock, connect_packet, connack_packet, connack_error)
|
|
|
|
|
|
|
|
|
2014-05-07 22:27:00 +00:00
|
|
|
def remaining_length(packet):
|
|
|
|
l = min(5, len(packet))
|
|
|
|
all_bytes = struct.unpack("!"+"B"*l, packet[:l])
|
|
|
|
mult = 1
|
|
|
|
rl = 0
|
|
|
|
for i in range(1,l-1):
|
|
|
|
byte = all_bytes[i]
|
|
|
|
|
|
|
|
rl += (byte & 127) * mult
|
|
|
|
mult *= 128
|
|
|
|
if byte & 128 == 0:
|
|
|
|
packet = packet[i+1:]
|
|
|
|
break
|
|
|
|
|
|
|
|
return (packet, rl)
|
|
|
|
|
|
|
|
|
2017-06-27 10:11:43 +00:00
|
|
|
def to_hex_string(packet):
|
|
|
|
if len(packet) == 0:
|
|
|
|
return ""
|
|
|
|
|
|
|
|
s = ""
|
|
|
|
while len(packet) > 0:
|
|
|
|
packet0 = struct.unpack("!B", packet[0])
|
|
|
|
s = s+hex(packet0[0]) + " "
|
|
|
|
packet = packet[1:]
|
|
|
|
|
|
|
|
return s
|
|
|
|
|
|
|
|
|
2014-05-07 22:27:00 +00:00
|
|
|
def to_string(packet):
|
|
|
|
if len(packet) == 0:
|
|
|
|
return ""
|
|
|
|
|
|
|
|
packet0 = struct.unpack("!B", packet[0])
|
|
|
|
packet0 = packet0[0]
|
|
|
|
cmd = packet0 & 0xF0
|
|
|
|
if cmd == 0x00:
|
|
|
|
# Reserved
|
|
|
|
return "0x00"
|
|
|
|
elif cmd == 0x10:
|
|
|
|
# CONNECT
|
|
|
|
(packet, rl) = remaining_length(packet)
|
|
|
|
pack_format = "!H" + str(len(packet)-2) + 's'
|
|
|
|
(slen, packet) = struct.unpack(pack_format, packet)
|
|
|
|
pack_format = "!" + str(slen)+'sBBH' + str(len(packet)-slen-4) + 's'
|
|
|
|
(protocol, proto_ver, flags, keepalive, packet) = struct.unpack(pack_format, packet)
|
|
|
|
s = "CONNECT, proto="+protocol+str(proto_ver)+", keepalive="+str(keepalive)
|
|
|
|
if flags&2:
|
|
|
|
s = s+", clean-session"
|
|
|
|
else:
|
|
|
|
s = s+", durable"
|
|
|
|
|
|
|
|
pack_format = "!H" + str(len(packet)-2) + 's'
|
|
|
|
(slen, packet) = struct.unpack(pack_format, packet)
|
|
|
|
pack_format = "!" + str(slen)+'s' + str(len(packet)-slen) + 's'
|
|
|
|
(client_id, packet) = struct.unpack(pack_format, packet)
|
|
|
|
s = s+", id="+client_id
|
|
|
|
|
|
|
|
if flags&4:
|
|
|
|
pack_format = "!H" + str(len(packet)-2) + 's'
|
|
|
|
(slen, packet) = struct.unpack(pack_format, packet)
|
|
|
|
pack_format = "!" + str(slen)+'s' + str(len(packet)-slen) + 's'
|
|
|
|
(will_topic, packet) = struct.unpack(pack_format, packet)
|
|
|
|
s = s+", will-topic="+will_topic
|
|
|
|
|
|
|
|
pack_format = "!H" + str(len(packet)-2) + 's'
|
|
|
|
(slen, packet) = struct.unpack(pack_format, packet)
|
|
|
|
pack_format = "!" + str(slen)+'s' + str(len(packet)-slen) + 's'
|
|
|
|
(will_message, packet) = struct.unpack(pack_format, packet)
|
|
|
|
s = s+", will-message="+will_message
|
|
|
|
|
|
|
|
s = s+", will-qos="+str((flags&24)>>3)
|
|
|
|
s = s+", will-retain="+str((flags&32)>>5)
|
|
|
|
|
|
|
|
if flags&128:
|
|
|
|
pack_format = "!H" + str(len(packet)-2) + 's'
|
|
|
|
(slen, packet) = struct.unpack(pack_format, packet)
|
|
|
|
pack_format = "!" + str(slen)+'s' + str(len(packet)-slen) + 's'
|
|
|
|
(username, packet) = struct.unpack(pack_format, packet)
|
|
|
|
s = s+", username="+username
|
|
|
|
|
|
|
|
if flags&64:
|
|
|
|
pack_format = "!H" + str(len(packet)-2) + 's'
|
|
|
|
(slen, packet) = struct.unpack(pack_format, packet)
|
|
|
|
pack_format = "!" + str(slen)+'s' + str(len(packet)-slen) + 's'
|
|
|
|
(password, packet) = struct.unpack(pack_format, packet)
|
|
|
|
s = s+", password="+password
|
|
|
|
|
2017-06-27 10:11:43 +00:00
|
|
|
if flags&1:
|
|
|
|
s = s+", reserved=1"
|
|
|
|
|
2014-05-07 22:27:00 +00:00
|
|
|
return s
|
|
|
|
elif cmd == 0x20:
|
|
|
|
# CONNACK
|
|
|
|
(cmd, rl, resv, rc) = struct.unpack('!BBBB', packet)
|
|
|
|
return "CONNACK, rl="+str(rl)+", res="+str(resv)+", rc="+str(rc)
|
|
|
|
elif cmd == 0x30:
|
|
|
|
# PUBLISH
|
|
|
|
dup = (packet0 & 0x08)>>3
|
|
|
|
qos = (packet0 & 0x06)>>1
|
|
|
|
retain = (packet0 & 0x01)
|
|
|
|
(packet, rl) = remaining_length(packet)
|
|
|
|
pack_format = "!H" + str(len(packet)-2) + 's'
|
|
|
|
(tlen, packet) = struct.unpack(pack_format, packet)
|
|
|
|
pack_format = "!" + str(tlen)+'s' + str(len(packet)-tlen) + 's'
|
|
|
|
(topic, packet) = struct.unpack(pack_format, packet)
|
|
|
|
s = "PUBLISH, rl="+str(rl)+", topic="+topic+", qos="+str(qos)+", retain="+str(retain)+", dup="+str(dup)
|
|
|
|
if qos > 0:
|
|
|
|
pack_format = "!H" + str(len(packet)-2) + 's'
|
|
|
|
(mid, packet) = struct.unpack(pack_format, packet)
|
|
|
|
s = s + ", mid="+str(mid)
|
|
|
|
|
|
|
|
s = s + ", payload="+packet
|
|
|
|
return s
|
|
|
|
elif cmd == 0x40:
|
|
|
|
# PUBACK
|
|
|
|
(cmd, rl, mid) = struct.unpack('!BBH', packet)
|
|
|
|
return "PUBACK, rl="+str(rl)+", mid="+str(mid)
|
|
|
|
elif cmd == 0x50:
|
|
|
|
# PUBREC
|
|
|
|
(cmd, rl, mid) = struct.unpack('!BBH', packet)
|
|
|
|
return "PUBREC, rl="+str(rl)+", mid="+str(mid)
|
|
|
|
elif cmd == 0x60:
|
|
|
|
# PUBREL
|
|
|
|
dup = (packet0 & 0x08)>>3
|
|
|
|
(cmd, rl, mid) = struct.unpack('!BBH', packet)
|
|
|
|
return "PUBREL, rl="+str(rl)+", mid="+str(mid)+", dup="+str(dup)
|
|
|
|
elif cmd == 0x70:
|
|
|
|
# PUBCOMP
|
|
|
|
(cmd, rl, mid) = struct.unpack('!BBH', packet)
|
|
|
|
return "PUBCOMP, rl="+str(rl)+", mid="+str(mid)
|
|
|
|
elif cmd == 0x80:
|
|
|
|
# SUBSCRIBE
|
|
|
|
(packet, rl) = remaining_length(packet)
|
|
|
|
pack_format = "!H" + str(len(packet)-2) + 's'
|
|
|
|
(mid, packet) = struct.unpack(pack_format, packet)
|
|
|
|
s = "SUBSCRIBE, rl="+str(rl)+", mid="+str(mid)
|
|
|
|
topic_index = 0
|
|
|
|
while len(packet) > 0:
|
|
|
|
pack_format = "!H" + str(len(packet)-2) + 's'
|
|
|
|
(tlen, packet) = struct.unpack(pack_format, packet)
|
|
|
|
pack_format = "!" + str(tlen)+'sB' + str(len(packet)-tlen-1) + 's'
|
|
|
|
(topic, qos, packet) = struct.unpack(pack_format, packet)
|
|
|
|
s = s + ", topic"+str(topic_index)+"="+topic+","+str(qos)
|
|
|
|
return s
|
|
|
|
elif cmd == 0x90:
|
|
|
|
# SUBACK
|
|
|
|
(packet, rl) = remaining_length(packet)
|
|
|
|
pack_format = "!H" + str(len(packet)-2) + 's'
|
|
|
|
(mid, packet) = struct.unpack(pack_format, packet)
|
|
|
|
pack_format = "!" + "B"*len(packet)
|
|
|
|
granted_qos = struct.unpack(pack_format, packet)
|
2016-04-09 21:18:11 +00:00
|
|
|
|
2014-05-07 22:27:00 +00:00
|
|
|
s = "SUBACK, rl="+str(rl)+", mid="+str(mid)+", granted_qos="+str(granted_qos[0])
|
|
|
|
for i in range(1, len(granted_qos)-1):
|
|
|
|
s = s+", "+str(granted_qos[i])
|
|
|
|
return s
|
|
|
|
elif cmd == 0xA0:
|
|
|
|
# UNSUBSCRIBE
|
|
|
|
(packet, rl) = remaining_length(packet)
|
|
|
|
pack_format = "!H" + str(len(packet)-2) + 's'
|
|
|
|
(mid, packet) = struct.unpack(pack_format, packet)
|
|
|
|
s = "UNSUBSCRIBE, rl="+str(rl)+", mid="+str(mid)
|
|
|
|
topic_index = 0
|
|
|
|
while len(packet) > 0:
|
|
|
|
pack_format = "!H" + str(len(packet)-2) + 's'
|
|
|
|
(tlen, packet) = struct.unpack(pack_format, packet)
|
|
|
|
pack_format = "!" + str(tlen)+'s' + str(len(packet)-tlen) + 's'
|
|
|
|
(topic, packet) = struct.unpack(pack_format, packet)
|
|
|
|
s = s + ", topic"+str(topic_index)+"="+topic
|
|
|
|
return s
|
|
|
|
elif cmd == 0xB0:
|
|
|
|
# UNSUBACK
|
|
|
|
(cmd, rl, mid) = struct.unpack('!BBH', packet)
|
|
|
|
return "UNSUBACK, rl="+str(rl)+", mid="+str(mid)
|
|
|
|
elif cmd == 0xC0:
|
|
|
|
# PINGREQ
|
|
|
|
(cmd, rl) = struct.unpack('!BB', packet)
|
|
|
|
return "PINGREQ, rl="+str(rl)
|
|
|
|
elif cmd == 0xD0:
|
|
|
|
# PINGRESP
|
|
|
|
(cmd, rl) = struct.unpack('!BB', packet)
|
|
|
|
return "PINGRESP, rl="+str(rl)
|
|
|
|
elif cmd == 0xE0:
|
|
|
|
# DISCONNECT
|
|
|
|
(cmd, rl) = struct.unpack('!BB', packet)
|
|
|
|
return "DISCONNECT, rl="+str(rl)
|
|
|
|
elif cmd == 0xF0:
|
|
|
|
# Reserved
|
|
|
|
return "0xF0"
|
|
|
|
|
2018-10-25 13:43:43 +00:00
|
|
|
def gen_connect(client_id, clean_session=True, keepalive=60, username=None, password=None, will_topic=None, will_qos=0, will_retain=False, will_payload="", proto_ver=4, connect_reserved=False, properties=None):
|
2014-05-07 22:27:00 +00:00
|
|
|
if (proto_ver&0x7F) == 3 or proto_ver == 0:
|
|
|
|
remaining_length = 12
|
2018-10-25 13:43:43 +00:00
|
|
|
elif (proto_ver&0x7F) == 4 or proto_ver == 5:
|
2014-05-07 22:27:00 +00:00
|
|
|
remaining_length = 10
|
|
|
|
else:
|
|
|
|
raise ValueError
|
|
|
|
|
|
|
|
if client_id != None:
|
|
|
|
remaining_length = remaining_length + 2+len(client_id)
|
|
|
|
|
|
|
|
connect_flags = 0
|
2017-06-27 10:11:43 +00:00
|
|
|
|
|
|
|
if connect_reserved:
|
|
|
|
connect_flags = connect_flags | 0x01
|
|
|
|
|
2014-05-07 22:27:00 +00:00
|
|
|
if clean_session:
|
|
|
|
connect_flags = connect_flags | 0x02
|
|
|
|
|
2018-10-25 13:43:43 +00:00
|
|
|
if proto_ver == 5:
|
|
|
|
remaining_length += 1
|
|
|
|
|
2014-05-07 22:27:00 +00:00
|
|
|
if will_topic != None:
|
|
|
|
remaining_length = remaining_length + 2+len(will_topic) + 2+len(will_payload)
|
|
|
|
connect_flags = connect_flags | 0x04 | ((will_qos&0x03) << 3)
|
|
|
|
if will_retain:
|
|
|
|
connect_flags = connect_flags | 32
|
|
|
|
|
|
|
|
if username != None:
|
|
|
|
remaining_length = remaining_length + 2+len(username)
|
|
|
|
connect_flags = connect_flags | 0x80
|
|
|
|
if password != None:
|
|
|
|
connect_flags = connect_flags | 0x40
|
|
|
|
remaining_length = remaining_length + 2+len(password)
|
|
|
|
|
|
|
|
rl = pack_remaining_length(remaining_length)
|
|
|
|
packet = struct.pack("!B"+str(len(rl))+"s", 0x10, rl)
|
|
|
|
if (proto_ver&0x7F) == 3 or proto_ver == 0:
|
|
|
|
packet = packet + struct.pack("!H6sBBH", len("MQIsdp"), "MQIsdp", proto_ver, connect_flags, keepalive)
|
2018-10-25 13:43:43 +00:00
|
|
|
elif (proto_ver&0x7F) == 4 or proto_ver == 5:
|
2014-05-07 22:27:00 +00:00
|
|
|
packet = packet + struct.pack("!H4sBBH", len("MQTT"), "MQTT", proto_ver, connect_flags, keepalive)
|
|
|
|
|
2018-10-25 13:43:43 +00:00
|
|
|
if proto_ver == 5:
|
|
|
|
packet += struct.pack("B", 0)
|
|
|
|
|
2014-05-07 22:27:00 +00:00
|
|
|
if client_id != None:
|
|
|
|
packet = packet + struct.pack("!H"+str(len(client_id))+"s", len(client_id), client_id)
|
|
|
|
|
|
|
|
if will_topic != None:
|
|
|
|
packet = packet + struct.pack("!H"+str(len(will_topic))+"s", len(will_topic), will_topic)
|
|
|
|
if len(will_payload) > 0:
|
|
|
|
packet = packet + struct.pack("!H"+str(len(will_payload))+"s", len(will_payload), will_payload)
|
|
|
|
else:
|
|
|
|
packet = packet + struct.pack("!H", 0)
|
|
|
|
|
|
|
|
if username != None:
|
|
|
|
packet = packet + struct.pack("!H"+str(len(username))+"s", len(username), username)
|
|
|
|
if password != None:
|
|
|
|
packet = packet + struct.pack("!H"+str(len(password))+"s", len(password), password)
|
|
|
|
return packet
|
|
|
|
|
2018-10-25 13:43:43 +00:00
|
|
|
def gen_connack(resv=0, rc=0, proto_ver=4):
|
|
|
|
if proto_ver == 5:
|
|
|
|
packet = struct.pack('!BBBBB', 32, 3, resv, rc, 0);
|
|
|
|
else:
|
|
|
|
packet = struct.pack('!BBBB', 32, 2, resv, rc);
|
|
|
|
|
|
|
|
return packet
|
2014-05-07 22:27:00 +00:00
|
|
|
|
2018-10-25 15:35:24 +00:00
|
|
|
def gen_publish(topic, qos, payload=None, retain=False, dup=False, mid=0, proto_ver=4, properties=None):
|
2014-05-07 22:27:00 +00:00
|
|
|
rl = 2+len(topic)
|
2016-06-23 17:33:19 +00:00
|
|
|
pack_format = "H"+str(len(topic))+"s"
|
2014-05-07 22:27:00 +00:00
|
|
|
if qos > 0:
|
|
|
|
rl = rl + 2
|
|
|
|
pack_format = pack_format + "H"
|
2018-10-25 15:35:24 +00:00
|
|
|
|
2018-10-25 13:57:41 +00:00
|
|
|
if proto_ver == 5:
|
2018-10-31 12:38:39 +00:00
|
|
|
if properties is None:
|
|
|
|
properties = struct.pack("!B", 0)
|
|
|
|
|
2018-10-25 15:35:24 +00:00
|
|
|
rl += len(properties)
|
|
|
|
# This will break if len(properties) > 127
|
|
|
|
pack_format = pack_format + "%ds"%(len(properties))
|
2018-10-25 13:57:41 +00:00
|
|
|
|
2014-05-07 22:27:00 +00:00
|
|
|
if payload != None:
|
|
|
|
rl = rl + len(payload)
|
|
|
|
pack_format = pack_format + str(len(payload))+"s"
|
|
|
|
else:
|
|
|
|
payload = ""
|
|
|
|
pack_format = pack_format + "0s"
|
|
|
|
|
2016-06-23 17:33:19 +00:00
|
|
|
rlpacked = pack_remaining_length(rl)
|
2014-05-07 22:27:00 +00:00
|
|
|
cmd = 48 | (qos<<1)
|
|
|
|
if retain:
|
|
|
|
cmd = cmd + 1
|
|
|
|
if dup:
|
|
|
|
cmd = cmd + 8
|
|
|
|
|
2018-10-25 13:57:41 +00:00
|
|
|
if proto_ver == 5:
|
|
|
|
if qos > 0:
|
2018-10-25 15:35:24 +00:00
|
|
|
return struct.pack("!B" + str(len(rlpacked))+"s" + pack_format, cmd, rlpacked, len(topic), topic, mid, properties, payload)
|
2018-10-25 13:57:41 +00:00
|
|
|
else:
|
2018-10-25 15:35:24 +00:00
|
|
|
return struct.pack("!B" + str(len(rlpacked))+"s" + pack_format, cmd, rlpacked, len(topic), topic, properties, payload)
|
2014-05-07 22:27:00 +00:00
|
|
|
else:
|
2018-10-25 13:57:41 +00:00
|
|
|
if qos > 0:
|
|
|
|
return struct.pack("!B" + str(len(rlpacked))+"s" + pack_format, cmd, rlpacked, len(topic), topic, mid, payload)
|
|
|
|
else:
|
|
|
|
return struct.pack("!B" + str(len(rlpacked))+"s" + pack_format, cmd, rlpacked, len(topic), topic, payload)
|
2014-05-07 22:27:00 +00:00
|
|
|
|
2018-10-31 12:38:39 +00:00
|
|
|
def _gen_command_with_mid(cmd, mid, proto_ver=4, reason_code=0):
|
2018-10-25 13:57:41 +00:00
|
|
|
if proto_ver == 5:
|
2018-10-31 12:38:39 +00:00
|
|
|
return struct.pack('!BBHBB', cmd, 4, mid, reason_code, 0)
|
2018-10-25 13:57:41 +00:00
|
|
|
else:
|
2018-10-31 12:38:39 +00:00
|
|
|
return struct.pack('!BBH', cmd, 2, mid)
|
2014-05-07 22:27:00 +00:00
|
|
|
|
2018-10-31 12:38:39 +00:00
|
|
|
def gen_puback(mid, proto_ver=4, reason_code=0):
|
|
|
|
return _gen_command_with_mid(64, mid, proto_ver, reason_code)
|
|
|
|
|
|
|
|
def gen_pubrec(mid, proto_ver=4, reason_code=0):
|
|
|
|
return _gen_command_with_mid(80, mid, proto_ver, reason_code)
|
2014-05-07 22:27:00 +00:00
|
|
|
|
2018-10-31 12:38:39 +00:00
|
|
|
def gen_pubrel(mid, dup=False, proto_ver=4, reason_code=0):
|
2014-05-07 22:27:00 +00:00
|
|
|
if dup:
|
|
|
|
cmd = 96+8+2
|
|
|
|
else:
|
|
|
|
cmd = 96+2
|
2018-10-31 12:38:39 +00:00
|
|
|
return _gen_command_with_mid(cmd, mid, proto_ver, reason_code)
|
2014-05-07 22:27:00 +00:00
|
|
|
|
2018-10-31 12:38:39 +00:00
|
|
|
def gen_pubcomp(mid, proto_ver=4, reason_code=0):
|
|
|
|
return _gen_command_with_mid(112, mid, proto_ver, reason_code)
|
2014-05-07 22:27:00 +00:00
|
|
|
|
2018-10-25 13:57:41 +00:00
|
|
|
def gen_subscribe(mid, topic, qos, proto_ver=4):
|
|
|
|
if proto_ver == 5:
|
|
|
|
pack_format = "!BBHBH"+str(len(topic))+"sB"
|
|
|
|
return struct.pack(pack_format, 130, 2+1+2+len(topic)+1, mid, 0, len(topic), topic, qos)
|
|
|
|
else:
|
|
|
|
pack_format = "!BBHH"+str(len(topic))+"sB"
|
|
|
|
return struct.pack(pack_format, 130, 2+2+len(topic)+1, mid, len(topic), topic, qos)
|
2014-05-07 22:27:00 +00:00
|
|
|
|
2018-10-25 13:57:41 +00:00
|
|
|
def gen_suback(mid, qos, proto_ver=4):
|
|
|
|
if proto_ver == 5:
|
|
|
|
return struct.pack('!BBHBB', 144, 2+1+1, mid, 0, qos)
|
|
|
|
else:
|
|
|
|
return struct.pack('!BBHB', 144, 2+1, mid, qos)
|
2014-05-07 22:27:00 +00:00
|
|
|
|
2018-10-25 13:57:41 +00:00
|
|
|
def gen_unsubscribe(mid, topic, proto_ver=4):
|
|
|
|
if proto_ver == 5:
|
|
|
|
pack_format = "!BBHBH"+str(len(topic))+"s"
|
|
|
|
return struct.pack(pack_format, 162, 2+2+len(topic)+1, mid, 0, len(topic), topic)
|
|
|
|
else:
|
|
|
|
pack_format = "!BBHH"+str(len(topic))+"s"
|
|
|
|
return struct.pack(pack_format, 162, 2+2+len(topic), mid, len(topic), topic)
|
2014-05-07 22:27:00 +00:00
|
|
|
|
2018-10-25 13:57:41 +00:00
|
|
|
def gen_unsuback(mid, proto_ver=4):
|
|
|
|
if proto_ver == 5:
|
|
|
|
return struct.pack('!BBHB', 176, 3, mid, 0)
|
|
|
|
else:
|
|
|
|
return struct.pack('!BBH', 176, 2, mid)
|
2014-05-07 22:27:00 +00:00
|
|
|
|
|
|
|
def gen_pingreq():
|
|
|
|
return struct.pack('!BB', 192, 0)
|
|
|
|
|
|
|
|
def gen_pingresp():
|
|
|
|
return struct.pack('!BB', 208, 0)
|
|
|
|
|
2018-11-09 22:23:11 +00:00
|
|
|
def gen_disconnect(proto_ver=4):
|
|
|
|
if proto_ver == 5:
|
|
|
|
return struct.pack('!BBBB', 224, 2, 0, 0)
|
|
|
|
else:
|
|
|
|
return struct.pack('!BB', 224, 0)
|
2014-05-07 22:27:00 +00:00
|
|
|
|
|
|
|
def pack_remaining_length(remaining_length):
|
|
|
|
s = ""
|
|
|
|
while True:
|
|
|
|
byte = remaining_length % 128
|
|
|
|
remaining_length = remaining_length // 128
|
|
|
|
# If there are more digits to encode, set the top bit of this digit
|
|
|
|
if remaining_length > 0:
|
|
|
|
byte = byte | 0x80
|
|
|
|
|
|
|
|
s = s + struct.pack("!B", byte)
|
|
|
|
if remaining_length == 0:
|
|
|
|
return s
|
2018-04-13 21:02:53 +00:00
|
|
|
|
|
|
|
|
2018-04-15 22:25:04 +00:00
|
|
|
def get_port(count=1):
|
|
|
|
if count == 1:
|
|
|
|
if len(sys.argv) == 2:
|
|
|
|
return int(sys.argv[1])
|
|
|
|
else:
|
|
|
|
return 1888
|
2018-04-13 21:02:53 +00:00
|
|
|
else:
|
2018-04-15 22:25:04 +00:00
|
|
|
if len(sys.argv) == 1+count:
|
|
|
|
p = ()
|
|
|
|
for i in range(0, count):
|
|
|
|
p = p + (int(sys.argv[1+i]),)
|
|
|
|
return p
|
|
|
|
else:
|
|
|
|
return tuple(range(1888, 1888+count))
|
2018-04-16 09:02:22 +00:00
|
|
|
|
|
|
|
|
|
|
|
def get_lib_port():
|
|
|
|
if len(sys.argv) == 3:
|
|
|
|
return int(sys.argv[2])
|
|
|
|
else:
|
|
|
|
return 1888
|