| 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 |