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
|
import curio
from ._errors import ProxyConnectionError, ProxyTimeoutError
from ._proxy_async import (
AsyncProxy,
Socks4ProxyNegotiator,
Socks5ProxyNegotiator,
HttpProxyNegotiator
)
from ._proxy_factory import ProxyFactory
from ._stream_async_curio import CurioSocketStream
from ._types import ProxyType
DEFAULT_TIMEOUT = 60
class CurioProxyConnection(AsyncProxy):
def __init__(self, proxy_host, proxy_port):
self._proxy_host = proxy_host
self._proxy_port = proxy_port
self._dest_host = None
self._dest_port = None
self._timeout = None
self._stream = CurioSocketStream()
async def connect(self, dest_host, dest_port, timeout=None, _socket=None):
if timeout is None:
timeout = DEFAULT_TIMEOUT
self._dest_host = dest_host
self._dest_port = dest_port
self._timeout = timeout
try:
await curio.timeout_after(self._timeout, self._connect, _socket)
except OSError as e:
await self._stream.close()
msg = ('Can not connect to proxy %s:%s [%s]' %
(self._proxy_host, self._proxy_port, e.strerror))
raise ProxyConnectionError(e.errno, msg) from e
except curio.TaskTimeout as e:
await self._stream.close()
raise ProxyTimeoutError('Proxy connection timed out: %s'
% self._timeout) from e
except Exception:
await self._stream.close()
raise
return self._stream.socket
async def _connect(self, _socket=None):
await self._stream.open_connection(
host=self._proxy_host,
port=self._proxy_port,
timeout=self._timeout,
_socket=_socket
)
await self.negotiate()
async def negotiate(self):
raise NotImplementedError() # pragma: no cover
@property
def proxy_host(self):
return self._proxy_host
@property
def proxy_port(self):
return self._proxy_port
class Socks5Proxy(Socks5ProxyNegotiator, CurioProxyConnection):
def __init__(self, proxy_host, proxy_port,
username=None, password=None, rdns=None):
super().__init__(proxy_host=proxy_host, proxy_port=proxy_port)
self._username = username
self._password = password
self._rdns = rdns
class Socks4Proxy(Socks4ProxyNegotiator, CurioProxyConnection):
def __init__(self, proxy_host, proxy_port, user_id=None, rdns=None):
super().__init__(proxy_host=proxy_host, proxy_port=proxy_port)
self._user_id = user_id
self._rdns = rdns
class HttpProxy(HttpProxyNegotiator, CurioProxyConnection):
def __init__(self, proxy_host, proxy_port, username=None, password=None):
super().__init__(proxy_host=proxy_host, proxy_port=proxy_port)
self._username = username
self._password = password
class Proxy(ProxyFactory):
types = {
ProxyType.SOCKS4: Socks4Proxy,
ProxyType.SOCKS5: Socks5Proxy,
ProxyType.HTTP: HttpProxy,
}
|