|
- # coding: utf-8
- from __future__ import unicode_literals, division, absolute_import, print_function
-
- import socket
- import struct
-
- from ._errors import unwrap
- from ._types import byte_cls, bytes_to_list, str_cls, type_name
-
-
- def inet_ntop(address_family, packed_ip):
- """
- Windows compatibility shim for socket.inet_ntop().
-
- :param address_family:
- socket.AF_INET for IPv4 or socket.AF_INET6 for IPv6
-
- :param packed_ip:
- A byte string of the network form of an IP address
-
- :return:
- A unicode string of the IP address
- """
-
- if address_family not in set([socket.AF_INET, socket.AF_INET6]):
- raise ValueError(unwrap(
- '''
- address_family must be socket.AF_INET (%s) or socket.AF_INET6 (%s),
- not %s
- ''',
- repr(socket.AF_INET),
- repr(socket.AF_INET6),
- repr(address_family)
- ))
-
- if not isinstance(packed_ip, byte_cls):
- raise TypeError(unwrap(
- '''
- packed_ip must be a byte string, not %s
- ''',
- type_name(packed_ip)
- ))
-
- required_len = 4 if address_family == socket.AF_INET else 16
- if len(packed_ip) != required_len:
- raise ValueError(unwrap(
- '''
- packed_ip must be %d bytes long - is %d
- ''',
- required_len,
- len(packed_ip)
- ))
-
- if address_family == socket.AF_INET:
- return '%d.%d.%d.%d' % tuple(bytes_to_list(packed_ip))
-
- octets = struct.unpack(b'!HHHHHHHH', packed_ip)
-
- runs_of_zero = {}
- longest_run = 0
- zero_index = None
- for i, octet in enumerate(octets + (-1,)):
- if octet != 0:
- if zero_index is not None:
- length = i - zero_index
- if length not in runs_of_zero:
- runs_of_zero[length] = zero_index
- longest_run = max(longest_run, length)
- zero_index = None
- elif zero_index is None:
- zero_index = i
-
- hexed = [hex(o)[2:] for o in octets]
-
- if longest_run < 2:
- return ':'.join(hexed)
-
- zero_start = runs_of_zero[longest_run]
- zero_end = zero_start + longest_run
-
- return ':'.join(hexed[:zero_start]) + '::' + ':'.join(hexed[zero_end:])
-
-
- def inet_pton(address_family, ip_string):
- """
- Windows compatibility shim for socket.inet_ntop().
-
- :param address_family:
- socket.AF_INET for IPv4 or socket.AF_INET6 for IPv6
-
- :param ip_string:
- A unicode string of an IP address
-
- :return:
- A byte string of the network form of the IP address
- """
-
- if address_family not in set([socket.AF_INET, socket.AF_INET6]):
- raise ValueError(unwrap(
- '''
- address_family must be socket.AF_INET (%s) or socket.AF_INET6 (%s),
- not %s
- ''',
- repr(socket.AF_INET),
- repr(socket.AF_INET6),
- repr(address_family)
- ))
-
- if not isinstance(ip_string, str_cls):
- raise TypeError(unwrap(
- '''
- ip_string must be a unicode string, not %s
- ''',
- type_name(ip_string)
- ))
-
- if address_family == socket.AF_INET:
- octets = ip_string.split('.')
- error = len(octets) != 4
- if not error:
- ints = []
- for o in octets:
- o = int(o)
- if o > 255 or o < 0:
- error = True
- break
- ints.append(o)
-
- if error:
- raise ValueError(unwrap(
- '''
- ip_string must be a dotted string with four integers in the
- range of 0 to 255, got %s
- ''',
- repr(ip_string)
- ))
-
- return struct.pack(b'!BBBB', *ints)
-
- error = False
- omitted = ip_string.count('::')
- if omitted > 1:
- error = True
- elif omitted == 0:
- octets = ip_string.split(':')
- error = len(octets) != 8
- else:
- begin, end = ip_string.split('::')
- begin_octets = begin.split(':')
- end_octets = end.split(':')
- missing = 8 - len(begin_octets) - len(end_octets)
- octets = begin_octets + (['0'] * missing) + end_octets
-
- if not error:
- ints = []
- for o in octets:
- o = int(o, 16)
- if o > 65535 or o < 0:
- error = True
- break
- ints.append(o)
-
- return struct.pack(b'!HHHHHHHH', *ints)
-
- raise ValueError(unwrap(
- '''
- ip_string must be a valid ipv6 string, got %s
- ''',
- repr(ip_string)
- ))
|