async def _tcp_server(self, host, port, backlog): """TCP Server implementation. Opens socket for accepting connection and creates task for every new accepted connection """ addr = socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM)[0][-1] sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.setblocking(False) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.bind(addr) sock.listen(backlog) try: while True: yield asyncio.IORead(sock) csock, caddr = sock.accept() csock.setblocking(False) # Start handler / keep it in the map - to be able to # shutdown gracefully - by close all connections self.processed_connections += 1 hid = id(csock) handler = self._handler(asyncio.StreamReader(csock), asyncio.StreamWriter(csock, {})) self.conns[hid] = handler self.loop.create_task(handler) # In case of max concurrency reached - temporary pause server: # 1. backlog must be greater than max_concurrency, otherwise # client will got "Connection Reset" # 2. Server task will be resumed whenever one active connection finished if len(self.conns) == self.max_concurrency: # Pause yield False except asyncio.CancelledError: return finally: sock.close()
async def __handler(self): while True: try: # Wait for packet yield asyncio.IORead(self.sock) packet, addr = self.sock.recvfrom(self.max_pkt_len) if len(packet) < DNS_QUERY_START: # Malformed packet continue # Check question / answer count qd = int.from_bytes(packet[4:6], 'big') an = int.from_bytes(packet[6:8], 'big') # We're tiny server - don't handle complicated queries if qd != 1 or an > 0: return None query = bytearray(packet[DNS_QUERY_START:]) if len(query) <= 4: # malformed packet - query must be at least 5 bytes continue # verify query type - only A/* supported qtype = int.from_bytes(query[-4:-2], 'big') if qtype not in [0x01, 0xff]: # unsupported query type, AAAA, CNAME, etc # Flags: 0x8180 Standard query response, No error resp = bytearray(packet) resp[2:4] = b'\x81\x80' self.sock.sendto(resp, addr) continue # sometimes request may query for ALL records (0xff) # since we're only support A records - simply override it to 0x01 query[-4:-2] = b'\x00\x01' resp = None for d in self.dlist: if d[0] == query: # Prepare response right from request :) resp = bytearray(len(packet) + len(d[1])) resp[:len(packet)] = packet # Adjust flags resp[2:4] = b'\x85\x80' # Flags and codes resp[6:8] = b'\x00\x01' # Answer record count # Add answer resp[len(packet):] = d[1] self.sock.sendto(resp, addr) break if not resp and not self.ignore_unknown: # no such domain, just send req back with error flag set resp = bytearray(packet) # Flags: 0x8183 Standard query response, No such name resp[2:4] = b'\x81\x83' self.sock.sendto(resp, addr) gc.collect() except asyncio.CancelledError: # Coroutine has been canceled self.sock.close() self.sock = None return except AttributeError: raise except Exception as e: log.exc(e, "")
async def _tcp_server(B,host,port,backlog): E=socket.getaddrinfo(host,port,0,socket.SOCK_STREAM)[0][-1];A=socket.socket(socket.AF_INET,socket.SOCK_STREAM);A.setblocking(_I);A.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1);A.bind(E);A.listen(backlog) try: while _E: if IS_UASYNCIO_V3:yield uasyncio.core._io_queue.queue_read(A) else:yield asyncio.IORead(A) C,G=A.accept();C.setblocking(_I);B.processed_connections+=1;F=id(C);D=B._handler(asyncio.StreamReader(C),asyncio.StreamWriter(C,{}));B.conns[F]=D;B.loop.create_task(D) if len(B.conns)==B.max_concurrency:yield _I except asyncio.CancelledError:return finally:A.close()
async def _reader_task(self, reader): try: # Wait for message, then process it while True: yield uasyncio.IORead(reader.ios) await self._process_msg(reader) except (OSError, MQTTException) as e: log.info("Connection lost: %s", e) self.reconnect() except uasyncio.CancelledError: return except Exception as e: log.exc(e, "") self.reconnect() finally: await reader.aclose()
async def client_rx(self): while True: if self.sw_client != None: try: yield asyncio.IORead(self.sw_client.socket) uos.dupterm_notify(True) # dupterm_notify will somehow make a copy of sw_client except: # clean up log.info("Telnet client disconnected ...") yield asyncio.IOReadDone(self.sw_client.socket) self.stop() await asyncio.sleep_ms(1) else: await asyncio.sleep(1)
async def run(timeout, nconns=10, verbose=False): addr = socket.getaddrinfo('0.0.0.0', PORT, 0, socket.SOCK_STREAM)[0][-1] s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) socks.append(s) s.bind(addr) s.listen(nconns) verbose and print('Awaiting connection.') while True: yield asyncio.IORead(s) # Register socket for polling conn, addr = s.accept() conn.setblocking(False) try: idstr = await readline(conn, timeout) verbose and print('Got connection from client', idstr) socks.append(conn) Connection.go(int(idstr), timeout, verbose, conn) except OSError: if conn is not None: conn.close()
async def readloop(self): while True: print('About to yield') yield asyncio.IORead(self) print('Should never happen')