Browse Source

Update win_inet_pton 1.0.1 (934a852) → 1.1.0 (57e3558).

pull/1200/head
JackDandy 6 years ago
parent
commit
d2849776f5
  1. 1
      CHANGES.md
  2. 148
      lib/win_inet_pton/win_inet_pton.py

1
CHANGES.md

@ -15,6 +15,7 @@
* Update Six compatibility library 1.12.0 (d927b9e) to 1.12.0 (8da94b8) * Update Six compatibility library 1.12.0 (d927b9e) to 1.12.0 (8da94b8)
* Update Tornado Web Server 5.1.1 (cc2cf07) to 5.1.1 (a99f1471) * Update Tornado Web Server 5.1.1 (cc2cf07) to 5.1.1 (a99f1471)
* Update unidecode module 1.0.22 (578cdb9) to 1.0.22 (a5045ab) * Update unidecode module 1.0.22 (578cdb9) to 1.0.22 (a5045ab)
* Update win_inet_pton 1.0.1 (934a852) to 1.1.0 (57e3558)
[develop changelog] [develop changelog]

148
lib/win_inet_pton/win_inet_pton.py

@ -4,81 +4,123 @@
# commercial or non-commercial, and by any means. # commercial or non-commercial, and by any means.
import socket import socket
import ctypes
import os import os
import sys
def inject_into_socket():
import ctypes
class in_addr(ctypes.Structure):
_fields_ = [("S_addr", ctypes.c_ubyte * 4)]
class in6_addr(ctypes.Structure):
_fields_ = [("Byte", ctypes.c_ubyte * 16)]
if hasattr(ctypes, "windll"):
# InetNtopW(
# INT family,
# const VOID *pAddr,
# PWSTR pStringBuf,
# size_t StringBufSize
# ) -> PCWSTR
InetNtopW = ctypes.windll.ws2_32.InetNtopW
class sockaddr(ctypes.Structure): # InetPtonW(
_fields_ = [("sa_family", ctypes.c_short), # INT family,
("__pad1", ctypes.c_ushort), # PCWSTR pszAddrString,
("ipv4_addr", ctypes.c_byte * 4), # PVOID pAddrBuf
("ipv6_addr", ctypes.c_byte * 16), # ) -> INT
("__pad2", ctypes.c_ulong)] InetPtonW = ctypes.windll.ws2_32.InetPtonW
if hasattr(ctypes, 'windll'): # WSAGetLastError() -> INT
WSAStringToAddressA = ctypes.windll.ws2_32.WSAStringToAddressA WSAGetLastError = ctypes.windll.ws2_32.WSAGetLastError
WSAAddressToStringA = ctypes.windll.ws2_32.WSAAddressToStringA
else: else:
def not_windows(): def not_windows():
raise SystemError( raise SystemError("Invalid platform. ctypes.windll must be available.")
"Invalid platform. ctypes.windll must be available."
)
WSAStringToAddressA = not_windows
WSAAddressToStringA = not_windows
InetNtopW = not_windows
InetPtonW = not_windows
WSAGetLastError = not_windows
def inet_pton(address_family, ip_string): def inet_pton(address_family, ip_string):
addr = sockaddr() if sys.version_info[0] > 2 and isinstance(ip_string, bytes):
addr.sa_family = address_family raise TypeError("inet_pton() argument 2 must be str, not bytes")
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: if address_family == socket.AF_INET:
return ctypes.string_at(addr.ipv4_addr, 4) family = 2
if address_family == socket.AF_INET6: addr = in_addr()
return ctypes.string_at(addr.ipv6_addr, 16) elif address_family == socket.AF_INET6:
family = 23
addr = in6_addr()
else:
raise OSError("unknown address family")
raise socket.error('unknown address family') ip_string = ctypes.c_wchar_p(ip_string)
ret = InetPtonW(ctypes.c_int(family), ip_string, ctypes.byref(addr))
if ret == 1:
if address_family == socket.AF_INET:
return ctypes.string_at(addr.S_addr, 4)
else:
return ctypes.string_at(addr.Byte, 16)
elif ret == 0:
raise socket.error("illegal IP address string passed to inet_pton")
else:
err = WSAGetLastError()
if err == 10047:
e = socket.error("unknown address family")
elif err == 10014:
e = OSError("bad address")
else:
e = OSError("unknown error from inet_ntop")
e.errno = err
raise e
def inet_ntop(address_family, packed_ip): 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 address_family == socket.AF_INET:
if len(packed_ip) != ctypes.sizeof(addr.ipv4_addr): addr = in_addr()
raise socket.error('packed IP wrong length for inet_ntoa') if len(packed_ip) != ctypes.sizeof(addr.S_addr):
ctypes.memmove(addr.ipv4_addr, packed_ip, 4) raise ValueError("packed IP wrong length for inet_ntop")
ctypes.memmove(addr.S_addr, packed_ip, 4)
buffer_len = 16
family = 2
elif address_family == socket.AF_INET6: elif address_family == socket.AF_INET6:
if len(packed_ip) != ctypes.sizeof(addr.ipv6_addr): addr = in6_addr()
raise socket.error('packed IP wrong length for inet_ntoa') if len(packed_ip) != ctypes.sizeof(addr.Byte):
ctypes.memmove(addr.ipv6_addr, packed_ip, 16) raise ValueError("packed IP wrong length for inet_ntop")
ctypes.memmove(addr.Byte, packed_ip, 16)
buffer_len = 46
family = 23
else: else:
raise socket.error('unknown address family') raise ValueError("unknown address family")
buffer = ctypes.create_unicode_buffer(buffer_len)
if WSAAddressToStringA( ret = InetNtopW(
ctypes.c_int(family),
ctypes.byref(addr), ctypes.byref(addr),
addr_size, ctypes.byref(buffer),
None, ctypes.sizeof(buffer),
ip_string, )
ctypes.byref(ip_string_size) if ret is None:
) != 0: err = WSAGetLastError()
raise socket.error(ctypes.FormatError()) if err == 10047:
e = ValueError("unknown address family")
else:
e = OSError("unknown error from inet_ntop")
e.errno = err
return ip_string[:ip_string_size.value - 1] return ctypes.wstring_at(buffer, buffer_len).rstrip("\x00")
# Adding our two functions to the socket library # Adding our two functions to the socket library
if os.name == 'nt':
socket.inet_pton = inet_pton socket.inet_pton = inet_pton
socket.inet_ntop = inet_ntop socket.inet_ntop = inet_ntop
if os.name == "nt" and not hasattr(socket, "inet_pton"):
inject_into_socket()

Loading…
Cancel
Save