def _connection_attached(self, conn, **handler_kwargs): self.logger.info("[conn|%d][host|%s][peer|%s] made", conn.connid, conn.sockname, conn.peername) assert conn.connid not in self.connections self.connections[conn.connid] = conn conn.add_close_cb(self._connection_detached) if self.parser: # used by stub conn.pack_meta = self.parser.pack_meta conn.unpack = self.parser.unpack conn.worker_gr = greenlet_pool.spawn(self.handler, conn, **handler_kwargs) conn.worker_gr.link_exception(conn.close) self.connection_attached(conn)
def run(self, conn): if not conn.oninit(): return header_length = HEADER_LENGTH max_packet_length = self.MAX_PACKET_LENGTH read, unpack = conn.read, self.unpack tasks_queue = Queue(self.MAX_TASKS) handle_response = self.handle_response gr = greenlet_pool.spawn(self.sequential_worker, tasks_queue) gr.link_exception(conn.close) callbacks = { PBC.REQUEST: self.handle_request, PBC.NOTIFICATION: self.handle_notification, } response, new_task = PBC.RESPONSE, tasks_queue.put try: while 1: header = read(header_length) if not header: conn.close(reset=True) break packet_length, content_length = unpack_header(header) if packet_length > max_packet_length: conn.close( RpcError.PacketTooLarge(packet_length=packet_length) ) break buf = read(packet_length + content_length) meta = unpack(buf[:packet_length], PBC) controller = Controller(meta, conn) content = buf[packet_length:] packet_type = meta.packet_type if packet_type == response: handle_response(controller, content) else: new_task((callbacks[packet_type], controller, content)) except socket_error as ex: conn.close(ex, reset=True) except Exception as ex: conn.close(ex) finally: tasks_queue.queue.clear() new_task(None)