Initial import to Tizen
[profile/ivi/python-twisted.git] / twisted / internet / test / _win32ifaces.py
1 # Copyright (c) Twisted Matrix Laboratories.
2 # See LICENSE for details.
3
4 """
5 Windows implementation of local network interface enumeration.
6 """
7
8 from socket import socket, AF_INET6, SOCK_STREAM
9 from ctypes import (
10     WinDLL, byref, create_string_buffer, c_int, c_void_p,
11     POINTER, Structure, cast, string_at)
12
13 WS2_32 = WinDLL('ws2_32')
14
15 SOCKET = c_int
16 DWORD = c_int
17 LPVOID = c_void_p
18 LPSOCKADDR = c_void_p
19 LPWSAPROTOCOL_INFO = c_void_p
20 LPTSTR = c_void_p
21 LPDWORD = c_void_p
22 LPWSAOVERLAPPED = c_void_p
23 LPWSAOVERLAPPED_COMPLETION_ROUTINE = c_void_p
24
25 # http://msdn.microsoft.com/en-us/library/ms741621(v=VS.85).aspx
26 # int WSAIoctl(
27 #         __in   SOCKET s,
28 #         __in   DWORD dwIoControlCode,
29 #         __in   LPVOID lpvInBuffer,
30 #         __in   DWORD cbInBuffer,
31 #         __out  LPVOID lpvOutBuffer,
32 #         __in   DWORD cbOutBuffer,
33 #         __out  LPDWORD lpcbBytesReturned,
34 #         __in   LPWSAOVERLAPPED lpOverlapped,
35 #         __in   LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
36 #       );
37 WSAIoctl = WS2_32.WSAIoctl
38 WSAIoctl.argtypes = [
39     SOCKET, DWORD, LPVOID, DWORD, LPVOID, DWORD, LPDWORD,
40     LPWSAOVERLAPPED, LPWSAOVERLAPPED_COMPLETION_ROUTINE]
41 WSAIoctl.restype = c_int
42
43 # http://msdn.microsoft.com/en-us/library/ms741516(VS.85).aspx
44 # INT WSAAPI WSAAddressToString(
45 #         __in      LPSOCKADDR lpsaAddress,
46 #         __in      DWORD dwAddressLength,
47 #         __in_opt  LPWSAPROTOCOL_INFO lpProtocolInfo,
48 #         __inout   LPTSTR lpszAddressString,
49 #         __inout   LPDWORD lpdwAddressStringLength
50 #       );
51 WSAAddressToString = WS2_32.WSAAddressToStringA
52 WSAAddressToString.argtypes = [
53     LPSOCKADDR, DWORD, LPWSAPROTOCOL_INFO, LPTSTR, LPDWORD]
54 WSAAddressToString.restype = c_int
55
56
57 SIO_ADDRESS_LIST_QUERY = 0x48000016
58 WSAEFAULT = 10014
59
60 class SOCKET_ADDRESS(Structure):
61     _fields_ = [('lpSockaddr', c_void_p),
62                 ('iSockaddrLength', c_int)]
63
64
65
66 def make_SAL(ln):
67     class SOCKET_ADDRESS_LIST(Structure):
68         _fields_ = [('iAddressCount', c_int),
69                     ('Address', SOCKET_ADDRESS * ln)]
70     return SOCKET_ADDRESS_LIST
71
72
73
74 def win32GetLinkLocalIPv6Addresses():
75     """
76     Return a list of strings in colon-hex format representing all the link local
77     IPv6 addresses available on the system, as reported by
78     I{WSAIoctl}/C{SIO_ADDRESS_LIST_QUERY}.
79     """
80     s = socket(AF_INET6, SOCK_STREAM)
81     size = 4096
82     retBytes = c_int()
83     for i in range(2):
84         buf = create_string_buffer(size)
85         ret = WSAIoctl(
86             s.fileno(),
87             SIO_ADDRESS_LIST_QUERY, 0, 0, buf, size, byref(retBytes), 0, 0)
88
89         # WSAIoctl might fail with WSAEFAULT, which means there was not enough
90         # space in the buffer we gave it.  There's no way to check the errno
91         # until Python 2.6, so we don't even try. :/ Maybe if retBytes is still
92         # 0 another error happened, though.
93         if ret and retBytes.value:
94             size = retBytes.value
95         else:
96             break
97
98     # If it failed, then we'll just have to give up.  Still no way to see why.
99     if ret:
100         raise RuntimeError("WSAIoctl failure")
101
102     addrList = cast(buf, POINTER(make_SAL(0)))
103     addrCount = addrList[0].iAddressCount
104     addrList = cast(buf, POINTER(make_SAL(addrCount)))
105
106     addressStringBufLength = 1024
107     addressStringBuf = create_string_buffer(addressStringBufLength)
108
109     retList = []
110     for i in range(addrList[0].iAddressCount):
111         retBytes.value = addressStringBufLength
112         addr = addrList[0].Address[i]
113         ret = WSAAddressToString(
114             addr.lpSockaddr, addr.iSockaddrLength, 0, addressStringBuf,
115             byref(retBytes))
116         if ret:
117             raise RuntimeError("WSAAddressToString failure")
118         retList.append(string_at(addressStringBuf))
119     return [addr for addr in retList if '%' in addr]