def _reader_coro(self): self.logger.debug("Starting reader coro") while self._running: try: self._reader_ready.set() fixed_header = yield from asyncio.wait_for(MQTTFixedHeader.from_stream(self.session.reader), 5) if fixed_header: cls = packet_class(fixed_header) packet = yield from cls.from_stream(self.session.reader, fixed_header=fixed_header) self.logger.debug(" <-in-- " + repr(packet)) yield from self.incoming_queues[packet.fixed_header.packet_type].put(packet) self.packet_received.send(packet) else: self.logger.debug("No more data, stopping reader coro") break except asyncio.TimeoutError: self.logger.debug("Input stream read timeout") except NoDataException as nde: self.logger.debug("No data available") except Exception as e: self.logger.warn("Unhandled exception in reader coro: %s" % e) break self.logger.debug("Reader coro stopped")
def _reader_loop(self): self.logger.debug("%s Starting reader coro" % self.session.client_id) running_tasks = collections.deque() keepalive_timeout = self.session.keep_alive if keepalive_timeout <= 0: keepalive_timeout = None while True: try: self._reader_ready.set() while running_tasks and running_tasks[0].done(): running_tasks.popleft() if len(running_tasks) > 1: self.logger.debug("handler running tasks: %d" % len(running_tasks)) fixed_header = yield from asyncio.wait_for( MQTTFixedHeader.from_stream(self.reader), keepalive_timeout, loop=self._loop) if fixed_header: if fixed_header.packet_type == RESERVED_0 or fixed_header.packet_type == RESERVED_15: self.logger.warning( "%s Received reserved packet, which is forbidden: closing connection" % (self.session.client_id)) yield from self.handle_connection_closed() else: cls = packet_class(fixed_header) packet = yield from cls.from_stream( self.reader, fixed_header=fixed_header) yield from self.plugins_manager.fire_event( EVENT_MQTT_PACKET_RECEIVED, packet=packet, session=self.session) task = None if packet.fixed_header.packet_type == CONNACK: task = asyncio.ensure_future( self.handle_connack(packet), loop=self._loop) elif packet.fixed_header.packet_type == SUBSCRIBE: task = asyncio.ensure_future( self.handle_subscribe(packet), loop=self._loop) elif packet.fixed_header.packet_type == UNSUBSCRIBE: task = asyncio.ensure_future( self.handle_unsubscribe(packet), loop=self._loop) elif packet.fixed_header.packet_type == SUBACK: task = asyncio.ensure_future( self.handle_suback(packet), loop=self._loop) elif packet.fixed_header.packet_type == UNSUBACK: task = asyncio.ensure_future( self.handle_unsuback(packet), loop=self._loop) elif packet.fixed_header.packet_type == PUBACK: task = asyncio.ensure_future( self.handle_puback(packet), loop=self._loop) elif packet.fixed_header.packet_type == PUBREC: task = asyncio.ensure_future( self.handle_pubrec(packet), loop=self._loop) elif packet.fixed_header.packet_type == PUBREL: task = asyncio.ensure_future( self.handle_pubrel(packet), loop=self._loop) elif packet.fixed_header.packet_type == PUBCOMP: task = asyncio.ensure_future( self.handle_pubcomp(packet), loop=self._loop) elif packet.fixed_header.packet_type == PINGREQ: task = asyncio.ensure_future( self.handle_pingreq(packet), loop=self._loop) elif packet.fixed_header.packet_type == PINGRESP: task = asyncio.ensure_future( self.handle_pingresp(packet), loop=self._loop) elif packet.fixed_header.packet_type == PUBLISH: task = asyncio.ensure_future( self.handle_publish(packet), loop=self._loop) elif packet.fixed_header.packet_type == DISCONNECT: task = asyncio.ensure_future( self.handle_disconnect(packet), loop=self._loop) elif packet.fixed_header.packet_type == CONNECT: self.handle_connect(packet) else: self.logger.warning( "%s Unhandled packet type: %s" % (self.session.client_id, packet.fixed_header.packet_type)) if task: running_tasks.append(task) else: self.logger.debug( "%s No more data (EOF received), stopping reader coro" % self.session.client_id) break except MQTTException: self.logger.debug("Message discarded") except asyncio.CancelledError: self.logger.debug("Task cancelled, reader loop ending") break except asyncio.TimeoutError: self.logger.debug("%s Input stream read timeout" % self.session.client_id) self.handle_read_timeout() except NoDataException: self.logger.debug("%s No data available" % self.session.client_id) except BaseException as e: self.logger.warning( "%s Unhandled exception in reader coro: %r" % (type(self).__name__, e)) break while running_tasks: running_tasks.popleft().cancel() yield from self.handle_connection_closed() self._reader_stopped.set() self.logger.debug("%s Reader coro stopped" % self.session.client_id) yield from self.stop()
def _reader_loop(self): self.logger.debug("%s Starting reader coro" % self.session.client_id) running_tasks = collections.deque() keepalive_timeout = self.session.keep_alive if keepalive_timeout <= 0: keepalive_timeout = None while True: try: self._reader_ready.set() while running_tasks and running_tasks[0].done(): running_tasks.popleft() if len(running_tasks) > 1: self.logger.debug("handler running tasks: %d" % len(running_tasks)) fixed_header = yield from asyncio.wait_for(MQTTFixedHeader.from_stream(self.reader), keepalive_timeout, loop=self._loop) if fixed_header: if fixed_header.packet_type == RESERVED_0 or fixed_header.packet_type == RESERVED_15: self.logger.warning("%s Received reserved packet, which is forbidden: closing connection" % (self.session.client_id)) yield from self.handle_connection_closed() else: cls = packet_class(fixed_header) packet = yield from cls.from_stream(self.reader, fixed_header=fixed_header) yield from self.plugins_manager.fire_event( EVENT_MQTT_PACKET_RECEIVED, packet=packet, session=self.session) task = None if packet.fixed_header.packet_type == CONNACK: task = ensure_future(self.handle_connack(packet), loop=self._loop) elif packet.fixed_header.packet_type == SUBSCRIBE: task = ensure_future(self.handle_subscribe(packet), loop=self._loop) elif packet.fixed_header.packet_type == UNSUBSCRIBE: task = ensure_future(self.handle_unsubscribe(packet), loop=self._loop) elif packet.fixed_header.packet_type == SUBACK: task = ensure_future(self.handle_suback(packet), loop=self._loop) elif packet.fixed_header.packet_type == UNSUBACK: task = ensure_future(self.handle_unsuback(packet), loop=self._loop) elif packet.fixed_header.packet_type == PUBACK: task = ensure_future(self.handle_puback(packet), loop=self._loop) elif packet.fixed_header.packet_type == PUBREC: task = ensure_future(self.handle_pubrec(packet), loop=self._loop) elif packet.fixed_header.packet_type == PUBREL: task = ensure_future(self.handle_pubrel(packet), loop=self._loop) elif packet.fixed_header.packet_type == PUBCOMP: task = ensure_future(self.handle_pubcomp(packet), loop=self._loop) elif packet.fixed_header.packet_type == PINGREQ: task = ensure_future(self.handle_pingreq(packet), loop=self._loop) elif packet.fixed_header.packet_type == PINGRESP: task = ensure_future(self.handle_pingresp(packet), loop=self._loop) elif packet.fixed_header.packet_type == PUBLISH: task = ensure_future(self.handle_publish(packet), loop=self._loop) elif packet.fixed_header.packet_type == DISCONNECT: task = ensure_future(self.handle_disconnect(packet), loop=self._loop) elif packet.fixed_header.packet_type == CONNECT: self.handle_connect(packet) else: self.logger.warning("%s Unhandled packet type: %s" % (self.session.client_id, packet.fixed_header.packet_type)) if task: running_tasks.append(task) else: self.logger.debug("%s No more data (EOF received), stopping reader coro" % self.session.client_id) break except MQTTException: self.logger.debug("Message discarded") except asyncio.CancelledError: self.logger.debug("Task cancelled, reader loop ending") break except asyncio.TimeoutError: self.logger.debug("%s Input stream read timeout" % self.session.client_id) self.handle_read_timeout() except NoDataException: self.logger.debug("%s No data available" % self.session.client_id) except BaseException as e: self.logger.warning("%s Unhandled exception in reader coro: %r" % (type(self).__name__, e)) break while running_tasks: running_tasks.popleft().cancel() yield from self.handle_connection_closed() self._reader_stopped.set() self.logger.debug("%s Reader coro stopped" % self.session.client_id) yield from self.stop()
async def _reader_loop(self): self.logger.debug("%s Starting reader coro", self.session.client_id) keepalive_timeout = self.session.keep_alive if keepalive_timeout <= 0: keepalive_timeout = None try: async with anyio.create_task_group() as tg: self._reader_task = tg while True: try: async with anyio.fail_after(keepalive_timeout): fixed_header = await MQTTFixedHeader.from_stream( self.stream) if fixed_header is None: self.logger.debug( "%s No more data (EOF received), stopping reader coro", self.session.client_id) break if fixed_header.packet_type == RESERVED_0 or fixed_header.packet_type == RESERVED_15: self.logger.warning( "%s Received reserved packet, which is forbidden: closing connection", self.session.client_id) await self.handle_connection_closed() break cls = packet_class(fixed_header) packet = await cls.from_stream( self.stream, fixed_header=fixed_header) self.logger.debug( "< %s %r", 'B' if 'Broker' in type(self).__name__ else 'C', packet) await self.plugins_manager.fire_event( EVENT_MQTT_PACKET_RECEIVED, packet=packet, session=self.session) try: pt, direct = PACKET_TYPES[ packet.fixed_header.packet_type] fn = getattr(self, 'handle_' + pt) except (KeyError, AttributeError): self.logger.warning( "%s Unhandled packet type: %s", self.session.client_id, packet.fixed_header.packet_type) else: try: if direct: await fn(packet) else: await tg.spawn(fn, packet) except StopAsyncIteration: break except MQTTException: self.logger.debug("Message discarded") except TimeoutError: self.logger.debug( "%s Input stream read timeout", self.session.client_id if self.session else '?') await self.handle_read_timeout() except NoDataException: self.logger.debug("%s No data available", self.session.client_id) break # XXX except anyio.get_cancelled_exc_class(): self.logger.warning("%s CANCEL", type(self).__name__) raise except BaseException as e: self.logger.warning( "%s Unhandled exception in reader coro", type(self).__name__, exc_info=e) raise await tg.cancel_scope.cancel() finally: async with anyio.open_cancel_scope(shield=True): self.logger.debug( "%s %s coro stopped", 'Broker' if 'Broker' in type(self).__name__ else 'Client', self.session.client_id if self.session else '?') await self._reader_stopped.set() if self._reader_task is not None: self._reader_task = None await self.handle_connection_closed()
def _reader_coro(self): self.logger.debug("%s Starting reader coro" % self.session.client_id) while self._running: try: self._reader_ready.set() keepalive_timeout = self.session.keep_alive if keepalive_timeout <= 0: keepalive_timeout = None fixed_header = yield from asyncio.wait_for(MQTTFixedHeader.from_stream(self.reader), keepalive_timeout) if fixed_header: if fixed_header.packet_type == RESERVED_0 or fixed_header.packet_type == RESERVED_15: self.logger.warn("%s Received reserved packet, which is forbidden: closing connection" % (self.session.client_id)) yield from self.handle_connection_closed() else: cls = packet_class(fixed_header) packet = yield from cls.from_stream(self.reader, fixed_header=fixed_header) self.logger.debug("%s <-in-- %s" % (self.session.client_id, repr(packet))) self._loop.call_soon(self.on_packet_received.send, packet) task = None if packet.fixed_header.packet_type == CONNACK: task = asyncio.Task(self.handle_connack(packet)) elif packet.fixed_header.packet_type == SUBSCRIBE: task = asyncio.Task(self.handle_subscribe(packet)) elif packet.fixed_header.packet_type == UNSUBSCRIBE: task = asyncio.Task(self.handle_unsubscribe(packet)) elif packet.fixed_header.packet_type == SUBACK: task = asyncio.Task(self.handle_suback(packet)) elif packet.fixed_header.packet_type == UNSUBACK: task = asyncio.Task(self.handle_unsuback(packet)) elif packet.fixed_header.packet_type == PUBACK: task = asyncio.Task(self.handle_puback(packet)) elif packet.fixed_header.packet_type == PUBREC: task = asyncio.Task(self.handle_pubrec(packet)) elif packet.fixed_header.packet_type == PUBREL: task = asyncio.Task(self.handle_pubrel(packet)) elif packet.fixed_header.packet_type == PUBCOMP: task = asyncio.Task(self.handle_pubcomp(packet)) elif packet.fixed_header.packet_type == PINGREQ: task = asyncio.Task(self.handle_pingreq(packet)) elif packet.fixed_header.packet_type == PINGRESP: task = asyncio.Task(self.handle_pingresp(packet)) elif packet.fixed_header.packet_type == PUBLISH: task = asyncio.Task(self.handle_publish(packet)) elif packet.fixed_header.packet_type == DISCONNECT: task = asyncio.Task(self.handle_disconnect(packet)) elif packet.fixed_header.packet_type == CONNECT: task = asyncio.Task(self.handle_connect(packet)) else: self.logger.warn("%s Unhandled packet type: %s" % (self.session.client_id, packet.fixed_header.packet_type)) if task: # Wait for message handling ends asyncio.wait([task]) else: self.logger.debug("%s No more data (EOF received), stopping reader coro" % self.session.client_id) yield from self.handle_connection_closed() break except asyncio.TimeoutError: self.logger.debug("%s Input stream read timeout" % self.session.client_id) self.handle_read_timeout() except NoDataException as nde: self.logger.debug("%s No data available" % self.session.client_id) except Exception as e: self.logger.warn("%s Unhandled exception in reader coro: %s" % (self.session.client_id, e)) break self.logger.debug("%s Reader coro stopped" % self.session.client_id)
def _reader_coro(self): self.logger.debug("%s Starting reader coro" % self.session.client_id) while self._running: try: self._reader_ready.set() keepalive_timeout = self.session.keep_alive if keepalive_timeout <= 0: keepalive_timeout = None fixed_header = yield from asyncio.wait_for( MQTTFixedHeader.from_stream(self.reader), keepalive_timeout) if fixed_header: if fixed_header.packet_type == RESERVED_0 or fixed_header.packet_type == RESERVED_15: self.logger.warn( "%s Received reserved packet, which is forbidden: closing connection" % (self.session.client_id)) yield from self.handle_connection_closed() else: cls = packet_class(fixed_header) packet = yield from cls.from_stream( self.reader, fixed_header=fixed_header) self.logger.debug( "%s <-in-- %s" % (self.session.client_id, repr(packet))) self._loop.call_soon(self.on_packet_received.send, packet) task = None if packet.fixed_header.packet_type == CONNACK: task = asyncio.Task(self.handle_connack(packet)) elif packet.fixed_header.packet_type == SUBSCRIBE: task = asyncio.Task(self.handle_subscribe(packet)) elif packet.fixed_header.packet_type == UNSUBSCRIBE: task = asyncio.Task( self.handle_unsubscribe(packet)) elif packet.fixed_header.packet_type == SUBACK: task = asyncio.Task(self.handle_suback(packet)) elif packet.fixed_header.packet_type == UNSUBACK: task = asyncio.Task(self.handle_unsuback(packet)) elif packet.fixed_header.packet_type == PUBACK: task = asyncio.Task(self.handle_puback(packet)) elif packet.fixed_header.packet_type == PUBREC: task = asyncio.Task(self.handle_pubrec(packet)) elif packet.fixed_header.packet_type == PUBREL: task = asyncio.Task(self.handle_pubrel(packet)) elif packet.fixed_header.packet_type == PUBCOMP: task = asyncio.Task(self.handle_pubcomp(packet)) elif packet.fixed_header.packet_type == PINGREQ: task = asyncio.Task(self.handle_pingreq(packet)) elif packet.fixed_header.packet_type == PINGRESP: task = asyncio.Task(self.handle_pingresp(packet)) elif packet.fixed_header.packet_type == PUBLISH: task = asyncio.Task(self.handle_publish(packet)) elif packet.fixed_header.packet_type == DISCONNECT: task = asyncio.Task(self.handle_disconnect(packet)) elif packet.fixed_header.packet_type == CONNECT: task = asyncio.Task(self.handle_connect(packet)) else: self.logger.warn("%s Unhandled packet type: %s" % (self.session.client_id, packet.fixed_header.packet_type)) if task: # Wait for message handling ends asyncio.wait([task]) else: self.logger.debug( "%s No more data (EOF received), stopping reader coro" % self.session.client_id) yield from self.handle_connection_closed() break except asyncio.TimeoutError: self.logger.debug("%s Input stream read timeout" % self.session.client_id) self.handle_read_timeout() except NoDataException as nde: self.logger.debug("%s No data available" % self.session.client_id) except Exception as e: self.logger.warn("%s Unhandled exception in reader coro: %s" % (self.session.client_id, e)) break self.logger.debug("%s Reader coro stopped" % self.session.client_id)
def client_connected(self, reader, writer): #handle connection and create session to add to the list of sessions #read connection packet from the client connect = yield from MQTTConnect.ConnectPacket.from_stream(reader) if (connect.payload.client_id is None): generate_id = True else: generate_id = False #send a connack packet to client depending on correct credentials connack = None if (connect.username == self._username and connect.password == self._password): connack = MQTTConnack.ConnackPacket.build( 0, MQTTConnack.CONNECTION_ACCEPTED) connected = True else: connack = MQTTConnack.ConnackPacket.build( 0, MQTTConnack.BAD_USERNAME_PASSWORD) connected = False writer.write(connack.to_bytes()) if (not connected): return new_session = Session() if (generate_id): new_session.client_id = new_session.generate_client_id() else: new_session.client_id = connect.client_id new_session.remote_address = writer.get_extra_info('peername') new_session.remote_port = writer.get_extra_info('socket') new_session.username = connect.username new_session.password = connect.password new_session.keep_alive = connect.keep_alive new_session.writer = writer new_session.reader = reader self._sessions[new_session.client_id] = new_session print("New client; %s connected from %s with keep_alive: %s" % (new_session.client_id, new_session.remote_address, new_session.keep_alive)) #received packets are checked and the corresponding method is used (publish, sub/unsub, disconnect) try: while connected: mqtt_header = yield from asyncio.wait_for( MQTTFixedHeader.from_stream(reader), new_session.keep_alive + 1, loop=self._loop) cls = packet_class(fixed_header=mqtt_header) packet = yield from cls.from_stream(reader, fixed_header=mqtt_header) if (packet.fixed_header.packet_type == SUBSCRIBE): for (topic, qos) in packet.payload.topics: if (qos != 0): print("QoS is different than expected") print(qos) self.add_subscription(topic, new_session) elif (packet.fixed_header.packet_type == UNSUBSCRIBE): for (topic, qos) in packet.payload.topics: if (qos != 0): print("QoS is different than expected") print(qos) self.del_subscription(topic, new_session) elif (packet.fixed_header.packet_type == PUBLISH): topic = packet.variable_header.topic_name message = packet.payload.data print("Broadcast; Topic: %s, Payload: %s" % (topic, message)) yield from self.broadcast_message(new_session, topic, message) elif (packet.fixed_header.packet_type == DISCONNECT): self.del_all_subscriptions(new_session) self.del_session(new_session.client_id) connected = False print("Client: %s disconnected" % (new_session.client_id)) elif (packet.fixed_header.packet_type == PINGREQ): pingresp_packet = PingRespPacket.build() writer.write(pingresp_packet.to_bytes()) else: print('Not yet supported packet received') except asyncio.TimeoutError: print("Client %s didn't respond; diconnecting" % new_session.client_id) self.del_session(new_session.client_id)