1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
|
# Copyright (c) 2021 Jeff Irion and contributors
#
# This file is part of the adb-shell package.
"""A class for creating a socket connection with the device and sending and receiving data.
* :class:`TcpTransportAsync`
* :meth:`TcpTransportAsync.bulk_read`
* :meth:`TcpTransportAsync.bulk_write`
* :meth:`TcpTransportAsync.close`
* :meth:`TcpTransportAsync.connect`
"""
import asyncio
import async_timeout
from .base_transport_async import BaseTransportAsync
from ..exceptions import TcpTimeoutException
class TcpTransportAsync(BaseTransportAsync):
"""TCP connection object.
Parameters
----------
host : str
The address of the device; may be an IP address or a host name
port : int
The device port to which we are connecting (default is 5555)
Attributes
----------
_host : str
The address of the device; may be an IP address or a host name
_port : int
The device port to which we are connecting (default is 5555)
_reader : StreamReader, None
Object for reading data from the socket
_writer : StreamWriter, None
Object for writing data to the socket
"""
def __init__(self, host, port=5555):
self._host = host
self._port = port
self._reader = None
self._writer = None
async def close(self):
"""Close the socket connection.
"""
if self._writer:
try:
self._writer.close()
await self._writer.wait_closed()
except OSError:
pass
self._reader = None
self._writer = None
async def connect(self, transport_timeout_s):
"""Create a socket connection to the device.
Parameters
----------
transport_timeout_s : float, None
Timeout for connecting to the socket; if it is ``None``, then it will block until the operation completes
"""
try:
async with async_timeout.timeout(transport_timeout_s):
self._reader, self._writer = await asyncio.open_connection(self._host, self._port)
except asyncio.TimeoutError as exc:
msg = 'Connecting to {}:{} timed out ({} seconds)'.format(self._host, self._port, transport_timeout_s)
raise TcpTimeoutException(msg) from exc
async def bulk_read(self, numbytes, transport_timeout_s):
"""Receive data from the socket.
Parameters
----------
numbytes : int
The maximum amount of data to be received
transport_timeout_s : float, None
Timeout for reading data from the socket; if it is ``None``, then it will block until the read operation completes
Returns
-------
bytes
The received data
Raises
------
TcpTimeoutException
Reading timed out.
"""
try:
async with async_timeout.timeout(transport_timeout_s):
return await self._reader.read(numbytes)
except asyncio.TimeoutError as exc:
msg = 'Reading from {}:{} timed out ({} seconds)'.format(self._host, self._port, transport_timeout_s)
raise TcpTimeoutException(msg) from exc
async def bulk_write(self, data, transport_timeout_s):
"""Send data to the socket.
Parameters
----------
data : bytes
The data to be sent
transport_timeout_s : float, None
Timeout for writing data to the socket; if it is ``None``, then it will block until the write operation completes
Returns
-------
int
The number of bytes sent
Raises
------
TcpTimeoutException
Sending data timed out. No data was sent.
"""
try:
self._writer.write(data)
async with async_timeout.timeout(transport_timeout_s):
await self._writer.drain()
return len(data)
except asyncio.TimeoutError as exc:
msg = 'Sending data to {}:{} timed out after {} seconds. No data was sent.'.format(self._host, self._port, transport_timeout_s)
raise TcpTimeoutException(msg) from exc
|