3 # Copyright 2007 Google Inc.
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
17 """IP address helper functions.
19 This file contains alternative implementations of the following functions
20 normally provided by the system:
35 from google
.appengine
.api
.remote_socket
._remote
_socket
_error
import *
47 return type(obj
).__name
__
50 def _LongestRun(seq
, value
):
51 """Finds the longest run (i.e. repeated adjacent values) of value in seq.
54 seq: A sequence to scan for runs.
55 value: A value to scan for in seq.
58 A tuple of the offset and run length for the longest run of value within
59 seq, or (-1, 0) if value does not occur within seq.
66 while i
+ run
< len(seq
) and seq
[i
+run
] == value
:
76 if text
[:2].lower() == '0x':
84 """ntohs(integer) -> integer
86 Convert a 16-bit integer from network to host byte order.
88 if sys
.byteorder
== 'big':
90 if not isinstance(integer
, (int, long)):
91 raise TypeError('an integer is required')
93 raise OverflowError("can't convert negative number to unsigned long")
94 if integer
>= (1<<16):
95 raise OverflowError('signed integer is greater than maximum')
97 ((integer
&0xff00)>>8)|
98 ((integer
&0x00ff)<<8))
102 """ntohl(integer) -> integer
104 Convert a 32-bit integer from network to host byte order.
106 if sys
.byteorder
== 'big':
108 if not isinstance(integer
, (int, long)):
109 raise TypeError('expected int/long, %s found' % _TypeName(integer
))
111 raise OverflowError('can\'t convert negative number to unsigned long')
112 if integer
>= (1<<32):
113 raise OverflowError('long int larger than 32 bits')
115 ((integer
&0xff000000)>>24)|
116 ((integer
&0x00ff0000)>>8)|
117 ((integer
&0x0000ff00)<<8)|
118 ((integer
&0x000000ff)<<24))
122 """htons(integer) -> integer
124 Convert a 16-bit integer from host to network byte order.
126 return ntohs(integer
)
130 """htonl(integer) -> integer
132 Convert a 32-bit integer from host to network byte order.
134 return ntohl(integer
)
137 def inet_aton(ip_string
):
138 """inet_aton(string) -> packed 32-bit IP representation
140 Convert an IP address in string format (123.45.67.89) to the 32-bit packed
141 binary format used in low-level network functions.
144 if not isinstance(ip_string
, basestring
):
145 raise error('inet_aton() argument 1 must be string, not %s' %
146 _TypeName(ip_string
))
150 parts
= [int(s
, _GetBase(s
)) for s
in ip_string
.split('.')]
151 assert len(parts
) >= 1 and len(parts
) <= 4
153 assert n
>= 0 and n
<= 0xff
155 ret |
= ((n
& 0xff) << bits
)
156 assert parts
[-1] >= 0 and parts
[-1] < (1 << bits
)
158 return struct
.pack('!L', ret
)
160 raise error('illegal IP address string passed to inet_aton')
163 def inet_ntoa(packed_ip
):
164 """inet_ntoa(packed_ip) -> ip_address_string
166 Convert an IP address from 32-bit packed binary format to string format
169 if not isinstance(packed_ip
, basestring
):
170 raise TypeError('inet_ntoa() argument 1 must be string or read-only '
171 'buffer, not %s' % _TypeName(packed_ip
))
172 if len(packed_ip
) != 4:
173 raise error('packed IP wrong length for inet_ntoa')
174 return '%u.%u.%u.%u' % struct
.unpack('4B', packed_ip
)
177 def inet_pton(af
, ip
):
178 """inet_pton(af, ip) -> packed IP address string
180 Convert an IP address from string format to a packed string suitable
181 for use with low-level network functions.
184 if not isinstance(af
, (int, long)):
185 raise TypeError('an integer is required')
186 if not isinstance(ip
, basestring
):
187 raise TypeError('inet_pton() argument 2 must be string, not %s' %
190 parts
= ip
.split('.')
192 raise error('illegal IP address string passed to inet_pton')
196 if not re
.match(r
'^(0|[1-9]\d*)$', part
) or int(part
) > 0xff:
197 raise error('illegal IP address string passed to inet_pton')
199 ret |
= ((int(part
) & 0xff) << bits
)
200 return struct
.pack('!L', ret
)
202 parts
= ip
.split(':')
205 ipv4_shorts
= struct
.unpack('!2H', inet_pton(AF_INET
, parts
[-1]))
206 parts
[-1:] = [hex(n
)[2:] for n
in ipv4_shorts
]
209 if len(parts
) == 1 or len(parts
) >= 8:
210 raise error('illegal IP address string passed to inet_pton')
212 idx
= parts
.index('')
213 count
= parts
.count('')
214 pad
= ['0']*(count
+(8-len(parts
)))
216 if count
== len(parts
) == 3:
218 elif count
== 2 and parts
[0:2] == ['', '']:
220 elif count
== 2 and parts
[-2:] == ['', '']:
223 parts
[idx
:idx
+1] = pad
225 raise error('illegal IP address string passed to inet_pton')
226 if (len(parts
) != 8 or
227 [x
for x
in parts
if not re
.match(r
'^[0-9A-Fa-f]{1,4}$', x
)]):
228 raise error('illegal IP address string passed to inet_pton')
229 return struct
.pack('!8H', *[int(x
, 16) for x
in parts
])
231 raise error(errno
.EAFNOSUPPORT
, os
.strerror(errno
.EAFNOSUPPORT
))
234 def inet_ntop(af
, packed_ip
):
235 """inet_ntop(af, packed_ip) -> string formatted IP address
237 Convert a packed IP address of the given family to string format.
239 if not isinstance(af
, (int, long)):
240 raise TypeError('an integer is required')
241 if not isinstance(packed_ip
, basestring
):
242 raise TypeError('inet_ntop() argument 2 must be string or read-only '
243 'buffer, not %s' % _TypeName(packed_ip
))
245 if len(packed_ip
) != 4:
246 raise ValueError('invalid length of packed IP address string')
247 return '%u.%u.%u.%u' % struct
.unpack('4B', packed_ip
)
249 if len(packed_ip
) != 16:
250 raise ValueError('invalid length of packed IP address string')
251 parts
= [hex(n
)[2:] for n
in struct
.unpack('!8H', packed_ip
)]
253 if (':'.join(parts
[:-2]) in ('0:0:0:0:0:0', '0:0:0:0:0:ffff') and
254 ':'.join(parts
) not in ('0:0:0:0:0:0:0:0', '0:0:0:0:0:0:0:1')):
255 parts
[-2:] = [inet_ntop(AF_INET
, packed_ip
[-4:])]
256 off
, run
= _LongestRun(parts
, '0')
261 if off
+ run
== len(parts
):
263 parts
[off
:off
+run
] = pad
264 return ':'.join(parts
)
266 raise ValueError('unknown address family %u' % af
)