_inet.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. # coding: utf-8
  2. from __future__ import unicode_literals, division, absolute_import, print_function
  3. import socket
  4. import struct
  5. from ._errors import unwrap
  6. from ._types import byte_cls, bytes_to_list, str_cls, type_name
  7. def inet_ntop(address_family, packed_ip):
  8. """
  9. Windows compatiblity shim for socket.inet_ntop().
  10. :param address_family:
  11. socket.AF_INET for IPv4 or socket.AF_INET6 for IPv6
  12. :param packed_ip:
  13. A byte string of the network form of an IP address
  14. :return:
  15. A unicode string of the IP address
  16. """
  17. if address_family not in set([socket.AF_INET, socket.AF_INET6]):
  18. raise ValueError(unwrap(
  19. '''
  20. address_family must be socket.AF_INET (%s) or socket.AF_INET6 (%s),
  21. not %s
  22. ''',
  23. repr(socket.AF_INET),
  24. repr(socket.AF_INET6),
  25. repr(address_family)
  26. ))
  27. if not isinstance(packed_ip, byte_cls):
  28. raise TypeError(unwrap(
  29. '''
  30. packed_ip must be a byte string, not %s
  31. ''',
  32. type_name(packed_ip)
  33. ))
  34. required_len = 4 if address_family == socket.AF_INET else 16
  35. if len(packed_ip) != required_len:
  36. raise ValueError(unwrap(
  37. '''
  38. packed_ip must be %d bytes long - is %d
  39. ''',
  40. required_len,
  41. len(packed_ip)
  42. ))
  43. if address_family == socket.AF_INET:
  44. return '%d.%d.%d.%d' % tuple(bytes_to_list(packed_ip))
  45. octets = struct.unpack(b'!HHHHHHHH', packed_ip)
  46. runs_of_zero = {}
  47. longest_run = 0
  48. zero_index = None
  49. for i, octet in enumerate(octets + (-1,)):
  50. if octet != 0:
  51. if zero_index is not None:
  52. length = i - zero_index
  53. if length not in runs_of_zero:
  54. runs_of_zero[length] = zero_index
  55. longest_run = max(longest_run, length)
  56. zero_index = None
  57. elif zero_index is None:
  58. zero_index = i
  59. hexed = [hex(o)[2:] for o in octets]
  60. if longest_run < 2:
  61. return ':'.join(hexed)
  62. zero_start = runs_of_zero[longest_run]
  63. zero_end = zero_start + longest_run
  64. return ':'.join(hexed[:zero_start]) + '::' + ':'.join(hexed[zero_end:])
  65. def inet_pton(address_family, ip_string):
  66. """
  67. Windows compatiblity shim for socket.inet_ntop().
  68. :param address_family:
  69. socket.AF_INET for IPv4 or socket.AF_INET6 for IPv6
  70. :param ip_string:
  71. A unicode string of an IP address
  72. :return:
  73. A byte string of the network form of the IP address
  74. """
  75. if address_family not in set([socket.AF_INET, socket.AF_INET6]):
  76. raise ValueError(unwrap(
  77. '''
  78. address_family must be socket.AF_INET (%s) or socket.AF_INET6 (%s),
  79. not %s
  80. ''',
  81. repr(socket.AF_INET),
  82. repr(socket.AF_INET6),
  83. repr(address_family)
  84. ))
  85. if not isinstance(ip_string, str_cls):
  86. raise TypeError(unwrap(
  87. '''
  88. ip_string must be a unicode string, not %s
  89. ''',
  90. type_name(ip_string)
  91. ))
  92. if address_family == socket.AF_INET:
  93. octets = ip_string.split('.')
  94. error = len(octets) != 4
  95. if not error:
  96. ints = []
  97. for o in octets:
  98. o = int(o)
  99. if o > 255 or o < 0:
  100. error = True
  101. break
  102. ints.append(o)
  103. if error:
  104. raise ValueError(unwrap(
  105. '''
  106. ip_string must be a dotted string with four integers in the
  107. range of 0 to 255, got %s
  108. ''',
  109. repr(ip_string)
  110. ))
  111. return struct.pack(b'!BBBB', *ints)
  112. error = False
  113. omitted = ip_string.count('::')
  114. if omitted > 1:
  115. error = True
  116. elif omitted == 0:
  117. octets = ip_string.split(':')
  118. error = len(octets) != 8
  119. else:
  120. begin, end = ip_string.split('::')
  121. begin_octets = begin.split(':')
  122. end_octets = end.split(':')
  123. missing = 8 - len(begin_octets) - len(end_octets)
  124. octets = begin_octets + (['0'] * missing) + end_octets
  125. if not error:
  126. ints = []
  127. for o in octets:
  128. o = int(o, 16)
  129. if o > 65535 or o < 0:
  130. error = True
  131. break
  132. ints.append(o)
  133. return struct.pack(b'!HHHHHHHH', *ints)
  134. raise ValueError(unwrap(
  135. '''
  136. ip_string must be a valid ipv6 string, got %s
  137. ''',
  138. repr(ip_string)
  139. ))