def publish(self, sock, packet, callback):
     if packet.Flags.QoS == 0:
         if packet.Flags.TopicIdType == 2:
             topic = MQTTSN.writeInt16(packet.TopicId).decode()
             print("topic", topic)
         self.broker.publish(self.clients[sock].id, topic, packet.Data,
                             packet.Flags.QoS, packet.Flags.RETAIN)
     elif packet.fh.QoS == 1:
         if packet.fh.DUP:
             logger.info(
                 "[MQTT-3.3.1-3] Incoming publish DUP 1 ==> outgoing publish with DUP 0"
             )
             logger.info(
                 "[MQTT-4.3.2-2] server must store message in accordance with QoS 1"
             )
         self.broker.publish(self.clients[sock].id, packet.topicName,
                             packet.data, packet.fh.QoS, packet.fh.RETAIN)
         resp = MQTTSN.Pubacks()
         logger.info("[MQTT-2.3.1-6] puback messge id same as publish")
         resp.messageIdentifier = packet.messageIdentifier
         respond(sock, callback, resp)
     elif packet.fh.QoS == 2:
         myclient = self.clients[sock]
         if self.publish_on_pubrel:
             if packet.messageIdentifier in myclient.inbound.keys():
                 if packet.fh.DUP == 0:
                     logger.error(
                         "[MQTT-3.3.1-2] duplicate QoS 2 message id %d found with DUP 0",
                         packet.messageIdentifier)
                 else:
                     logger.info(
                         "[MQTT-3.3.1-2] DUP flag is 1 on redelivery")
             else:
                 myclient.inbound[packet.messageIdentifier] = packet
         else:
             if packet.messageIdentifier in myclient.inbound:
                 if packet.fh.DUP == 0:
                     logger.error(
                         "[MQTT-3.3.1-2] duplicate QoS 2 message id %d found with DUP 0",
                         packet.messageIdentifier)
                 else:
                     logger.info(
                         "[MQTT-3.3.1-2] DUP flag is 1 on redelivery")
             else:
                 myclient.inbound.append(packet.messageIdentifier)
                 logger.info(
                     "[MQTT-4.3.3-2] server must store message in accordance with QoS 2"
                 )
                 self.broker.publish(myclient, packet.topicName,
                                     packet.data, packet.fh.QoS,
                                     packet.fh.RETAIN)
         resp = MQTTSN.Pubrecs()
         logger.info("[MQTT-2.3.1-6] pubrec messge id same as publish")
         resp.messageIdentifier = packet.messageIdentifier
         respond(sock, callback, resp)
 def subscribe(self, sock, packet):
     topics = []
     qoss = []
     respqoss = []
     for p in packet.data:
         if p[0] == "test/nosubscribe":
             respqoss.append(0x80)
         else:
             if p[0] == "test/QoS 1 only":
                 respqoss.append(min(1), p[1])
             elif p[0] == "test/QoS 0 only":
                 respqoss.append(min(0), p[1])
             else:
                 respqoss.append(p[1])
             topics.append(p[0])
             qoss.append(respqoss[-1])
     if len(topics) > 0:
         self.broker.subscribe(self.clients[sock].id, topics, qoss)
     resp = MQTTSN.Subacks()
     logger.info(
         "[MQTT-2.3.1-7][MQTT-3.8.4-2] Suback has same message id as subscribe"
     )
     logger.info("[MQTT-3.8.4-1] Must respond with suback")
     resp.messageIdentifier = packet.messageIdentifier
     logger.info(
         "[MQTT-3.8.4-5] return code must be returned for each topic in subscribe"
     )
     logger.info(
         "[MQTT-3.9.3-1] the order of return codes must match order of topics in subscribe"
     )
     resp.data = respqoss
     respond(sock, resp)
 def pubrec(self, sock, packet):
     "confirmed reception of qos 2"
     myclient = self.clients[sock]
     if myclient.pubrec(packet.messageIdentifier):
         logger.info(
             "[MQTT-3.5.4-1] must reply with pubrel in response to pubrec")
         resp = MQTTSN.Pubrels()
         resp.messageIdentifier = packet.messageIdentifier
         respond(sock, resp)
 def handleRequest(self, raw_packet, client_address, callback):
     "this is going to be called from multiple threads, so synchronize"
     self.lock.acquire()
     terminate = False
     try:
         if raw_packet == None:
             # will message
             self.disconnect(sock, None, terminate=True)
             terminate = True
         else:
             packet = MQTTSN.unpackPacket(raw_packet)
             if packet:
                 terminate = self.handlePacket(packet, client_address,
                                               callback)
             else:
                 raise MQTTSN.MQTTSNException(
                     "[MQTT-2.0.0-1] handleRequest: badly formed MQTT packet"
                 )
     finally:
         self.lock.release()
     return terminate
 def pubrel(self, sock, packet):
     myclient = self.clients[sock]
     pub = myclient.pubrel(packet.messageIdentifier)
     if pub:
         if self.publish_on_pubrel:
             self.broker.publish(myclient.id, pub.topicName, pub.data,
                                 pub.fh.QoS, pub.fh.RETAIN)
             del myclient.inbound[packet.messageIdentifier]
         else:
             myclient.inbound.remove(packet.messageIdentifier)
     resp = MQTTSN.Pubcomps()
     logger.info("[MQTT-2.3.1-6] pubcomp messge id same as publish")
     resp.messageIdentifier = packet.messageIdentifier
     respond(sock, resp)
 def unsubscribe(self, sock, packet):
     self.broker.unsubscribe(self.clients[sock].id, packet.data)
     resp = MQTTSN.Unsubacks()
     logger.info(
         "[MQTT-2.3.1-7] Unsuback has same message id as unsubscribe")
     logger.info(
         "[MQTT-3.10.4-4] Unsuback must be sent - same message id as unsubscribe"
     )
     me = self.clients[sock]
     if len(me.outbound) > 0:
         logger.info(
             "[MQTT-3.10.4-3] sending unsuback has no effect on outward inflight messages"
         )
     resp.messageIdentifier = packet.messageIdentifier
     respond(sock, resp)
 def handlePacket(self, packet, sock, callback):
     terminate = False
     logger.info("in: " + str(packet))
     if sock not in self.clients.keys() and not isinstance(
             packet, MQTTSN.Connects):
         print(self.clients.keys(), sock)
         self.disconnect(sock, packet)
         raise MQTTSN.MQTTSNException(
             "[MQTT-3.1.0-1] Connect was not first packet on socket")
     else:
         getattr(self, MQTTSN.Messages.Names[packet.messageType].lower())(
             sock, packet, callback)
         if sock in self.clients.keys():
             self.clients[sock].lastPacket = time.time()
     if packet.messageType == MQTTSN.MessageTypes.DISCONNECT:
         terminate = True
     return terminate
 def publishArrived(self, topic, msg, qos, retained=False):
     pub = MQTTSN.Publishes()
     logger.info(
         "[MQTT-3.2.3-3] topic name must match the subscription's topic filter"
     )
     pub.topicName = topic
     pub.data = msg
     pub.fh.QoS = qos
     pub.fh.RETAIN = retained
     if retained:
         logger.info(
             "[MQTT-2.1.2-7] Last retained message on matching topics sent on subscribe"
         )
     if pub.fh.RETAIN:
         logger.info(
             "[MQTT-2.1.2-9] Set retained flag on retained messages")
     if qos == 2:
         pub.qos2state = "PUBREC"
     if qos in [1, 2]:
         pub.messageIdentifier = self.msgid
         logger.debug("client id: %d msgid: %d", self.id, self.msgid)
         if self.msgid == 65535:
             self.msgid = 1
         else:
             self.msgid += 1
         self.outbound.append(pub)
         self.outmsgs[pub.messageIdentifier] = pub
     logger.info(
         "[MQTT-4.6.0-6] publish packets must be sent in order of receipt from any given client"
     )
     if self.connected:
         respond(self.socket, pub)
     else:
         if qos == 0 and not self.broker.dropQoS0:
             self.outbound.append(pub)
         if qos in [1, 2]:
             logger.info(
                 "[MQTT-3.1.2-5] storing of QoS 1 and 2 messages for disconnected client %s",
                 self.id)
 def resend(self):
     logger.debug("resending unfinished publications %s",
                  str(self.outbound))
     if len(self.outbound) > 0:
         logger.info(
             "[MQTT-4.4.0-1] resending inflight QoS 1 and 2 messages")
     for pub in self.outbound:
         logger.debug("resending", pub)
         logger.info("[MQTT-4.4.0-2] dup flag must be set on in re-publish")
         if pub.fh.QoS == 0:
             respond(self.socket, pub)
         elif pub.fh.QoS == 1:
             pub.fh.DUP = 1
             logger.info(
                 "[MQTT-2.1.2-3] Dup when resending QoS 1 publish id %d",
                 pub.messageIdentifier)
             logger.info(
                 "[MQTT-2.3.1-4] Message id same as original publish on resend"
             )
             logger.info("[MQTT-4.3.2-1] Resending QoS 1 with DUP flag")
             respond(self.socket, pub)
         elif pub.fh.QoS == 2:
             if pub.qos2state == "PUBREC":
                 logger.info(
                     "[MQTT-2.1.2-3] Dup when resending QoS 2 publish id %d",
                     pub.messageIdentifier)
                 pub.fh.DUP = 1
                 logger.info(
                     "[MQTT-2.3.1-4] Message id same as original publish on resend"
                 )
                 logger.info("[MQTT-4.3.3-1] Resending QoS 2 with DUP flag")
                 respond(self.socket, pub)
             else:
                 resp = MQTTSN.Pubrels()
                 logger.info(
                     "[MQTT-2.3.1-4] Message id same as original publish on resend"
                 )
                 resp.messageIdentifier = pub.messageIdentifier
                 respond(self.socket, resp)
 def pingreq(self, sock, packet):
     resp = MQTTSN.Pingresps()
     logger.info("[MQTT-3.12.4-1] sending pingresp in response to pingreq")
     respond(sock, resp)
 def connect(self, sock, packet, callback):
     if packet.ProtocolId != 1:
         logger.error("[MQTT-3.1.2-2] Wrong protocol version %d",
                      packet.ProtocolVersion)
         resp = MQTTSN.Connacks()
         resp.ReturnCode = 1
         respond(sock, callback, resp)
         logger.info(
             "[MQTT-3.2.2-5] must close connection after non-zero connack")
         self.disconnect(sock, None)
         logger.info(
             "[MQTT-3.1.4-5] When rejecting connect, no more data must be processed"
         )
         return
     if sock in self.clients.keys():  # is socket is already connected?
         self.disconnect(sock, None)
         logger.info(
             "[MQTT-3.1.4-5] When rejecting connect, no more data must be processed"
         )
         raise MQTTSN.MQTTSNException(
             "[MQTT-3.1.0-2] Second connect packet")
     if len(packet.ClientId) == 0:
         if self.zero_length_clientids == False or packet.CleanSession == False:
             if self.zero_length_clientids:
                 logger.info(
                     "[MQTT-3.1.3-8] Reject 0-length clientid with cleansession false"
                 )
             logger.info(
                 "[MQTT-3.1.3-9] if clientid is rejected, must send connack 2 and close connection"
             )
             resp = MQTTSN.Connacks()
             resp.returnCode = 2
             respond(sock, callback, resp)
             logger.info(
                 "[MQTT-3.2.2-5] must close connection after non-zero connack"
             )
             self.disconnect(sock, None)
             logger.info(
                 "[MQTT-3.1.4-5] When rejecting connect, no more data must be processed"
             )
             return
         else:
             logger.info(
                 "[MQTT-3.1.3-7] 0-length clientid must have cleansession true"
             )
             packet.ClientId = uuid.uuid4(
             )  # give the client a unique clientid
             logger.info(
                 "[MQTT-3.1.3-6] 0-length clientid must be assigned a unique id %s",
                 packet.ClientId)
     logger.info(
         "[MQTT-3.1.3-5] Clientids of 1 to 23 chars and ascii alphanumeric must be allowed"
     )
     if packet.ClientId in [
             client.id for client in self.clients.values()
     ]:  # is this client already connected on a different socket?
         for s in self.clients.keys():
             if self.clients[s].id == packet.ClientId:
                 logger.info("[MQTT-3.1.4-2] Disconnecting old client %s",
                             packet.ClientId)
                 self.disconnect(s, None)
                 break
     me = None
     if not packet.Flags.CleanSession:
         me = self.broker.getClient(
             packet.ClientId)  # find existing state, if there is any
         if me:
             logger.info(
                 "[MQTT-3.1.3-2] clientid used to retrieve client state")
     resp = MQTTSN.Connacks()
     if me == None:
         me = MQTTSNClients(packet.ClientId, packet.Flags.CleanSession,
                            packet.Duration, sock, self)
     else:
         me.socket = sock  # set existing client state to new socket
         me.cleansession = packet.Flags.CleanSession
         me.keepalive = packet.Duration
     logger.info(
         "[MQTT-4.1.0-1] server must store data for at least as long as the network connection lasts"
     )
     self.clients[sock] = me
     #me.will = (packet.WillTopic, packet.WillQoS, packet.WillMessage, packet.WillRETAIN) if packet.WillFlag else None
     self.broker.connect(me)
     logger.info(
         "[MQTT-3.2.0-1] the first response to a client must be a connack")
     resp.ReturnCode = 0
     respond(sock, callback, resp)
     me.resend()