From 9fb41f3e80256ba0cffb9af72930a1efbb140e48 Mon Sep 17 00:00:00 2001 From: nibrag Date: Sat, 7 May 2016 00:48:21 +0300 Subject: [PATCH] A more meaningful error handling --- aiosocks/__init__.py | 18 +++++++++++++----- aiosocks/connector.py | 18 ++++++++++++++---- aiosocks/errors.py | 4 ++++ aiosocks/protocols.py | 12 ++++++------ 4 files changed, 37 insertions(+), 15 deletions(-) diff --git a/aiosocks/__init__.py b/aiosocks/__init__.py index 0743677..2a6ac95 100644 --- a/aiosocks/__init__.py +++ b/aiosocks/__init__.py @@ -7,7 +7,7 @@ __version__ = '0.1.1' __all__ = ('Socks4Protocol', 'Socks5Protocol', 'Socks4Auth', 'Socks5Auth', 'Socks4Addr', 'Socks5Addr', 'SocksError', - 'NoAcceptableAuthMethods', 'LoginAuthenticationFailed', + 'NoAcceptableAuthMethods', 'LoginAuthenticationFailed', 'SocksConnectionError', 'InvalidServerVersion', 'InvalidServerReply', 'create_connection') @@ -46,11 +46,19 @@ async def create_connection(protocol_factory, proxy, proxy_auth, dst, *, remote_ proxy=proxy, proxy_auth=proxy_auth, dst=dst, remote_resolve=remote_resolve, loop=loop) - transport, protocol = await loop.create_connection( - socks_factory, proxy.host, proxy.port, ssl=ssl, family=family, proto=proto, - flags=flags, sock=sock, local_addr=local_addr, server_hostname=server_hostname) + try: + transport, protocol = await loop.create_connection( + socks_factory, proxy.host, proxy.port, ssl=ssl, family=family, proto=proto, + flags=flags, sock=sock, local_addr=local_addr, server_hostname=server_hostname) + except OSError as exc: + raise SocksConnectionError('[Errno %s] Can not connect to proxy %s:%d [%s]' % + (exc.errno, proxy.host, proxy.port, exc.strerror)) from exc - await protocol.negotiate_done() + try: + await protocol.negotiate_done() + except SocksError as exc: + raise SocksError('Can not connect to %s:%s [%s]' % + (dst[0], dst[1], exc)) sock = transport.get_extra_info('socket') diff --git a/aiosocks/connector.py b/aiosocks/connector.py index e04105f..339a018 100644 --- a/aiosocks/connector.py +++ b/aiosocks/connector.py @@ -1,4 +1,9 @@ +import socket + import aiohttp +import ipaddress +from aiohttp.errors import ProxyConnectionError +from .errors import SocksError, SocksConnectionError from . import create_connection __all__ = ('SocksConnector',) @@ -46,9 +51,14 @@ class SocksConnector(aiohttp.TCPConnector): proto=hinfo['proto'], flags=hinfo['flags'], local_addr=self._local_addr) return transp, proto - except OSError as e: + except (OSError, SocksError, SocksConnectionError) as e: exc = e else: - raise aiohttp.ClientOSError(exc.errno, - 'Can not connect to %s:%s [%s]' % - (req.host, req.port, exc.strerror)) from exc + if isinstance(exc, SocksConnectionError): + raise ProxyConnectionError(*exc.args) + if isinstance(exc, SocksError): + raise exc + else: + raise aiohttp.ClientOSError(exc.errno, + 'Can not connect to %s:%s [%s]' % + (req.host, req.port, exc.strerror)) from exc diff --git a/aiosocks/errors.py b/aiosocks/errors.py index e106c17..aaf1edf 100644 --- a/aiosocks/errors.py +++ b/aiosocks/errors.py @@ -16,3 +16,7 @@ class InvalidServerVersion(SocksError): class InvalidServerReply(SocksError): pass + + +class SocksConnectionError(OSError): + pass diff --git a/aiosocks/protocols.py b/aiosocks/protocols.py index 541dda7..99fc3f7 100644 --- a/aiosocks/protocols.py +++ b/aiosocks/protocols.py @@ -106,7 +106,7 @@ class Socks4Protocol(SocksProtocol): raise InvalidServerReply('SOCKS4 proxy server sent invalid data') if resp[1] != c.SOCKS4_GRANTED: error = c.SOCKS4_ERRORS.get(resp[1], 'Unknown error') - raise SocksError('{0:#04x}: {1}'.format(resp[1], error)) + raise SocksError('[Errno {0:#04x}]: {1}'.format(resp[1], error)) binded = socket.inet_ntoa(resp[4:]), struct.unpack('>H', resp[2:4])[0] return (host, port), binded @@ -138,7 +138,7 @@ class Socks5Protocol(SocksProtocol): chosen_auth = await self.read_response(2) if chosen_auth[0] != c.SOCKS_VER5: - raise InvalidServerVersion + raise InvalidServerVersion('SOCKS5 proxy server sent invalid version') if chosen_auth[1] == c.SOCKS5_AUTH_UNAME_PWD: req = [0x01, chr(len(self._auth.login)).encode(), self._auth.login, @@ -149,11 +149,11 @@ class Socks5Protocol(SocksProtocol): if auth_status[0] != 0x01: raise InvalidServerReply('SOCKS5 proxy server sent invalid data') if auth_status[1] != c.SOCKS5_GRANTED: - raise LoginAuthenticationFailed + raise LoginAuthenticationFailed('SOCKS5 authentication failed') # offered auth methods rejected elif chosen_auth[1] != c.SOCKS5_AUTH_ANONYMOUS: if chosen_auth[1] == c.SOCKS5_AUTH_NO_ACCEPTABLE_METHODS: - raise NoAcceptableAuthMethods + raise NoAcceptableAuthMethods('All offered SOCKS5 authentication methods were rejected') else: raise InvalidServerReply('SOCKS5 proxy server sent invalid data') @@ -165,10 +165,10 @@ class Socks5Protocol(SocksProtocol): resp = await self.read_response(3) if resp[0] != c.SOCKS_VER5: - raise InvalidServerVersion + raise InvalidServerVersion('SOCKS5 proxy server sent invalid version') if resp[1] != c.SOCKS5_GRANTED: error = c.SOCKS5_ERRORS.get(resp[1], 'Unknown error') - raise SocksError('{0:#04x}: {1}'.format(resp[1], error)) + raise SocksError('[Errno {0:#04x}]: {1}'.format(resp[1], error)) binded = await self.read_address()