OLD | NEW |
| (Empty) |
1 # Copyright (c) 2008 Twisted Matrix Laboratories. | |
2 # See LICENSE for details. | |
3 | |
4 | |
5 ctypedef int size_t | |
6 ctypedef unsigned long HANDLE | |
7 ctypedef unsigned long SOCKET | |
8 ctypedef unsigned long DWORD | |
9 ctypedef unsigned long ULONG_PTR | |
10 ctypedef int BOOL | |
11 | |
12 cdef extern from 'io.h': | |
13 long _get_osfhandle(int filehandle) | |
14 | |
15 cdef extern from 'errno.h': | |
16 int errno | |
17 enum: | |
18 EBADF | |
19 | |
20 cdef extern from 'winsock2.h': | |
21 pass | |
22 | |
23 cdef extern from 'windows.h': | |
24 ctypedef struct OVERLAPPED: | |
25 pass | |
26 HANDLE CreateIoCompletionPort(HANDLE fileHandle, HANDLE existing, ULONG_PTR
key, DWORD numThreads) | |
27 BOOL GetQueuedCompletionStatus(HANDLE port, DWORD *bytes, ULONG_PTR *key, OV
ERLAPPED **ov, DWORD timeout) | |
28 BOOL PostQueuedCompletionStatus(HANDLE port, DWORD bytes, ULONG_PTR key, OVE
RLAPPED *ov) | |
29 DWORD GetLastError() | |
30 BOOL CloseHandle(HANDLE h) | |
31 enum: | |
32 INVALID_HANDLE_VALUE | |
33 void DebugBreak() | |
34 | |
35 cdef extern from 'python.h': | |
36 struct PyObject: | |
37 pass | |
38 void *PyMem_Malloc(size_t n) except NULL | |
39 void PyMem_Free(void *p) | |
40 struct PyThreadState: | |
41 pass | |
42 PyThreadState *PyEval_SaveThread() | |
43 void PyEval_RestoreThread(PyThreadState *tstate) | |
44 void Py_INCREF(object o) | |
45 void Py_XINCREF(object o) | |
46 void Py_DECREF(object o) | |
47 void Py_XDECREF(object o) | |
48 int PyObject_AsWriteBuffer(object obj, void **buffer, int *buffer_len) excep
t -1 | |
49 int PyObject_AsReadBuffer(object obj, void **buffer, int *buffer_len) except
-1 | |
50 object PyString_FromString(char *v) | |
51 object PyString_FromStringAndSize(char *v, int len) | |
52 object PyBuffer_New(int size) | |
53 char *PyString_AsString(object obj) except NULL | |
54 object PySequence_Fast(object o, char *m) | |
55 # object PySequence_Fast_GET_ITEM(object o, int i) | |
56 PyObject** PySequence_Fast_ITEMS(object o) | |
57 PyObject* PySequence_ITEM( PyObject *o, int i) | |
58 int PySequence_Fast_GET_SIZE(object o) | |
59 | |
60 cdef extern from '': | |
61 struct sockaddr: | |
62 int sa_family | |
63 char sa_data[0] | |
64 cdef struct in_addr: | |
65 unsigned long s_addr | |
66 struct sockaddr_in: | |
67 int sin_port | |
68 in_addr sin_addr | |
69 int getsockopt(SOCKET s, int level, int optname, char *optval, int *optlen) | |
70 enum: | |
71 SOL_SOCKET | |
72 SO_PROTOCOL_INFO | |
73 SOCKET_ERROR | |
74 ERROR_IO_PENDING | |
75 AF_INET | |
76 INADDR_ANY | |
77 ctypedef struct WSAPROTOCOL_INFO: | |
78 int iMaxSockAddr | |
79 int iAddressFamily | |
80 int WSAGetLastError() | |
81 char *inet_ntoa(in_addr ina) | |
82 unsigned long inet_addr(char *cp) | |
83 short ntohs(short netshort) | |
84 short htons(short hostshort) | |
85 ctypedef struct WSABUF: | |
86 long len | |
87 char *buf | |
88 # cdef struct TRANSMIT_FILE_BUFFERS: | |
89 # pass | |
90 int WSARecv(SOCKET s, WSABUF *buffs, DWORD buffcount, DWORD *bytes, DWORD *f
lags, OVERLAPPED *ov, void *crud) | |
91 int WSARecvFrom(SOCKET s, WSABUF *buffs, DWORD buffcount, DWORD *bytes, DWOR
D *flags, sockaddr *fromaddr, int *fromlen, OVERLAPPED *ov, void *crud) | |
92 int WSASend(SOCKET s, WSABUF *buffs, DWORD buffcount, DWORD *bytes, DWORD fl
ags, OVERLAPPED *ov, void *crud) | |
93 | |
94 cdef extern from 'string.h': | |
95 void *memset(void *s, int c, size_t n) | |
96 | |
97 cdef extern from 'winsock_pointers.h': | |
98 int initWinsockPointers() | |
99 BOOL (*lpAcceptEx)(SOCKET listening, SOCKET accepting, void *buffer, DWORD r
ecvlen, DWORD locallen, DWORD remotelen, DWORD *bytes, OVERLAPPED *ov) | |
100 void (*lpGetAcceptExSockaddrs)(void *buffer, DWORD recvlen, DWORD locallen,
DWORD remotelen, sockaddr **localaddr, int *locallen, sockaddr **remoteaddr, int
*remotelen) | |
101 BOOL (*lpConnectEx)(SOCKET s, sockaddr *name, int namelen, void *buff, DWORD
sendlen, DWORD *sentlen, OVERLAPPED *ov) | |
102 # BOOL (*lpTransmitFile)(SOCKET s, HANDLE hFile, DWORD size, DWORD buffer_siz
e, OVERLAPPED *ov, TRANSMIT_FILE_BUFFERS *buff, DWORD flags) | |
103 | |
104 cdef struct myOVERLAPPED: | |
105 OVERLAPPED ov | |
106 PyObject *obj | |
107 | |
108 cdef myOVERLAPPED *makeOV() except NULL: | |
109 cdef myOVERLAPPED *res | |
110 res = <myOVERLAPPED *>PyMem_Malloc(sizeof(myOVERLAPPED)) | |
111 if not res: | |
112 raise MemoryError | |
113 memset(res, 0, sizeof(myOVERLAPPED)) | |
114 return res | |
115 | |
116 cdef void raise_error(int err, object message) except *: | |
117 if not err: | |
118 err = GetLastError() | |
119 raise WindowsError(message, err) | |
120 | |
121 class Event: | |
122 def __init__(self, callback, owner, **kw): | |
123 self.callback = callback | |
124 self.owner = owner | |
125 self.ignore = False | |
126 for k, v in kw.items(): | |
127 setattr(self, k, v) | |
128 | |
129 cdef class CompletionPort: | |
130 cdef HANDLE port | |
131 def __init__(self): | |
132 cdef HANDLE res | |
133 res = CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 0) | |
134 if not res: | |
135 raise_error(0, 'CreateIoCompletionPort') | |
136 self.port = res | |
137 | |
138 def addHandle(self, long handle, long key=0): | |
139 cdef HANDLE res | |
140 res = CreateIoCompletionPort(handle, self.port, key, 0) | |
141 if not res: | |
142 raise_error(0, 'CreateIoCompletionPort') | |
143 | |
144 def getEvent(self, long timeout): | |
145 cdef PyThreadState *_save | |
146 cdef unsigned long bytes, key, rc | |
147 cdef myOVERLAPPED *ov | |
148 | |
149 _save = PyEval_SaveThread() | |
150 rc = GetQueuedCompletionStatus(self.port, &bytes, &key, <OVERLAPPED **>&
ov, timeout) | |
151 PyEval_RestoreThread(_save) | |
152 | |
153 if not rc: | |
154 rc = GetLastError() | |
155 else: | |
156 rc = 0 | |
157 | |
158 obj = None | |
159 if ov: | |
160 if ov.obj: | |
161 obj = <object>ov.obj | |
162 Py_DECREF(obj) # we are stealing a reference here | |
163 PyMem_Free(ov) | |
164 | |
165 return (rc, bytes, key, obj) | |
166 | |
167 def postEvent(self, unsigned long bytes, unsigned long key, obj): | |
168 cdef myOVERLAPPED *ov | |
169 cdef unsigned long rc | |
170 | |
171 if obj is not None: | |
172 ov = makeOV() | |
173 Py_INCREF(obj) # give ov its own reference to obj | |
174 ov.obj = <PyObject *>obj | |
175 else: | |
176 ov = NULL | |
177 | |
178 rc = PostQueuedCompletionStatus(self.port, bytes, key, <OVERLAPPED *>ov) | |
179 if not rc: | |
180 raise_error(0, 'PostQueuedCompletionStatus') | |
181 | |
182 def __del__(self): | |
183 CloseHandle(self.port) | |
184 | |
185 def makesockaddr(object buff): | |
186 cdef void *mem_buffer | |
187 cdef int size | |
188 | |
189 PyObject_AsReadBuffer(buff, &mem_buffer, &size) | |
190 # XXX: this should really return the address family as well | |
191 return _makesockaddr(<sockaddr *>mem_buffer, size) | |
192 | |
193 cdef object _makesockaddr(sockaddr *addr, int len): | |
194 cdef sockaddr_in *sin | |
195 if not len: | |
196 return None | |
197 if addr.sa_family == AF_INET: | |
198 sin = <sockaddr_in *>addr | |
199 return PyString_FromString(inet_ntoa(sin.sin_addr)), ntohs(sin.sin_port) | |
200 else: | |
201 return PyString_FromStringAndSize(addr.sa_data, sizeof(addr.sa_data)) | |
202 | |
203 cdef object fillinetaddr(sockaddr_in *dest, object addr): | |
204 cdef short port | |
205 cdef unsigned long res | |
206 cdef char *hoststr | |
207 host, port = addr | |
208 | |
209 hoststr = PyString_AsString(host) | |
210 res = inet_addr(hoststr) | |
211 if res == INADDR_ANY: | |
212 raise ValueError, 'invalid IP address' | |
213 dest.sin_addr.s_addr = res | |
214 | |
215 dest.sin_port = htons(port) | |
216 | |
217 def AllocateReadBuffer(int size): | |
218 return PyBuffer_New(size) | |
219 | |
220 def maxAddrLen(long s): | |
221 cdef WSAPROTOCOL_INFO wsa_pi | |
222 cdef int size, rc | |
223 | |
224 size = sizeof(wsa_pi) | |
225 rc = getsockopt(s, SOL_SOCKET, SO_PROTOCOL_INFO, <char *>&wsa_pi, &size) | |
226 if rc == SOCKET_ERROR: | |
227 raise_error(WSAGetLastError(), 'getsockopt') | |
228 return wsa_pi.iMaxSockAddr | |
229 | |
230 cdef int getAddrFamily(SOCKET s) except *: | |
231 cdef WSAPROTOCOL_INFO wsa_pi | |
232 cdef int size, rc | |
233 | |
234 size = sizeof(wsa_pi) | |
235 rc = getsockopt(s, SOL_SOCKET, SO_PROTOCOL_INFO, <char *>&wsa_pi, &size) | |
236 if rc == SOCKET_ERROR: | |
237 raise_error(WSAGetLastError(), 'getsockopt') | |
238 return wsa_pi.iAddressFamily | |
239 | |
240 import socket # for WSAStartup | |
241 if not initWinsockPointers(): | |
242 raise ValueError, 'Failed to initialize Winsock function vectors' | |
243 | |
244 have_connectex = (lpConnectEx != NULL) | |
245 | |
246 include 'acceptex.pxi' | |
247 include 'connectex.pxi' | |
248 include 'wsarecv.pxi' | |
249 include 'wsasend.pxi' | |
250 | |
OLD | NEW |