async def connect(self, aio_loop): self._allow_states(*ServiceState.halted_states()) self.script = Queue(loop=aio_loop) self.in_buffer = StreamReader(loop=aio_loop) self.out_buffer = StreamReader(loop=aio_loop) # Transfer deferred actions. for action in self._deferred_actions: self._add_action_now(action) self._deferred_actions = [] # If the client wishes to delay startup of the scripted actions (e.g. to register an EventStream first), # we set this up here. if self.defer_script: self._defer_event = Event(loop=aio_loop) # We're inside of an asyncio task, but need a synchronous start. Hack up # an asyncio version of it. started = Event(loop=aio_loop) def async_start(): self.sync_start() self.aio_loop.call_soon_threadsafe(started.set) Thread(target=async_start).start() await started.wait() return self.out_buffer, self
async def test_isalive_false_not_auth(): conn = AsyncTelnetTransport("localhost") conn._isauthenticated = False conn.stdout = StreamReader() data = b"somethingtoread" conn.stdout.feed_data(data) assert conn.isalive() is False
def __init__(self, loop, config): super().__init__(loop=loop) self._loop = loop self._config = config self._transport = None self._write_pending_data_topic = [] # tuple (data, topic) self._connected = False self._encryptor = cryptor.Cryptor(self._config['password'], self._config['method']) self._peername = None self._reader_task = None self._data_task = None self._keepalive_task = None self._keepalive_timeout = self._config['timeout'] self._reader_ready = None self._reader_stopped = asyncio.Event(loop=self._loop) self._stream_reader = StreamReader(loop=self._loop) self._stream_writer = None self._reader = None self._topic_to_clients = {} self._queue = Queue(loop=loop)
async def _open(self): rx = StreamReader() transport, proto = await get_running_loop().connect_write_pipe( lambda: StreamReaderProtocol(rx), os.fdopen(self._fd, "wb")) tx = StreamWriter(transport, proto, rx, get_running_loop()) return transport, tx
def connection_made(self, transport): if self.kill_active: return sock = transport.get_extra_info('socket') set_tcp_keepalive(sock, opts=dict( tcp_keepalive=True, tcp_keepalive_idle=self.tcp_keepalive_time, tcp_keepalive_intvl=self.tcp_keepalive_interval, tcp_keepalive_cnt=self.tcp_keepalive_probes, )) # https://eklitzke.org/the-caveats-of-tcp-nodelay sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) if hasattr(socket, 'TCP_USER_TIMEOUT'): logger.debug('Setting TCP_USER_TIMEOUT to %s', self.tcp_user_timeout_seconds * 1000) sock.setsockopt(socket.SOL_TCP, socket.TCP_USER_TIMEOUT, self.tcp_user_timeout_seconds * 1000) self.transport = transport self._reader = StreamReader() self._reader.set_transport(transport) loop = asyncio.get_event_loop() loop.create_task(self.receive_commands()) super().connection_made(transport)
async def decrypt_stream(self, reader: StreamReader) -> StreamReader: data_length = await reader.read(ENCRYPTED_DATA_LENGTH) if not data_length: raise SecurityError('Connection closed') data_length_int = int.from_bytes(data_length, byteorder='little') + AUTH_TAG_LENGTH encrypted_data = await reader.read(data_length_int) chacha = ChaCha20Poly1305(self.context['decrypt_key']) nonce = b'\x00\x00\x00\x00' + self.encrypted_request_count.to_bytes( 8, byteorder='little') try: decrypted_data = chacha.decrypt(nonce, encrypted_data, data_length) except InvalidTag: decrypted_data = None if not decrypted_data: raise SecurityError('Unable to decrypt encrypted data') self.encrypted_request_count += 1 decrypted_reader = StreamReader() decrypted_reader.feed_data(decrypted_data) return decrypted_reader
async def test_read_timeout(): conn = AsyncTelnetTransport("localhost") conn.stdout = StreamReader() conn._stdout_binary_transmission = True conn.set_timeout(0.01) with pytest.raises(ScrapliTimeout): await conn.read()
async def test_authenticate(transport, protocol): conn = AsyncTelnetTransport( "localhost", auth_password="******", auth_username="******", timeout_ops=10, timeout_socket=5, ) conn.stdout = StreamReader() conn.stdin = StreamWriter(transport, protocol, reader=None, loop=asyncio.get_event_loop()) # feed data in w/ the username prompt already in it -- auth should then send the username and # clear the buffer... then it should read and see the password that we are inserting later data = b"\xff\xfd\x18\xff\xfd \xff\xfd#username:\xff\xfd'\xff\xfb\x03\xff\xfd\x01\xff\xfd\x1f\xff\xfb\x05\xff\xfd!\xff\xfb\x03\xff\xfb\x01" conn.stdout.feed_data(data) async def _put_login_data_in_reader(): # this sleep is enough that we should *always* see a an additional return char that we send # when we dont get any output on telnet connections await asyncio.sleep(1.5) conn.stdout.feed_data(b"Password:"******"lookforthisusername" in conn.stdin.transport.out_buf assert b"lookforthispassword" in conn.stdin.transport.out_buf # a return for the username, one for password and one for the extra return we send when we dont # see the password prompt soon enough assert conn.stdin.transport.out_buf.count(b"\n") >= 3
async def test_read_success_stdout_binary(): conn = AsyncTelnetTransport("localhost") conn.stdout = StreamReader() conn._stdout_binary_transmission = True data = b"\x00somethingtoread" conn.stdout.feed_data(data) out = await conn.read() assert out == b"somethingtoread"
async def test_read_success(): conn = AsyncTelnetTransport("localhost") # load up the conn's stdout obj w/ a little faked out streamreader conn.stdout = StreamReader() data = b"somethingtoread" conn.stdout.feed_data(data) out = await conn.read() assert out == data
async def read_pipe(file, size): loop = get_event_loop() reader = StreamReader() protocol = StreamReaderProtocol(reader) transport, _ = await loop.connect_read_pipe( lambda: protocol, fdopen(os_open(file, O_RDONLY | O_NONBLOCK))) data = await reader.read(size) transport.close() return data
async def test_BufferedReader_overflow(): stream_data = b"1234" stream_reader = StreamReader() stream_reader.feed_data(stream_data) reader = BufferedReader(stream_reader, 1) result = await reader.read_bytes(4) assert result == stream_data
async def connect(self): await self.connecting.wait() kcpConn = UKcp(self.conv, self) reader = StreamReader(limit=_DEFAULT_LIMIT, loop=self._loop) writer = StreamWriter(TransportWrapper(self.conv, self), self, reader, self._loop) conn = Conn(kcpConn=kcpConn, reader=reader, writer=writer) self.conns[self.conv] = conn self.activeConns.add(self.conv) self.conv += 1 return reader, writer
async def main(): arg_parser = ArgumentParser(prog="bloXroute CLI", epilog=get_description(), formatter_class=RawDescriptionHelpFormatter) cli_parser = ArgumentParser(prog="bloXroute CLI", epilog=get_description(), formatter_class=RawDescriptionHelpFormatter) add_base_arguments(arg_parser) add_base_arguments(cli_parser) add_run_arguments(cli_parser) args = sys.argv[1:] if "-h" in args or "--help" in args: cli_parser.print_help() arg_parser.exit() opts, params = arg_parser.parse_known_args() stdin_reader = StreamReader() cli_loop = asyncio.get_event_loop() await cli_loop.connect_read_pipe( lambda: StreamReaderProtocol(stdin_reader), sys.stdin) transport, protocol = await cli_loop.connect_write_pipe( lambda: FlowControlMixin(), os.fdopen(sys.stdout.fileno(), "wb")) stdout_writer = StreamWriter(transport, protocol, None, cli_loop) if not validate_args(opts, stdout_writer): exit(1) try: if opts.interactive_shell or len(params) == 0: await run_cli(opts.rpc_host, opts.rpc_port, opts.rpc_user, opts.rpc_password, opts.account_id, opts.secret_hash, opts.cloud_api_url, opts.cloud_api, cli_parser, stdin_reader, stdout_writer) else: if "help" in sys.argv: cli_parser.print_help(file=ArgParserFile(stdout_writer)) async with RpcClient(opts.rpc_host, opts.rpc_port, opts.rpc_user, opts.rpc_password, opts.account_id, opts.secret_hash, opts.cloud_api_url, opts.cloud_api) as client: await parse_and_handle_command(cli_parser, stdout_writer, client) except (ClientConnectorError, ClientConnectionError, TimeoutError, CancelledError) as e: stdout_writer.write( f"Connection to RPC server is broken: {e}, exiting!\n".encode( "utf-8")) await stdout_writer.drain() if opts.debug: raise finally: stdout_writer.close()
async def start_tls(self, ssl_context: SSLContext) -> None: loop = asyncio.get_event_loop() transport = self.writer.transport protocol = transport.get_protocol() # type: ignore new_transport = await loop.start_tls( # type: ignore transport, protocol, ssl_context, server_side=True) protocol._stream_reader = StreamReader(loop=loop) protocol._client_connected_cb = self._reset_streams protocol.connection_made(new_transport) self._print('%d <->| %s', b'<TLS handshake>')
async def test_telnet_isauthenticated_failed_password(transport, protocol): conn = AsyncTelnetTransport("localhost") conn.stdout = StreamReader() conn.stdin = StreamWriter(transport, protocol, reader=None, loop=asyncio.get_event_loop()) data = b"password:" conn.stdout.feed_data(data) _isauthenticated = await conn._telnet_isauthenticated() assert _isauthenticated is False
def datagram_received(self, data, addr): self.default_receiver = addr conv = UKcp.ikcp_decode32u(data, 0) if conv in self.conns: self.activeConns.add(conv) self.conns[conv].kcpConn.input(data) else: kcpConn = UKcp(conv, self) reader = StreamReader(limit=_DEFAULT_LIMIT, loop=self._loop) writer = StreamWriter(TransportWrapper(conv, self), self, reader, self._loop) conn = Conn(kcpConn=kcpConn, reader=reader, writer=writer) self.conns[conv] = conn self.activeConns.add(conv) self._loop.create_task(self.cb(reader, writer))
async def read_pipe(file, size): loop = get_event_loop() reader = StreamReader() protocol = StreamReaderProtocol(reader) transport, _ = await loop.connect_read_pipe( lambda: protocol, fdopen(os_open(file, O_RDONLY | O_NONBLOCK))) chunks = list() while size > 0: chunk = await reader.read(size) if not chunk: break chunks.append(chunk) size -= len(chunk) transport.close() return b''.join(chunks)
async def test_telnet_isauthenticated_success(transport, protocol): conn = AsyncTelnetTransport("localhost") assert conn._isauthenticated is False conn.stdout = StreamReader() conn.stdin = StreamWriter(transport, protocol, reader=None, loop=asyncio.get_event_loop()) # feed data in w/ the username prompt already in it -- auth should then send the username and # clear the buffer... then it should read and see the password that we are inserting later data = b"averyniceswitch#" conn.stdout.feed_data(data) await conn._telnet_isauthenticated() assert conn._isauthenticated is True
async def open(self, loop=None): """ Open the receive end on the given event loop, returning an instance of [`asyncio.StreamReader`](https://docs.python.org/3/library/asyncio-stream.html#streamreader). If no event loop is given, the default one will be used. """ if loop is None: loop = asyncio.get_event_loop() rx = StreamReader(loop=loop) _, _ = await loop.connect_read_pipe( lambda: StreamReaderProtocol(rx, loop=loop), os.fdopen(self._fd)) return rx
async def test_handle_control_chars(transport, protocol): conn = AsyncTelnetTransport("localhost") conn._isauthenticated = True conn.stdout = StreamReader() conn.stdin = StreamWriter(transport, protocol, reader=None, loop=asyncio.get_event_loop()) data = b"\xff\xfd\x18\xff\xfd \xff\xfd#someoutput\xff\xfd'\xff\xfb\x03\xff\xfd\x01\xff\xfd\x1f\xff\xfb\x05\xff\xfd!\xff\xfb\x03\xff\xfb\x01moreoutput" conn.stdout.feed_data(data) output = await conn._handle_control_chars() assert output == b"someoutputmoreoutput" assert ( conn.stdin.transport.out_buf == b"\xff\xfc\x18\xff\xfc \xff\xfc#\xff\xfc'\xff\xfe\x03\xff\xfc\x01\xff\xfc\x1f\xff\xfe\x05\xff\xfc!\xff\xfe\x03\xff\xfe\x01" )
async def open(self, loop=None): """ Open the transmit end on the given event loop, returning an instance of [`asyncio.StreamWriter`](https://docs.python.org/3/library/asyncio-stream.html#streamwriter). If no event loop is given, the default one will be used. """ if loop is None: loop = asyncio.get_event_loop() txTransport, txProto = await loop.connect_write_pipe( lambda: StreamReaderProtocol(StreamReader(loop=loop), loop=loop), os.fdopen(self._fd, "w")) tx = StreamWriter(txTransport, txProto, None, loop) return tx
async def test_telnet_isauthenticated_success_set_binary_transmission( transport, protocol): conn = AsyncTelnetTransport("localhost") assert conn._isauthenticated is False assert conn._stdout_binary_transmission is False conn.stdout = StreamReader() conn.stdin = StreamWriter(transport, protocol, reader=None, loop=asyncio.get_event_loop()) data = b"\x00averyniceswitch#" conn.stdout.feed_data(data) await conn._telnet_isauthenticated() assert conn._isauthenticated is True assert conn._stdout_binary_transmission is True
async def _make_new_stream(self, stream_name: StreamName): await self._write_new_stream(stream_name) self._stream_names.add(stream_name) reader: StreamReader = StreamReader() stream_id = _get_stream_id_from_name(stream_name) self._stream_readers[stream_id] = reader def cleanup_callback(): self._stream_names.remove(stream_name) del self._stream_readers[stream_id] del self._streams[stream_id] stream = Stream( stream_address=StreamAddress(self.ip, self.port, stream_name), protocol=self._protocol, reader=reader, cleanup_callback=cleanup_callback, ) self._streams[stream_id] = stream return stream
def __init__(self, loop, config): super().__init__(loop=loop) self._loop = loop self._transport = None self._encryptor = cryptor.Cryptor(config['password'], config['method']) self._topic_to_remote = {} self._peername = None self._reader_task = None self._data_task = None self._keepalive_task = None self._keepalive_timeout = config['timeout'] self._reader_ready = None self._reader_stopped = asyncio.Event(loop=self._loop) self._stream_reader = StreamReader(loop=self._loop) self._stream_writer = None self._reader = None self._approved = False self._queue = Queue(loop=loop)
async def _do_starttls(self) -> Response: ssl_context = self.config.ssl_context if ssl_context is None: raise ValueError('ssl_context is None') elif not self._offer_starttls: return Response(Condition.NO, text='Bad command.') resp = Response(Condition.OK) await self._write_response(resp) loop = asyncio.get_event_loop() transport = self.writer.transport protocol = transport.get_protocol() # type: ignore new_transport = await loop.start_tls( # type: ignore transport, protocol, ssl_context, server_side=True) protocol._stream_reader = StreamReader(loop=loop) protocol._client_connected_cb = self._reset_streams protocol.connection_made(new_transport) self._print('%d <->| %s', b'<TLS handshake>') self._offer_starttls = False self.auth = self.config.insecure_auth return CapabilitiesResponse(self.capabilities)
async def test_authenticate_timeout(transport, protocol): conn = AsyncTelnetTransport("localhost", auth_password="******", auth_username="******") # make the timeout way faster so we dont have to wait conn._timeout_ops_auth = 0.25 conn.stdout = StreamReader() conn.stdin = StreamWriter(transport, protocol, reader=None, loop=asyncio.get_event_loop()) # feed data in w/ the username prompt already in it -- auth should then send the username and # clear the buffer... then it should read and see the password that we are inserting later data = b"\xff\xfd\x18\xff\xfd \xff\xfd#username:\xff\xfd'\xff\xfb\x03\xff\xfd\x01\xff\xfd\x1f\xff\xfb\x05\xff\xfd!\xff\xfb\x03\xff\xfb\x01" conn.stdout.feed_data(data) with pytest.raises(ScrapliTimeout) as exc: await conn._authenticate() assert str(exc.value) == "Timed out looking for telnet login prompts" # asserting that we at least got the username sent assert b"lookforthisusername" in conn.stdin.transport.out_buf
def reestablish_connection(self): self._stream_reader = StreamReader(loop=self._loop) self._encryptor = cryptor.Cryptor(self._config['password'], self._config['method']) self._loop.call_later(5, lambda: self._loop.create_task(self.create_connection()))
async def test_isalive_false_eof(): conn = AsyncTelnetTransport("localhost") conn._isauthenticated = True conn.stdout = StreamReader() conn.stdout.feed_eof() assert conn.isalive() is False
def reader(loop): return StreamReader(loop=loop)