From 1144f2898211ca7fb0578b31306f3bd41e261586 Mon Sep 17 00:00:00 2001 From: shortcutme Date: Sat, 8 Apr 2017 17:22:00 +0200 Subject: [PATCH] Rev2027, Rollback PySocks as it does not works well with Tor/gevent --- src/Config.py | 2 +- src/lib/PySocks/README.md | 54 ++-- src/lib/PySocks/setup.py | 5 +- src/lib/PySocks/socks.py | 232 ++++-------------- src/lib/PySocks/win_inet_pton/LICENSE | 4 - src/lib/PySocks/win_inet_pton/README | 29 --- src/lib/PySocks/win_inet_pton/__init__.py | 1 - src/lib/PySocks/win_inet_pton/setup.py | 20 -- .../PySocks/win_inet_pton/win_inet_pton.py | 84 ------- 9 files changed, 81 insertions(+), 350 deletions(-) delete mode 100644 src/lib/PySocks/win_inet_pton/LICENSE delete mode 100644 src/lib/PySocks/win_inet_pton/README delete mode 100644 src/lib/PySocks/win_inet_pton/__init__.py delete mode 100644 src/lib/PySocks/win_inet_pton/setup.py delete mode 100644 src/lib/PySocks/win_inet_pton/win_inet_pton.py diff --git a/src/Config.py b/src/Config.py index 831430f5..c2f1fee1 100644 --- a/src/Config.py +++ b/src/Config.py @@ -10,7 +10,7 @@ class Config(object): def __init__(self, argv): self.version = "0.5.3" - self.rev = 2026 + self.rev = 2027 self.argv = argv self.action = None self.config_file = "zeronet.conf" diff --git a/src/lib/PySocks/README.md b/src/lib/PySocks/README.md index f67a0264..65419240 100644 --- a/src/lib/PySocks/README.md +++ b/src/lib/PySocks/README.md @@ -1,7 +1,7 @@ PySocks ======= -Updated and semi-actively maintained version of [SocksiPy](http://socksipy.sourceforge.net/), with bug fixes and extra features. +Updated version of SocksiPy. Many old bugs fixed, and overall code cleanup. Acts as a drop-in replacement to the socket module. @@ -10,10 +10,23 @@ Acts as a drop-in replacement to the socket module. Features ======== -* SOCKS proxy client for Python 2.6 - 3.x -* TCP and UDP both supported -* HTTP proxy client included but not supported or recommended (you should use urllib2's or requests' own HTTP proxy interface) -* urllib2 handler included. `pip install` / `setup.py install` will automatically install the `sockshandler` module. +* Fully supports Python 2.6 - 3.4 + +* UDP support + +* SocksiPyHandler, courtesy e000, was also added as an example of how this module can be used with urllib2. See example code in sockshandler.py. `pip install` and `setup.py install` will automatically install the `sockshandler` module. + +* Bugs in the original SocksiPy were fixed, including two that could lead to infinite hanging when communicating with bad proxy servers. + +* urllib3, which powers the requests module, is working on integrating SOCKS proxy support based on this branch + +* `SOCKS5`, `SOCKS4`, and `HTTP` are now aliases for `PROXY_TYPE_SOCKS5`, `PROXY_TYPE_SOCKS4`, and `PROXY_TYPE_HTTP` + +* Tests added + +* Various style and performance improvements; codebase simplified + +* Actively maintained Installation ============ @@ -30,18 +43,18 @@ Alternatively, include just `socks.py` in your project. -------------------------------------------- -*Warning:* PySocks/SocksiPy only supports HTTP proxies that use CONNECT tunneling. Certain HTTP proxies may not work with this library. If you wish to use HTTP (not SOCKS) proxies, it is recommended that you rely on your HTTP client's native proxy support (`proxies` dict for `requests`, or `urllib2.ProxyHandler` for `urllib2`) instead. +*Warning:* PySocks/SocksiPy only supports HTTP proxies that use CONNECT tunneling. Certain HTTP proxies may not work with this library. If you wish to use HTTP proxies (and not SOCKS proxies), it is recommended that you rely on your HTTP client's native proxy support (`proxies` dict for `requests`, or `urllib2.ProxyHandler` for `urllib2`) instead. -------------------------------------------- Usage ===== -## socks.socksocket ## +## Example ## import socks - s = socks.socksocket() # Same API as socket.socket in the standard lib + s = socks.socksocket() s.set_proxy(socks.SOCKS5, "localhost") # SOCKS4 and SOCKS5 use port 1080 by default # Or @@ -50,35 +63,23 @@ Usage s.set_proxy(socks.HTTP, "5.5.5.5", 8888) # Can be treated identical to a regular socket object - s.connect(("www.somesite.com", 80)) - s.sendall("GET / HTTP/1.1 ...") + s.connect(("www.test.com", 80)) + s.sendall("GET / ...") print s.recv(4096) -## Monkeypatching ## To monkeypatch the entire standard library with a single default proxy: - import urllib2 import socket import socks + import urllib2 socks.set_default_proxy(socks.SOCKS5, "localhost") socket.socket = socks.socksocket - urllib2.urlopen("http://www.somesite.com/") # All requests will pass through the SOCKS proxy + urllib2.urlopen("http://...") # All requests will pass through the SOCKS proxy -Note that monkeypatching may not work for all standard modules or for all third party modules, and generally isn't recommended. Monkeypatching is usually an anti-pattern in Python. - -## urllib2 Handler ## - -Example use case with the `sockshandler` urllib2 handler. Note that you must import both `socks` and `sockshandler`, as the handler is its own module separate from PySocks. The module is included in the PyPI package. - - import urllib2 - import socks - from sockshandler import SocksiPyHandler - - opener = urllib2.build_opener(SocksiPyHandler(socks.SOCKS5, "127.0.0.1", 9050)) - print opener.open("http://www.somesite.com/") # All requests made by the opener will pass through the SOCKS proxy +Note that monkeypatching may not work for all standard modules or for all third party modules, and generally isn't recommended. -------------------------------------------- @@ -86,7 +87,7 @@ Original SocksiPy README attached below, amended to reflect API changes. -------------------------------------------- -SocksiPy +SocksiPy - version 1.5.0 A Python SOCKS module. @@ -276,7 +277,6 @@ class `HTTPError` - This will be raised for HTTP errors. The message will contai the HTTP status code and provided error message. After establishing the connection, the object behaves like a standard socket. - Methods like `makefile()` and `settimeout()` should behave just like regular sockets. Call the `close()` method to close the connection. diff --git a/src/lib/PySocks/setup.py b/src/lib/PySocks/setup.py index d864fcc0..9db0f3d2 100644 --- a/src/lib/PySocks/setup.py +++ b/src/lib/PySocks/setup.py @@ -1,7 +1,7 @@ #!/usr/bin/env python -from setuptools import setup +from distutils.core import setup -VERSION = "1.6.7" +VERSION = "1.5.3" setup( name = "PySocks", @@ -14,3 +14,4 @@ setup( keywords = ["socks", "proxy"], py_modules=["socks", "sockshandler"] ) + diff --git a/src/lib/PySocks/socks.py b/src/lib/PySocks/socks.py index 0c91ea6a..ad1e9780 100644 --- a/src/lib/PySocks/socks.py +++ b/src/lib/PySocks/socks.py @@ -1,5 +1,6 @@ """ SocksiPy - Python SOCKS module. +Version 1.5.3 Copyright 2006 Dan-Haim. All rights reserved. @@ -51,28 +52,14 @@ Modifications made by Anorov (https://github.com/Anorov) -Various small bug fixes """ -__version__ = "1.6.7" +__version__ = "1.5.3" import socket import struct from errno import EOPNOTSUPP, EINVAL, EAGAIN from io import BytesIO from os import SEEK_CUR -import os -import sys -import functools -import logging from collections import Callable -from base64 import b64encode - - -if os.name == "nt" and sys.version_info < (3, 0): - try: - import win_inet_pton - except ImportError: - raise ImportError("To run PySocks on Windows you must install win_inet_pton") - -log = logging.getLogger(__name__) PROXY_TYPE_SOCKS4 = SOCKS4 = 1 PROXY_TYPE_SOCKS5 = SOCKS5 = 2 @@ -83,25 +70,6 @@ PRINTABLE_PROXY_TYPES = dict(zip(PROXY_TYPES.values(), PROXY_TYPES.keys())) _orgsocket = _orig_socket = socket.socket - -def set_self_blocking(function): - - @functools.wraps(function) - def wrapper(*args, **kwargs): - self = args[0] - try: - _is_blocking = self.gettimeout() - if _is_blocking == 0: - self.setblocking(True) - return function(*args, **kwargs) - except Exception as e: - raise - finally: - # set orgin blcoking - if _is_blocking == 0: - self.setblocking(False) - return wrapper - class ProxyError(IOError): """ socket_err contains original socket.error exception. @@ -154,10 +122,7 @@ def set_default_proxy(proxy_type=None, addr=None, port=None, rdns=True, username username.encode() if username else None, password.encode() if password else None) -def setdefaultproxy(*args, **kwargs): - if 'proxytype' in kwargs: - kwargs['proxy_type'] = kwargs.pop('proxytype') - return set_default_proxy(*args, **kwargs) +setdefaultproxy = set_default_proxy def get_default_proxy(): """ @@ -182,10 +147,9 @@ def wrap_module(module): wrapmodule = wrap_module def create_connection(dest_pair, proxy_type=None, proxy_addr=None, - proxy_port=None, proxy_rdns=True, - proxy_username=None, proxy_password=None, - timeout=None, source_address=None, - socket_options=None): + proxy_port=None, proxy_username=None, + proxy_password=None, timeout=None, + source_address=None): """create_connection(dest_pair, *[, timeout], **proxy_args) -> socket object Like socket.create_connection(), but connects to proxy @@ -197,48 +161,14 @@ def create_connection(dest_pair, proxy_type=None, proxy_addr=None, source_address - tuple (host, port) for the socket to bind to as its source address before connecting (only for compatibility) """ - # Remove IPv6 brackets on the remote address and proxy address. - remote_host, remote_port = dest_pair - if remote_host.startswith('['): - remote_host = remote_host.strip('[]') - if proxy_addr and proxy_addr.startswith('['): - proxy_addr = proxy_addr.strip('[]') - - err = None - - # Allow the SOCKS proxy to be on IPv4 or IPv6 addresses. - for r in socket.getaddrinfo(proxy_addr, proxy_port, 0, socket.SOCK_STREAM): - family, socket_type, proto, canonname, sa = r - sock = None - try: - sock = socksocket(family, socket_type, proto) - - if socket_options: - for opt in socket_options: - sock.setsockopt(*opt) - - if isinstance(timeout, (int, float)): - sock.settimeout(timeout) - - if proxy_type: - sock.set_proxy(proxy_type, proxy_addr, proxy_port, proxy_rdns, - proxy_username, proxy_password) - if source_address: - sock.bind(source_address) - - sock.connect((remote_host, remote_port)) - return sock - - except (socket.error, ProxyConnectionError) as e: - err = e - if sock: - sock.close() - sock = None - - if err: - raise err - - raise socket.error("gai returned empty list.") + sock = socksocket() + if isinstance(timeout, (int, float)): + sock.settimeout(timeout) + if proxy_type is not None: + sock.set_proxy(proxy_type, proxy_addr, proxy_port, + proxy_username, proxy_password) + sock.connect(dest_pair) + return sock class _BaseSocket(socket.socket): """Allows Python 2's "delegated" methods such as send() to be overridden @@ -277,12 +207,12 @@ class socksocket(_BaseSocket): default_proxy = None - def __init__(self, family=socket.AF_INET, type=socket.SOCK_STREAM, proto=0, *args, **kwargs): + def __init__(self, family=socket.AF_INET, type=socket.SOCK_STREAM, proto=0, _sock=None): if type not in (socket.SOCK_STREAM, socket.SOCK_DGRAM): msg = "Socket type must be stream or datagram, not {!r}" raise ValueError(msg.format(type)) - super(socksocket, self).__init__(family, type, proto, *args, **kwargs) + _BaseSocket.__init__(self, family, type, proto, _sock) self._proxyconn = None # TCP connection to keep UDP relay alive if self.default_proxy: @@ -292,8 +222,6 @@ class socksocket(_BaseSocket): self.proxy_sockname = None self.proxy_peername = None - self._timeout = None - def _readall(self, file, count): """ Receive EXACTLY the number of bytes requested from the file object. @@ -307,24 +235,6 @@ class socksocket(_BaseSocket): data += d return data - def settimeout(self, timeout): - self._timeout = timeout - try: - # test if we're connected, if so apply timeout - peer = self.get_proxy_peername() - super(socksocket, self).settimeout(self._timeout) - except socket.error: - pass - - def gettimeout(self): - return self._timeout - - def setblocking(self, v): - if v: - self.settimeout(None) - else: - self.settimeout(0.0) - def set_proxy(self, proxy_type=None, addr=None, port=None, rdns=True, username=None, password=None): """set_proxy(proxy_type, addr[, port[, rdns[, username[, password]]]]) Sets the proxy to be used. @@ -347,10 +257,7 @@ class socksocket(_BaseSocket): username.encode() if username else None, password.encode() if password else None) - def setproxy(self, *args, **kwargs): - if 'proxytype' in kwargs: - kwargs['proxy_type'] = kwargs.pop('proxytype') - return self.set_proxy(*args, **kwargs) + setproxy = set_proxy def bind(self, *pos, **kw): """ @@ -366,7 +273,7 @@ class socksocket(_BaseSocket): if proxy_type != SOCKS5: msg = "UDP only supported by SOCKS5 proxy type" raise socket.error(EOPNOTSUPP, msg) - super(socksocket, self).bind(*pos, **kw) + _BaseSocket.bind(self, *pos, **kw) # Need to specify actual local port because # some relays drop packets if a port of zero is specified. @@ -385,13 +292,12 @@ class socksocket(_BaseSocket): # but some proxies return a private IP address (10.x.y.z) host, _ = proxy _, port = relay - super(socksocket, self).connect((host, port)) - super(socksocket, self).settimeout(self._timeout) + _BaseSocket.connect(self, (host, port)) self.proxy_sockname = ("0.0.0.0", 0) # Unknown def sendto(self, bytes, *args, **kwargs): if self.type != socket.SOCK_DGRAM: - return super(socksocket, self).sendto(bytes, *args, **kwargs) + return _BaseSocket.sendto(self, bytes, *args, **kwargs) if not self._proxyconn: self.bind(("", 0)) @@ -405,23 +311,23 @@ class socksocket(_BaseSocket): header.write(STANDALONE) self._write_SOCKS5_address(address, header) - sent = super(socksocket, self).send(header.getvalue() + bytes, *flags, **kwargs) + sent = _BaseSocket.send(self, header.getvalue() + bytes, *flags, **kwargs) return sent - header.tell() def send(self, bytes, flags=0, **kwargs): if self.type == socket.SOCK_DGRAM: return self.sendto(bytes, flags, self.proxy_peername, **kwargs) else: - return super(socksocket, self).send(bytes, flags, **kwargs) + return _BaseSocket.send(self, bytes, flags, **kwargs) def recvfrom(self, bufsize, flags=0): if self.type != socket.SOCK_DGRAM: - return super(socksocket, self).recvfrom(bufsize, flags) + return _BaseSocket.recvfrom(self, bufsize, flags) if not self._proxyconn: self.bind(("", 0)) - buf = BytesIO(super(socksocket, self).recv(bufsize + 1024, flags)) - buf.seek(2, SEEK_CUR) + buf = BytesIO(_BaseSocket.recv(self, bufsize, flags)) + buf.seek(+2, SEEK_CUR) frag = buf.read(1) if ord(frag): raise NotImplementedError("Received UDP packet fragment") @@ -432,7 +338,7 @@ class socksocket(_BaseSocket): if fromhost != peerhost or peerport not in (0, fromport): raise socket.error(EAGAIN, "Packet filtered") - return (buf.read(bufsize), (fromhost, fromport)) + return (buf.read(), (fromhost, fromport)) def recv(self, *pos, **kw): bytes, _ = self.recvfrom(*pos, **kw) @@ -441,7 +347,7 @@ class socksocket(_BaseSocket): def close(self): if self._proxyconn: self._proxyconn.close() - return super(socksocket, self).close() + return _BaseSocket.close(self) def get_proxy_sockname(self): """ @@ -455,7 +361,7 @@ class socksocket(_BaseSocket): """ Returns the IP and port number of the proxy. """ - return super(socksocket, self).getpeername() + return _BaseSocket.getpeername(self) getproxypeername = get_proxy_peername @@ -553,8 +459,6 @@ class socksocket(_BaseSocket): # Get the bound address/port bnd = self._read_SOCKS5_address(reader) - - super(socksocket, self).settimeout(self._timeout) return (resolved, bnd) finally: reader.close() @@ -567,38 +471,25 @@ class socksocket(_BaseSocket): """ host, port = addr proxy_type, _, _, rdns, username, password = self.proxy - family_to_byte = {socket.AF_INET: b"\x01", socket.AF_INET6: b"\x04"} # If the given destination address is an IP address, we'll - # use the IP address request even if remote resolving was specified. - # Detect whether the address is IPv4/6 directly. - for family in (socket.AF_INET, socket.AF_INET6): - try: - addr_bytes = socket.inet_pton(family, host) - file.write(family_to_byte[family] + addr_bytes) - host = socket.inet_ntop(family, addr_bytes) - file.write(struct.pack(">H", port)) - return host, port - except socket.error: - continue + # use the IPv4 address request even if remote resolving was specified. + try: + addr_bytes = socket.inet_aton(host) + file.write(b"\x01" + addr_bytes) + host = socket.inet_ntoa(addr_bytes) + except socket.error: + # Well it's not an IP number, so it's probably a DNS name. + if rdns: + # Resolve remotely + host_bytes = host.encode('idna') + file.write(b"\x03" + chr(len(host_bytes)).encode() + host_bytes) + else: + # Resolve locally + addr_bytes = socket.inet_aton(socket.gethostbyname(host)) + file.write(b"\x01" + addr_bytes) + host = socket.inet_ntoa(addr_bytes) - # Well it's not an IP number, so it's probably a DNS name. - if rdns: - # Resolve remotely - host_bytes = host.encode('idna') - file.write(b"\x03" + chr(len(host_bytes)).encode() + host_bytes) - else: - # Resolve locally - addresses = socket.getaddrinfo(host, port, socket.AF_UNSPEC, socket.SOCK_STREAM, socket.IPPROTO_TCP, socket.AI_ADDRCONFIG) - # We can't really work out what IP is reachable, so just pick the - # first. - target_addr = addresses[0] - family = target_addr[0] - host = target_addr[4][0] - - addr_bytes = socket.inet_pton(family, host) - file.write(family_to_byte[family] + addr_bytes) - host = socket.inet_ntop(family, addr_bytes) file.write(struct.pack(">H", port)) return host, port @@ -609,8 +500,6 @@ class socksocket(_BaseSocket): elif atyp == b"\x03": length = self._readall(file, 1) addr = self._readall(file, ord(length)) - elif atyp == b"\x04": - addr = socket.inet_ntop(socket.AF_INET6, self._readall(file, 16)) else: raise GeneralProxyError("SOCKS5 proxy server sent invalid data") @@ -686,17 +575,8 @@ class socksocket(_BaseSocket): # If we need to resolve locally, we do this now addr = dest_addr if rdns else socket.gethostbyname(dest_addr) - http_headers = [ - b"CONNECT " + addr.encode('idna') + b":" + str(dest_port).encode() + b" HTTP/1.1", - b"Host: " + dest_addr.encode('idna') - ] - - if username and password: - http_headers.append(b"Proxy-Authorization: basic " + b64encode(username + b":" + password)) - - http_headers.append(b"\r\n") - - self.sendall(b"\r\n".join(http_headers)) + self.sendall(b"CONNECT " + addr.encode('idna') + b":" + str(dest_port).encode() + + b" HTTP/1.1\r\n" + b"Host: " + dest_addr.encode('idna') + b"\r\n\r\n") # We just need the first line to check if the connection was successful fobj = self.makefile() @@ -736,7 +616,7 @@ class socksocket(_BaseSocket): HTTP: _negotiate_HTTP } - @set_self_blocking + def connect(self, dest_pair): """ Connects to the specified destination through a proxy. @@ -745,12 +625,6 @@ class socksocket(_BaseSocket): dest_pair - 2-tuple of (IP/hostname, port). """ - if len(dest_pair) != 2 or dest_pair[0].startswith("["): - # Probably IPv6, not supported -- raise an error, and hope - # Happy Eyeballs (RFC6555) makes sure at least the IPv4 - # connection works... - raise socket.error("PySocks doesn't support IPv6: %s" % str(dest_pair)) - dest_addr, dest_port = dest_pair if self.type == socket.SOCK_DGRAM: @@ -776,22 +650,17 @@ class socksocket(_BaseSocket): raise GeneralProxyError("Invalid destination-connection (host, port) pair") - # We set the timeout here so that we don't hang in connection or during - # negotiation. - super(socksocket, self).settimeout(self._timeout) - if proxy_type is None: # Treat like regular socket object self.proxy_peername = dest_pair - super(socksocket, self).settimeout(self._timeout) - super(socksocket, self).connect((dest_addr, dest_port)) + _BaseSocket.connect(self, (dest_addr, dest_port)) return proxy_addr = self._proxy_addr() try: - # Initial connection to proxy server. - super(socksocket, self).connect(proxy_addr) + # Initial connection to proxy server + _BaseSocket.connect(self, proxy_addr) except socket.error as error: # Error while connecting to proxy @@ -802,7 +671,6 @@ class socksocket(_BaseSocket): msg = "Error connecting to {0} proxy {1}".format(printable_type, proxy_server) - log.debug("%s due to: %s", msg, error) raise ProxyConnectionError(msg, error) else: diff --git a/src/lib/PySocks/win_inet_pton/LICENSE b/src/lib/PySocks/win_inet_pton/LICENSE deleted file mode 100644 index 3efb7f73..00000000 --- a/src/lib/PySocks/win_inet_pton/LICENSE +++ /dev/null @@ -1,4 +0,0 @@ -This software released into the public domain. Anyone is free to copy, -modify, publish, use, compile, sell, or distribute this software, -either in source code form or as a compiled binary, for any purpose, -commercial or non-commercial, and by any means. \ No newline at end of file diff --git a/src/lib/PySocks/win_inet_pton/README b/src/lib/PySocks/win_inet_pton/README deleted file mode 100644 index 2929a82e..00000000 --- a/src/lib/PySocks/win_inet_pton/README +++ /dev/null @@ -1,29 +0,0 @@ -win_inet_pton -============= - -Native inet_pton and inet_ntop implementation for Python on Windows (with ctypes). - - -Credit Where Credit Is Due --------------------------- - -This package is based on code that was originally written by https://github.com/nnemkin here: https://gist.github.com/nnemkin/4966028 - - -Why? ----- - -I needed this functionality in https://github.com/SerenitySoftwareLLC/cahoots to get full windows support. I figured, since there were other people looking for a solution to this on the net, I should publish it. - - -Usage ------ - -Just import it, and it will auto-add the methods to the socket library. - - -import win_inet_pton -import socket - -socket.inet_pton(...) -socket.inet_ntop(...) \ No newline at end of file diff --git a/src/lib/PySocks/win_inet_pton/__init__.py b/src/lib/PySocks/win_inet_pton/__init__.py deleted file mode 100644 index ae69f8f9..00000000 --- a/src/lib/PySocks/win_inet_pton/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from win_inet_pton import * \ No newline at end of file diff --git a/src/lib/PySocks/win_inet_pton/setup.py b/src/lib/PySocks/win_inet_pton/setup.py deleted file mode 100644 index 9d9a2fda..00000000 --- a/src/lib/PySocks/win_inet_pton/setup.py +++ /dev/null @@ -1,20 +0,0 @@ -from distutils.core import setup - -setup ( - name = 'win_inet_pton', - version = '1.0.1', - py_modules = ['win_inet_pton'], - url = 'https://github.com/hickeroar/win_inet_pton', - author = 'Ryan Vennell', - author_email = 'ryan.vennell@gmail.com', - description = 'Native inet_pton and inet_ntop implementation for Python on Windows (with ctypes).', - license = open('LICENSE', 'r').read(), - classifiers = [ - 'Development Status :: 5 - Production/Stable', - 'Intended Audience :: Developers', - 'Operating System :: OS Independent', - 'Operating System :: Microsoft :: Windows', - 'Programming Language :: Python :: 2.7', - 'Topic :: Utilities' - ] -) \ No newline at end of file diff --git a/src/lib/PySocks/win_inet_pton/win_inet_pton.py b/src/lib/PySocks/win_inet_pton/win_inet_pton.py deleted file mode 100644 index 12aaf46c..00000000 --- a/src/lib/PySocks/win_inet_pton/win_inet_pton.py +++ /dev/null @@ -1,84 +0,0 @@ -# This software released into the public domain. Anyone is free to copy, -# modify, publish, use, compile, sell, or distribute this software, -# either in source code form or as a compiled binary, for any purpose, -# commercial or non-commercial, and by any means. - -import socket -import ctypes -import os - - -class sockaddr(ctypes.Structure): - _fields_ = [("sa_family", ctypes.c_short), - ("__pad1", ctypes.c_ushort), - ("ipv4_addr", ctypes.c_byte * 4), - ("ipv6_addr", ctypes.c_byte * 16), - ("__pad2", ctypes.c_ulong)] - -if hasattr(ctypes, 'windll'): - WSAStringToAddressA = ctypes.windll.ws2_32.WSAStringToAddressA - WSAAddressToStringA = ctypes.windll.ws2_32.WSAAddressToStringA -else: - def not_windows(): - raise SystemError( - "Invalid platform. ctypes.windll must be available." - ) - WSAStringToAddressA = not_windows - WSAAddressToStringA = not_windows - - -def inet_pton(address_family, ip_string): - addr = sockaddr() - addr.sa_family = address_family - addr_size = ctypes.c_int(ctypes.sizeof(addr)) - - if WSAStringToAddressA( - ip_string, - address_family, - None, - ctypes.byref(addr), - ctypes.byref(addr_size) - ) != 0: - raise socket.error(ctypes.FormatError()) - - if address_family == socket.AF_INET: - return ctypes.string_at(addr.ipv4_addr, 4) - if address_family == socket.AF_INET6: - return ctypes.string_at(addr.ipv6_addr, 16) - - raise socket.error('unknown address family') - - -def inet_ntop(address_family, packed_ip): - addr = sockaddr() - addr.sa_family = address_family - addr_size = ctypes.c_int(ctypes.sizeof(addr)) - ip_string = ctypes.create_string_buffer(128) - ip_string_size = ctypes.c_int(ctypes.sizeof(ip_string)) - - if address_family == socket.AF_INET: - if len(packed_ip) != ctypes.sizeof(addr.ipv4_addr): - raise socket.error('packed IP wrong length for inet_ntoa') - ctypes.memmove(addr.ipv4_addr, packed_ip, 4) - elif address_family == socket.AF_INET6: - if len(packed_ip) != ctypes.sizeof(addr.ipv6_addr): - raise socket.error('packed IP wrong length for inet_ntoa') - ctypes.memmove(addr.ipv6_addr, packed_ip, 16) - else: - raise socket.error('unknown address family') - - if WSAAddressToStringA( - ctypes.byref(addr), - addr_size, - None, - ip_string, - ctypes.byref(ip_string_size) - ) != 0: - raise socket.error(ctypes.FormatError()) - - return ip_string[:ip_string_size.value - 1] - -# Adding our two functions to the socket library -if os.name == 'nt': - socket.inet_pton = inet_pton - socket.inet_ntop = inet_ntop