blob: 44a0a5a834633fd5d601ad4b73271e4e3e924bfe [file] [log] [blame]
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001/*
2 * Support for overlapped IO
3 *
4 * Some code borrowed from Modules/_winapi.c of CPython
5 */
6
7/* XXX check overflow and DWORD <-> Py_ssize_t conversions
8 Check itemsize */
9
10#include "Python.h"
11#include "structmember.h"
12
13#define WINDOWS_LEAN_AND_MEAN
14#include <winsock2.h>
15#include <ws2tcpip.h>
16#include <mswsock.h>
17
18#if defined(MS_WIN32) && !defined(MS_WIN64)
19# define F_POINTER "k"
20# define T_POINTER T_ULONG
21#else
22# define F_POINTER "K"
23# define T_POINTER T_ULONGLONG
24#endif
25
Victor Stinnerccdbe802016-04-01 21:37:41 +020026/* Compatibility with Python 3.3 */
27#if PY_VERSION_HEX < 0x03040000
28# define PyMem_RawMalloc PyMem_Malloc
29# define PyMem_RawFree PyMem_Free
30#endif
31
Guido van Rossum27b7c7e2013-10-17 13:40:50 -070032#define F_HANDLE F_POINTER
33#define F_ULONG_PTR F_POINTER
34#define F_DWORD "k"
35#define F_BOOL "i"
36#define F_UINT "I"
37
38#define T_HANDLE T_POINTER
39
Antoine Pitrou525f40d2017-10-19 21:46:40 +020040enum {TYPE_NONE, TYPE_NOT_STARTED, TYPE_READ, TYPE_READINTO, TYPE_WRITE,
41 TYPE_ACCEPT, TYPE_CONNECT, TYPE_DISCONNECT, TYPE_CONNECT_NAMED_PIPE,
Andrew Svetlovbafd4b52019-05-28 12:52:15 +030042 TYPE_WAIT_NAMED_PIPE_AND_CONNECT, TYPE_TRANSMIT_FILE, TYPE_READ_FROM,
43 TYPE_WRITE_TO};
Guido van Rossum27b7c7e2013-10-17 13:40:50 -070044
45typedef struct {
46 PyObject_HEAD
47 OVERLAPPED overlapped;
48 /* For convenience, we store the file handle too */
49 HANDLE handle;
50 /* Error returned by last method call */
51 DWORD error;
52 /* Type of operation */
53 DWORD type;
54 union {
Antoine Pitrou525f40d2017-10-19 21:46:40 +020055 /* Buffer allocated by us: TYPE_READ and TYPE_ACCEPT */
56 PyObject *allocated_buffer;
Andrew Svetlovbafd4b52019-05-28 12:52:15 +030057 /* Buffer passed by the user: TYPE_WRITE, TYPE_WRITE_TO, and TYPE_READINTO */
Antoine Pitrou525f40d2017-10-19 21:46:40 +020058 Py_buffer user_buffer;
Andrew Svetlovbafd4b52019-05-28 12:52:15 +030059
60 /* Data used for reading from a connectionless socket:
61 TYPE_READ_FROM */
62 struct {
63 // A (buffer, (host, port)) tuple
64 PyObject *result;
65 // The actual read buffer
66 PyObject *allocated_buffer;
67 struct sockaddr_in6 address;
68 int address_length;
69 } read_from;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -070070 };
71} OverlappedObject;
72
Guido van Rossum27b7c7e2013-10-17 13:40:50 -070073/*
74 * Map Windows error codes to subclasses of OSError
75 */
76
77static PyObject *
78SetFromWindowsErr(DWORD err)
79{
80 PyObject *exception_type;
81
82 if (err == 0)
83 err = GetLastError();
84 switch (err) {
85 case ERROR_CONNECTION_REFUSED:
86 exception_type = PyExc_ConnectionRefusedError;
87 break;
88 case ERROR_CONNECTION_ABORTED:
89 exception_type = PyExc_ConnectionAbortedError;
90 break;
91 default:
92 exception_type = PyExc_OSError;
93 }
94 return PyErr_SetExcFromWindowsErr(exception_type, err);
95}
96
97/*
98 * Some functions should be loaded at runtime
99 */
100
101static LPFN_ACCEPTEX Py_AcceptEx = NULL;
102static LPFN_CONNECTEX Py_ConnectEx = NULL;
103static LPFN_DISCONNECTEX Py_DisconnectEx = NULL;
Andrew Svetlova19fb3c2018-02-25 19:32:14 +0300104static LPFN_TRANSMITFILE Py_TransmitFile = NULL;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700105static BOOL (CALLBACK *Py_CancelIoEx)(HANDLE, LPOVERLAPPED) = NULL;
106
107#define GET_WSA_POINTER(s, x) \
108 (SOCKET_ERROR != WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, \
109 &Guid##x, sizeof(Guid##x), &Py_##x, \
110 sizeof(Py_##x), &dwBytes, NULL, NULL))
111
112static int
113initialize_function_pointers(void)
114{
115 GUID GuidAcceptEx = WSAID_ACCEPTEX;
116 GUID GuidConnectEx = WSAID_CONNECTEX;
117 GUID GuidDisconnectEx = WSAID_DISCONNECTEX;
Andrew Svetlova19fb3c2018-02-25 19:32:14 +0300118 GUID GuidTransmitFile = WSAID_TRANSMITFILE;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700119 HINSTANCE hKernel32;
120 SOCKET s;
121 DWORD dwBytes;
122
123 s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
124 if (s == INVALID_SOCKET) {
125 SetFromWindowsErr(WSAGetLastError());
126 return -1;
127 }
128
129 if (!GET_WSA_POINTER(s, AcceptEx) ||
130 !GET_WSA_POINTER(s, ConnectEx) ||
Andrew Svetlova19fb3c2018-02-25 19:32:14 +0300131 !GET_WSA_POINTER(s, DisconnectEx) ||
132 !GET_WSA_POINTER(s, TransmitFile))
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700133 {
134 closesocket(s);
135 SetFromWindowsErr(WSAGetLastError());
136 return -1;
137 }
138
139 closesocket(s);
140
141 /* On WinXP we will have Py_CancelIoEx == NULL */
Tony Roberts4860f012019-02-02 18:16:42 +0100142 Py_BEGIN_ALLOW_THREADS
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700143 hKernel32 = GetModuleHandle("KERNEL32");
144 *(FARPROC *)&Py_CancelIoEx = GetProcAddress(hKernel32, "CancelIoEx");
Tony Roberts4860f012019-02-02 18:16:42 +0100145 Py_END_ALLOW_THREADS
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700146 return 0;
147}
148
149/*
150 * Completion port stuff
151 */
152
153PyDoc_STRVAR(
154 CreateIoCompletionPort_doc,
155 "CreateIoCompletionPort(handle, port, key, concurrency) -> port\n\n"
156 "Create a completion port or register a handle with a port.");
157
158static PyObject *
159overlapped_CreateIoCompletionPort(PyObject *self, PyObject *args)
160{
161 HANDLE FileHandle;
162 HANDLE ExistingCompletionPort;
163 ULONG_PTR CompletionKey;
164 DWORD NumberOfConcurrentThreads;
165 HANDLE ret;
166
167 if (!PyArg_ParseTuple(args, F_HANDLE F_HANDLE F_ULONG_PTR F_DWORD,
168 &FileHandle, &ExistingCompletionPort, &CompletionKey,
169 &NumberOfConcurrentThreads))
170 return NULL;
171
172 Py_BEGIN_ALLOW_THREADS
173 ret = CreateIoCompletionPort(FileHandle, ExistingCompletionPort,
174 CompletionKey, NumberOfConcurrentThreads);
175 Py_END_ALLOW_THREADS
176
177 if (ret == NULL)
178 return SetFromWindowsErr(0);
179 return Py_BuildValue(F_HANDLE, ret);
180}
181
182PyDoc_STRVAR(
183 GetQueuedCompletionStatus_doc,
184 "GetQueuedCompletionStatus(port, msecs) -> (err, bytes, key, address)\n\n"
185 "Get a message from completion port. Wait for up to msecs milliseconds.");
186
187static PyObject *
188overlapped_GetQueuedCompletionStatus(PyObject *self, PyObject *args)
189{
190 HANDLE CompletionPort = NULL;
191 DWORD NumberOfBytes = 0;
192 ULONG_PTR CompletionKey = 0;
193 OVERLAPPED *Overlapped = NULL;
194 DWORD Milliseconds;
195 DWORD err;
196 BOOL ret;
197
198 if (!PyArg_ParseTuple(args, F_HANDLE F_DWORD,
199 &CompletionPort, &Milliseconds))
200 return NULL;
201
202 Py_BEGIN_ALLOW_THREADS
203 ret = GetQueuedCompletionStatus(CompletionPort, &NumberOfBytes,
204 &CompletionKey, &Overlapped, Milliseconds);
205 Py_END_ALLOW_THREADS
206
207 err = ret ? ERROR_SUCCESS : GetLastError();
208 if (Overlapped == NULL) {
209 if (err == WAIT_TIMEOUT)
210 Py_RETURN_NONE;
211 else
212 return SetFromWindowsErr(err);
213 }
214 return Py_BuildValue(F_DWORD F_DWORD F_ULONG_PTR F_POINTER,
215 err, NumberOfBytes, CompletionKey, Overlapped);
216}
217
218PyDoc_STRVAR(
219 PostQueuedCompletionStatus_doc,
220 "PostQueuedCompletionStatus(port, bytes, key, address) -> None\n\n"
221 "Post a message to completion port.");
222
223static PyObject *
224overlapped_PostQueuedCompletionStatus(PyObject *self, PyObject *args)
225{
226 HANDLE CompletionPort;
227 DWORD NumberOfBytes;
228 ULONG_PTR CompletionKey;
229 OVERLAPPED *Overlapped;
230 BOOL ret;
231
232 if (!PyArg_ParseTuple(args, F_HANDLE F_DWORD F_ULONG_PTR F_POINTER,
233 &CompletionPort, &NumberOfBytes, &CompletionKey,
234 &Overlapped))
235 return NULL;
236
237 Py_BEGIN_ALLOW_THREADS
238 ret = PostQueuedCompletionStatus(CompletionPort, NumberOfBytes,
239 CompletionKey, Overlapped);
240 Py_END_ALLOW_THREADS
241
242 if (!ret)
243 return SetFromWindowsErr(0);
244 Py_RETURN_NONE;
245}
246
247/*
Guido van Rossum90fb9142013-10-30 14:44:05 -0700248 * Wait for a handle
249 */
250
251struct PostCallbackData {
252 HANDLE CompletionPort;
253 LPOVERLAPPED Overlapped;
254};
255
256static VOID CALLBACK
257PostToQueueCallback(PVOID lpParameter, BOOL TimerOrWaitFired)
258{
259 struct PostCallbackData *p = (struct PostCallbackData*) lpParameter;
260
261 PostQueuedCompletionStatus(p->CompletionPort, TimerOrWaitFired,
262 0, p->Overlapped);
263 /* ignore possible error! */
Victor Stinner6150f312016-03-16 23:25:02 +0100264 PyMem_RawFree(p);
Guido van Rossum90fb9142013-10-30 14:44:05 -0700265}
266
267PyDoc_STRVAR(
268 RegisterWaitWithQueue_doc,
269 "RegisterWaitWithQueue(Object, CompletionPort, Overlapped, Timeout)\n"
270 " -> WaitHandle\n\n"
271 "Register wait for Object; when complete CompletionPort is notified.\n");
272
273static PyObject *
274overlapped_RegisterWaitWithQueue(PyObject *self, PyObject *args)
275{
276 HANDLE NewWaitObject;
277 HANDLE Object;
278 ULONG Milliseconds;
279 struct PostCallbackData data, *pdata;
280
281 if (!PyArg_ParseTuple(args, F_HANDLE F_HANDLE F_POINTER F_DWORD,
282 &Object,
283 &data.CompletionPort,
284 &data.Overlapped,
285 &Milliseconds))
286 return NULL;
287
Victor Stinner6150f312016-03-16 23:25:02 +0100288 /* Use PyMem_RawMalloc() rather than PyMem_Malloc(), since
289 PostToQueueCallback() will call PyMem_Free() from a new C thread
290 which doesn't hold the GIL. */
291 pdata = PyMem_RawMalloc(sizeof(struct PostCallbackData));
Guido van Rossum90fb9142013-10-30 14:44:05 -0700292 if (pdata == NULL)
293 return SetFromWindowsErr(0);
294
295 *pdata = data;
296
297 if (!RegisterWaitForSingleObject(
298 &NewWaitObject, Object, (WAITORTIMERCALLBACK)PostToQueueCallback,
299 pdata, Milliseconds,
300 WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE))
301 {
Victor Stinner6150f312016-03-16 23:25:02 +0100302 PyMem_RawFree(pdata);
Guido van Rossum90fb9142013-10-30 14:44:05 -0700303 return SetFromWindowsErr(0);
304 }
305
306 return Py_BuildValue(F_HANDLE, NewWaitObject);
307}
308
309PyDoc_STRVAR(
310 UnregisterWait_doc,
311 "UnregisterWait(WaitHandle) -> None\n\n"
312 "Unregister wait handle.\n");
313
314static PyObject *
315overlapped_UnregisterWait(PyObject *self, PyObject *args)
316{
317 HANDLE WaitHandle;
318 BOOL ret;
319
320 if (!PyArg_ParseTuple(args, F_HANDLE, &WaitHandle))
321 return NULL;
322
323 Py_BEGIN_ALLOW_THREADS
324 ret = UnregisterWait(WaitHandle);
325 Py_END_ALLOW_THREADS
326
327 if (!ret)
328 return SetFromWindowsErr(0);
329 Py_RETURN_NONE;
330}
331
Victor Stinnerd0a28de2015-01-21 23:39:51 +0100332PyDoc_STRVAR(
333 UnregisterWaitEx_doc,
334 "UnregisterWaitEx(WaitHandle, Event) -> None\n\n"
335 "Unregister wait handle.\n");
336
337static PyObject *
338overlapped_UnregisterWaitEx(PyObject *self, PyObject *args)
339{
340 HANDLE WaitHandle, Event;
341 BOOL ret;
342
343 if (!PyArg_ParseTuple(args, F_HANDLE F_HANDLE, &WaitHandle, &Event))
344 return NULL;
345
346 Py_BEGIN_ALLOW_THREADS
347 ret = UnregisterWaitEx(WaitHandle, Event);
348 Py_END_ALLOW_THREADS
349
350 if (!ret)
351 return SetFromWindowsErr(0);
352 Py_RETURN_NONE;
353}
354
Guido van Rossum90fb9142013-10-30 14:44:05 -0700355/*
356 * Event functions -- currently only used by tests
357 */
358
359PyDoc_STRVAR(
360 CreateEvent_doc,
361 "CreateEvent(EventAttributes, ManualReset, InitialState, Name)"
362 " -> Handle\n\n"
363 "Create an event. EventAttributes must be None.\n");
364
365static PyObject *
366overlapped_CreateEvent(PyObject *self, PyObject *args)
367{
368 PyObject *EventAttributes;
369 BOOL ManualReset;
370 BOOL InitialState;
371 Py_UNICODE *Name;
372 HANDLE Event;
373
374 if (!PyArg_ParseTuple(args, "O" F_BOOL F_BOOL "Z",
375 &EventAttributes, &ManualReset,
376 &InitialState, &Name))
377 return NULL;
378
379 if (EventAttributes != Py_None) {
380 PyErr_SetString(PyExc_ValueError, "EventAttributes must be None");
381 return NULL;
382 }
383
384 Py_BEGIN_ALLOW_THREADS
385 Event = CreateEventW(NULL, ManualReset, InitialState, Name);
386 Py_END_ALLOW_THREADS
387
388 if (Event == NULL)
389 return SetFromWindowsErr(0);
390 return Py_BuildValue(F_HANDLE, Event);
391}
392
393PyDoc_STRVAR(
394 SetEvent_doc,
395 "SetEvent(Handle) -> None\n\n"
396 "Set event.\n");
397
398static PyObject *
399overlapped_SetEvent(PyObject *self, PyObject *args)
400{
401 HANDLE Handle;
402 BOOL ret;
403
404 if (!PyArg_ParseTuple(args, F_HANDLE, &Handle))
405 return NULL;
406
407 Py_BEGIN_ALLOW_THREADS
408 ret = SetEvent(Handle);
409 Py_END_ALLOW_THREADS
410
411 if (!ret)
412 return SetFromWindowsErr(0);
413 Py_RETURN_NONE;
414}
415
416PyDoc_STRVAR(
417 ResetEvent_doc,
418 "ResetEvent(Handle) -> None\n\n"
419 "Reset event.\n");
420
421static PyObject *
422overlapped_ResetEvent(PyObject *self, PyObject *args)
423{
424 HANDLE Handle;
425 BOOL ret;
426
427 if (!PyArg_ParseTuple(args, F_HANDLE, &Handle))
428 return NULL;
429
430 Py_BEGIN_ALLOW_THREADS
431 ret = ResetEvent(Handle);
432 Py_END_ALLOW_THREADS
433
434 if (!ret)
435 return SetFromWindowsErr(0);
436 Py_RETURN_NONE;
437}
438
439/*
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700440 * Bind socket handle to local port without doing slow getaddrinfo()
441 */
442
443PyDoc_STRVAR(
444 BindLocal_doc,
445 "BindLocal(handle, family) -> None\n\n"
446 "Bind a socket handle to an arbitrary local port.\n"
447 "family should AF_INET or AF_INET6.\n");
448
449static PyObject *
450overlapped_BindLocal(PyObject *self, PyObject *args)
451{
452 SOCKET Socket;
453 int Family;
454 BOOL ret;
455
456 if (!PyArg_ParseTuple(args, F_HANDLE "i", &Socket, &Family))
457 return NULL;
458
459 if (Family == AF_INET) {
460 struct sockaddr_in addr;
461 memset(&addr, 0, sizeof(addr));
462 addr.sin_family = AF_INET;
463 addr.sin_port = 0;
464 addr.sin_addr.S_un.S_addr = INADDR_ANY;
465 ret = bind(Socket, (SOCKADDR*)&addr, sizeof(addr)) != SOCKET_ERROR;
466 } else if (Family == AF_INET6) {
467 struct sockaddr_in6 addr;
468 memset(&addr, 0, sizeof(addr));
469 addr.sin6_family = AF_INET6;
470 addr.sin6_port = 0;
471 addr.sin6_addr = in6addr_any;
472 ret = bind(Socket, (SOCKADDR*)&addr, sizeof(addr)) != SOCKET_ERROR;
473 } else {
474 PyErr_SetString(PyExc_ValueError, "expected tuple of length 2 or 4");
475 return NULL;
476 }
477
478 if (!ret)
479 return SetFromWindowsErr(WSAGetLastError());
480 Py_RETURN_NONE;
481}
482
483/*
484 * Windows equivalent of os.strerror() -- compare _ctypes/callproc.c
485 */
486
487PyDoc_STRVAR(
488 FormatMessage_doc,
489 "FormatMessage(error_code) -> error_message\n\n"
490 "Return error message for an error code.");
491
492static PyObject *
493overlapped_FormatMessage(PyObject *ignore, PyObject *args)
494{
495 DWORD code, n;
496 WCHAR *lpMsgBuf;
497 PyObject *res;
498
499 if (!PyArg_ParseTuple(args, F_DWORD, &code))
500 return NULL;
501
502 n = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
503 FORMAT_MESSAGE_FROM_SYSTEM,
504 NULL,
505 code,
506 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
507 (LPWSTR) &lpMsgBuf,
508 0,
509 NULL);
510 if (n) {
511 while (iswspace(lpMsgBuf[n-1]))
512 --n;
513 lpMsgBuf[n] = L'\0';
514 res = Py_BuildValue("u", lpMsgBuf);
515 } else {
516 res = PyUnicode_FromFormat("unknown error code %u", code);
517 }
518 LocalFree(lpMsgBuf);
519 return res;
520}
521
522
523/*
524 * Mark operation as completed - used when reading produces ERROR_BROKEN_PIPE
525 */
526
527static void
528mark_as_completed(OVERLAPPED *ov)
529{
530 ov->Internal = 0;
531 if (ov->hEvent != NULL)
532 SetEvent(ov->hEvent);
533}
534
535/*
536 * A Python object wrapping an OVERLAPPED structure and other useful data
537 * for overlapped I/O
538 */
539
540PyDoc_STRVAR(
541 Overlapped_doc,
542 "Overlapped object");
543
544static PyObject *
545Overlapped_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
546{
547 OverlappedObject *self;
548 HANDLE event = INVALID_HANDLE_VALUE;
549 static char *kwlist[] = {"event", NULL};
550
551 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|" F_HANDLE, kwlist, &event))
552 return NULL;
553
554 if (event == INVALID_HANDLE_VALUE) {
555 event = CreateEvent(NULL, TRUE, FALSE, NULL);
556 if (event == NULL)
557 return SetFromWindowsErr(0);
558 }
559
560 self = PyObject_New(OverlappedObject, type);
561 if (self == NULL) {
562 if (event != NULL)
563 CloseHandle(event);
564 return NULL;
565 }
566
567 self->handle = NULL;
568 self->error = 0;
569 self->type = TYPE_NONE;
Antoine Pitrou525f40d2017-10-19 21:46:40 +0200570 self->allocated_buffer = NULL;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700571 memset(&self->overlapped, 0, sizeof(OVERLAPPED));
Antoine Pitrou525f40d2017-10-19 21:46:40 +0200572 memset(&self->user_buffer, 0, sizeof(Py_buffer));
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700573 if (event)
574 self->overlapped.hEvent = event;
575 return (PyObject *)self;
576}
577
Victor Stinner54850852019-01-11 14:35:14 +0100578
579/* Note (bpo-32710): OverlappedType.tp_clear is not defined to not release
580 buffers while overlapped are still running, to prevent a crash. */
581static int
582Overlapped_clear(OverlappedObject *self)
583{
584 switch (self->type) {
Andrew Svetlovbafd4b52019-05-28 12:52:15 +0300585 case TYPE_READ:
586 case TYPE_ACCEPT: {
587 Py_CLEAR(self->allocated_buffer);
588 break;
Victor Stinner54850852019-01-11 14:35:14 +0100589 }
Andrew Svetlovbafd4b52019-05-28 12:52:15 +0300590 case TYPE_READ_FROM: {
591 // An initial call to WSARecvFrom will only allocate the buffer.
592 // The result tuple of (message, address) is only
593 // allocated _after_ a message has been received.
594 if(self->read_from.result) {
595 // We've received a message, free the result tuple.
596 Py_CLEAR(self->read_from.result);
597 }
598 if(self->read_from.allocated_buffer) {
599 Py_CLEAR(self->read_from.allocated_buffer);
600 }
601 break;
602 }
603 case TYPE_WRITE:
604 case TYPE_WRITE_TO:
605 case TYPE_READINTO: {
606 if (self->user_buffer.obj) {
607 PyBuffer_Release(&self->user_buffer);
608 }
609 break;
610 }
Victor Stinner54850852019-01-11 14:35:14 +0100611 }
612 self->type = TYPE_NOT_STARTED;
613 return 0;
614}
615
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700616static void
617Overlapped_dealloc(OverlappedObject *self)
618{
619 DWORD bytes;
620 DWORD olderr = GetLastError();
621 BOOL wait = FALSE;
622 BOOL ret;
623
624 if (!HasOverlappedIoCompleted(&self->overlapped) &&
625 self->type != TYPE_NOT_STARTED)
626 {
627 if (Py_CancelIoEx && Py_CancelIoEx(self->handle, &self->overlapped))
628 wait = TRUE;
629
630 Py_BEGIN_ALLOW_THREADS
631 ret = GetOverlappedResult(self->handle, &self->overlapped,
632 &bytes, wait);
633 Py_END_ALLOW_THREADS
634
635 switch (ret ? ERROR_SUCCESS : GetLastError()) {
636 case ERROR_SUCCESS:
637 case ERROR_NOT_FOUND:
638 case ERROR_OPERATION_ABORTED:
639 break;
640 default:
641 PyErr_Format(
642 PyExc_RuntimeError,
643 "%R still has pending operation at "
644 "deallocation, the process may crash", self);
645 PyErr_WriteUnraisable(NULL);
646 }
647 }
648
Victor Stinner54850852019-01-11 14:35:14 +0100649 if (self->overlapped.hEvent != NULL) {
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700650 CloseHandle(self->overlapped.hEvent);
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700651 }
Victor Stinner54850852019-01-11 14:35:14 +0100652
653 Overlapped_clear(self);
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700654 PyObject_Del(self);
655 SetLastError(olderr);
656}
657
Andrew Svetlovbafd4b52019-05-28 12:52:15 +0300658
659/* Convert IPv4 sockaddr to a Python str. */
660
661static PyObject *
662make_ipv4_addr(const struct sockaddr_in *addr)
663{
664 char buf[INET_ADDRSTRLEN];
665 if (inet_ntop(AF_INET, &addr->sin_addr, buf, sizeof(buf)) == NULL) {
666 PyErr_SetFromErrno(PyExc_OSError);
667 return NULL;
668 }
669 return PyUnicode_FromString(buf);
670}
671
672#ifdef ENABLE_IPV6
673/* Convert IPv6 sockaddr to a Python str. */
674
675static PyObject *
676make_ipv6_addr(const struct sockaddr_in6 *addr)
677{
678 char buf[INET6_ADDRSTRLEN];
679 if (inet_ntop(AF_INET6, &addr->sin6_addr, buf, sizeof(buf)) == NULL) {
680 PyErr_SetFromErrno(PyExc_OSError);
681 return NULL;
682 }
683 return PyUnicode_FromString(buf);
684}
685#endif
686
687static PyObject*
688unparse_address(LPSOCKADDR Address, DWORD Length)
689{
690 /* The function is adopted from mocketmodule.c makesockaddr()*/
691
692 switch(Address->sa_family) {
693 case AF_INET: {
694 const struct sockaddr_in *a = (const struct sockaddr_in *)Address;
695 PyObject *addrobj = make_ipv4_addr(a);
696 PyObject *ret = NULL;
697 if (addrobj) {
698 ret = Py_BuildValue("Oi", addrobj, ntohs(a->sin_port));
699 Py_DECREF(addrobj);
700 }
701 return ret;
702 }
703#ifdef ENABLE_IPV6
704 case AF_INET6: {
705 const struct sockaddr_in6 *a = (const struct sockaddr_in6 *)Address;
706 PyObject *addrobj = make_ipv6_addr(a);
707 PyObject *ret = NULL;
708 if (addrobj) {
709 ret = Py_BuildValue("OiII",
710 addrobj,
711 ntohs(a->sin6_port),
712 ntohl(a->sin6_flowinfo),
713 a->sin6_scope_id);
714 Py_DECREF(addrobj);
715 }
716 return ret;
717 }
718#endif /* ENABLE_IPV6 */
719 default: {
720 return SetFromWindowsErr(ERROR_INVALID_PARAMETER);
721 }
722 }
723}
724
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700725PyDoc_STRVAR(
726 Overlapped_cancel_doc,
727 "cancel() -> None\n\n"
728 "Cancel overlapped operation");
729
730static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530731Overlapped_cancel(OverlappedObject *self, PyObject *Py_UNUSED(ignored))
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700732{
733 BOOL ret = TRUE;
734
735 if (self->type == TYPE_NOT_STARTED
736 || self->type == TYPE_WAIT_NAMED_PIPE_AND_CONNECT)
737 Py_RETURN_NONE;
738
739 if (!HasOverlappedIoCompleted(&self->overlapped)) {
740 Py_BEGIN_ALLOW_THREADS
741 if (Py_CancelIoEx)
742 ret = Py_CancelIoEx(self->handle, &self->overlapped);
743 else
744 ret = CancelIo(self->handle);
745 Py_END_ALLOW_THREADS
746 }
747
748 /* CancelIoEx returns ERROR_NOT_FOUND if the I/O completed in-between */
749 if (!ret && GetLastError() != ERROR_NOT_FOUND)
750 return SetFromWindowsErr(0);
751 Py_RETURN_NONE;
752}
753
754PyDoc_STRVAR(
755 Overlapped_getresult_doc,
756 "getresult(wait=False) -> result\n\n"
757 "Retrieve result of operation. If wait is true then it blocks\n"
758 "until the operation is finished. If wait is false and the\n"
759 "operation is still pending then an error is raised.");
760
761static PyObject *
762Overlapped_getresult(OverlappedObject *self, PyObject *args)
763{
764 BOOL wait = FALSE;
765 DWORD transferred = 0;
766 BOOL ret;
767 DWORD err;
Andrew Svetlovbafd4b52019-05-28 12:52:15 +0300768 PyObject *addr;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700769
770 if (!PyArg_ParseTuple(args, "|" F_BOOL, &wait))
771 return NULL;
772
773 if (self->type == TYPE_NONE) {
774 PyErr_SetString(PyExc_ValueError, "operation not yet attempted");
775 return NULL;
776 }
777
778 if (self->type == TYPE_NOT_STARTED) {
779 PyErr_SetString(PyExc_ValueError, "operation failed to start");
780 return NULL;
781 }
782
783 Py_BEGIN_ALLOW_THREADS
784 ret = GetOverlappedResult(self->handle, &self->overlapped, &transferred,
785 wait);
786 Py_END_ALLOW_THREADS
787
788 self->error = err = ret ? ERROR_SUCCESS : GetLastError();
789 switch (err) {
790 case ERROR_SUCCESS:
791 case ERROR_MORE_DATA:
792 break;
793 case ERROR_BROKEN_PIPE:
Andrew Svetlovbafd4b52019-05-28 12:52:15 +0300794 if (self->type == TYPE_READ || self->type == TYPE_READINTO) {
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700795 break;
Andrew Svetlovbafd4b52019-05-28 12:52:15 +0300796 }
797 else if (self->type == TYPE_READ_FROM &&
798 (self->read_from.result != NULL ||
799 self->read_from.allocated_buffer != NULL))
800 {
801 break;
802 }
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700803 /* fall through */
804 default:
805 return SetFromWindowsErr(err);
806 }
807
808 switch (self->type) {
809 case TYPE_READ:
Antoine Pitrou525f40d2017-10-19 21:46:40 +0200810 assert(PyBytes_CheckExact(self->allocated_buffer));
811 if (transferred != PyBytes_GET_SIZE(self->allocated_buffer) &&
812 _PyBytes_Resize(&self->allocated_buffer, transferred))
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700813 return NULL;
Andrew Svetlovbafd4b52019-05-28 12:52:15 +0300814
Antoine Pitrou525f40d2017-10-19 21:46:40 +0200815 Py_INCREF(self->allocated_buffer);
816 return self->allocated_buffer;
Andrew Svetlovbafd4b52019-05-28 12:52:15 +0300817 case TYPE_READ_FROM:
818 assert(PyBytes_CheckExact(self->read_from.allocated_buffer));
819
820 if (transferred != PyBytes_GET_SIZE(
821 self->read_from.allocated_buffer) &&
822 _PyBytes_Resize(&self->read_from.allocated_buffer, transferred))
823 {
824 return NULL;
825 }
826
827 // unparse the address
828 addr = unparse_address((SOCKADDR*)&self->read_from.address,
829 self->read_from.address_length);
830
831 if (addr == NULL) {
832 return NULL;
833 }
834
835 // The result is a two item tuple: (message, address)
836 self->read_from.result = PyTuple_New(2);
837 if (self->read_from.result == NULL) {
838 Py_CLEAR(addr);
839 return NULL;
840 }
841
842 // first item: message
843 Py_INCREF(self->read_from.allocated_buffer);
844 PyTuple_SET_ITEM(self->read_from.result, 0,
845 self->read_from.allocated_buffer);
846 // second item: address
847 PyTuple_SET_ITEM(self->read_from.result, 1, addr);
848
849 Py_INCREF(self->read_from.result);
850 return self->read_from.result;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700851 default:
852 return PyLong_FromUnsignedLong((unsigned long) transferred);
853 }
854}
855
Antoine Pitrou525f40d2017-10-19 21:46:40 +0200856static PyObject *
857do_ReadFile(OverlappedObject *self, HANDLE handle,
858 char *bufstart, DWORD buflen)
859{
860 DWORD nread;
861 int ret;
862 DWORD err;
863
864 Py_BEGIN_ALLOW_THREADS
865 ret = ReadFile(handle, bufstart, buflen, &nread,
866 &self->overlapped);
867 Py_END_ALLOW_THREADS
868
869 self->error = err = ret ? ERROR_SUCCESS : GetLastError();
870 switch (err) {
871 case ERROR_BROKEN_PIPE:
872 mark_as_completed(&self->overlapped);
873 return SetFromWindowsErr(err);
874 case ERROR_SUCCESS:
875 case ERROR_MORE_DATA:
876 case ERROR_IO_PENDING:
877 Py_RETURN_NONE;
878 default:
Victor Stinner54850852019-01-11 14:35:14 +0100879 Overlapped_clear(self);
Antoine Pitrou525f40d2017-10-19 21:46:40 +0200880 return SetFromWindowsErr(err);
881 }
882}
883
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700884PyDoc_STRVAR(
885 Overlapped_ReadFile_doc,
886 "ReadFile(handle, size) -> Overlapped[message]\n\n"
887 "Start overlapped read");
888
889static PyObject *
890Overlapped_ReadFile(OverlappedObject *self, PyObject *args)
891{
892 HANDLE handle;
893 DWORD size;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700894 PyObject *buf;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700895
896 if (!PyArg_ParseTuple(args, F_HANDLE F_DWORD, &handle, &size))
897 return NULL;
898
899 if (self->type != TYPE_NONE) {
900 PyErr_SetString(PyExc_ValueError, "operation already attempted");
901 return NULL;
902 }
903
904#if SIZEOF_SIZE_T <= SIZEOF_LONG
905 size = Py_MIN(size, (DWORD)PY_SSIZE_T_MAX);
906#endif
907 buf = PyBytes_FromStringAndSize(NULL, Py_MAX(size, 1));
908 if (buf == NULL)
909 return NULL;
910
911 self->type = TYPE_READ;
912 self->handle = handle;
Antoine Pitrou525f40d2017-10-19 21:46:40 +0200913 self->allocated_buffer = buf;
914
915 return do_ReadFile(self, handle, PyBytes_AS_STRING(buf), size);
916}
917
918PyDoc_STRVAR(
919 Overlapped_ReadFileInto_doc,
920 "ReadFileInto(handle, buf) -> Overlapped[bytes_transferred]\n\n"
921 "Start overlapped receive");
922
923static PyObject *
924Overlapped_ReadFileInto(OverlappedObject *self, PyObject *args)
925{
926 HANDLE handle;
927 PyObject *bufobj;
928
929 if (!PyArg_ParseTuple(args, F_HANDLE "O", &handle, &bufobj))
930 return NULL;
931
932 if (self->type != TYPE_NONE) {
933 PyErr_SetString(PyExc_ValueError, "operation already attempted");
934 return NULL;
935 }
936
937 if (!PyArg_Parse(bufobj, "y*", &self->user_buffer))
938 return NULL;
939
940#if SIZEOF_SIZE_T > SIZEOF_LONG
941 if (self->user_buffer.len > (Py_ssize_t)ULONG_MAX) {
942 PyBuffer_Release(&self->user_buffer);
943 PyErr_SetString(PyExc_ValueError, "buffer too large");
944 return NULL;
945 }
946#endif
947
948 self->type = TYPE_READINTO;
949 self->handle = handle;
950
951 return do_ReadFile(self, handle, self->user_buffer.buf,
952 (DWORD)self->user_buffer.len);
953}
954
955static PyObject *
956do_WSARecv(OverlappedObject *self, HANDLE handle,
957 char *bufstart, DWORD buflen, DWORD flags)
958{
959 DWORD nread;
960 WSABUF wsabuf;
961 int ret;
962 DWORD err;
Serhiy Storchakabdf42982017-10-26 16:59:40 +0300963
Antoine Pitrou525f40d2017-10-19 21:46:40 +0200964 wsabuf.buf = bufstart;
965 wsabuf.len = buflen;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700966
967 Py_BEGIN_ALLOW_THREADS
Antoine Pitrou525f40d2017-10-19 21:46:40 +0200968 ret = WSARecv((SOCKET)handle, &wsabuf, 1, &nread, &flags,
969 &self->overlapped, NULL);
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700970 Py_END_ALLOW_THREADS
971
Antoine Pitrou525f40d2017-10-19 21:46:40 +0200972 self->error = err = (ret < 0 ? WSAGetLastError() : ERROR_SUCCESS);
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700973 switch (err) {
974 case ERROR_BROKEN_PIPE:
975 mark_as_completed(&self->overlapped);
Victor Stinner41063d22015-01-26 22:30:49 +0100976 return SetFromWindowsErr(err);
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700977 case ERROR_SUCCESS:
978 case ERROR_MORE_DATA:
979 case ERROR_IO_PENDING:
980 Py_RETURN_NONE;
981 default:
Victor Stinner54850852019-01-11 14:35:14 +0100982 Overlapped_clear(self);
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700983 return SetFromWindowsErr(err);
984 }
985}
986
987PyDoc_STRVAR(
988 Overlapped_WSARecv_doc,
989 "RecvFile(handle, size, flags) -> Overlapped[message]\n\n"
990 "Start overlapped receive");
991
992static PyObject *
993Overlapped_WSARecv(OverlappedObject *self, PyObject *args)
994{
995 HANDLE handle;
996 DWORD size;
997 DWORD flags = 0;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700998 PyObject *buf;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700999
1000 if (!PyArg_ParseTuple(args, F_HANDLE F_DWORD "|" F_DWORD,
1001 &handle, &size, &flags))
1002 return NULL;
1003
1004 if (self->type != TYPE_NONE) {
1005 PyErr_SetString(PyExc_ValueError, "operation already attempted");
1006 return NULL;
1007 }
1008
1009#if SIZEOF_SIZE_T <= SIZEOF_LONG
1010 size = Py_MIN(size, (DWORD)PY_SSIZE_T_MAX);
1011#endif
1012 buf = PyBytes_FromStringAndSize(NULL, Py_MAX(size, 1));
1013 if (buf == NULL)
1014 return NULL;
1015
1016 self->type = TYPE_READ;
1017 self->handle = handle;
Antoine Pitrou525f40d2017-10-19 21:46:40 +02001018 self->allocated_buffer = buf;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001019
Antoine Pitrou525f40d2017-10-19 21:46:40 +02001020 return do_WSARecv(self, handle, PyBytes_AS_STRING(buf), size, flags);
1021}
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001022
Antoine Pitrou525f40d2017-10-19 21:46:40 +02001023PyDoc_STRVAR(
1024 Overlapped_WSARecvInto_doc,
1025 "WSARecvInto(handle, buf, flags) -> Overlapped[bytes_transferred]\n\n"
1026 "Start overlapped receive");
1027
1028static PyObject *
1029Overlapped_WSARecvInto(OverlappedObject *self, PyObject *args)
1030{
1031 HANDLE handle;
1032 PyObject *bufobj;
1033 DWORD flags;
1034
1035 if (!PyArg_ParseTuple(args, F_HANDLE "O" F_DWORD,
1036 &handle, &bufobj, &flags))
1037 return NULL;
1038
1039 if (self->type != TYPE_NONE) {
1040 PyErr_SetString(PyExc_ValueError, "operation already attempted");
1041 return NULL;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001042 }
Antoine Pitrou525f40d2017-10-19 21:46:40 +02001043
1044 if (!PyArg_Parse(bufobj, "y*", &self->user_buffer))
1045 return NULL;
1046
1047#if SIZEOF_SIZE_T > SIZEOF_LONG
1048 if (self->user_buffer.len > (Py_ssize_t)ULONG_MAX) {
1049 PyBuffer_Release(&self->user_buffer);
1050 PyErr_SetString(PyExc_ValueError, "buffer too large");
1051 return NULL;
1052 }
1053#endif
1054
1055 self->type = TYPE_READINTO;
1056 self->handle = handle;
1057
1058 return do_WSARecv(self, handle, self->user_buffer.buf,
1059 (DWORD)self->user_buffer.len, flags);
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001060}
1061
1062PyDoc_STRVAR(
1063 Overlapped_WriteFile_doc,
1064 "WriteFile(handle, buf) -> Overlapped[bytes_transferred]\n\n"
1065 "Start overlapped write");
1066
1067static PyObject *
1068Overlapped_WriteFile(OverlappedObject *self, PyObject *args)
1069{
1070 HANDLE handle;
1071 PyObject *bufobj;
1072 DWORD written;
1073 BOOL ret;
1074 DWORD err;
1075
1076 if (!PyArg_ParseTuple(args, F_HANDLE "O", &handle, &bufobj))
1077 return NULL;
1078
1079 if (self->type != TYPE_NONE) {
1080 PyErr_SetString(PyExc_ValueError, "operation already attempted");
1081 return NULL;
1082 }
1083
Antoine Pitrou525f40d2017-10-19 21:46:40 +02001084 if (!PyArg_Parse(bufobj, "y*", &self->user_buffer))
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001085 return NULL;
1086
1087#if SIZEOF_SIZE_T > SIZEOF_LONG
Antoine Pitrou525f40d2017-10-19 21:46:40 +02001088 if (self->user_buffer.len > (Py_ssize_t)ULONG_MAX) {
1089 PyBuffer_Release(&self->user_buffer);
Oren Milmand83c23b2017-08-15 19:04:18 +03001090 PyErr_SetString(PyExc_ValueError, "buffer too large");
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001091 return NULL;
1092 }
1093#endif
1094
1095 self->type = TYPE_WRITE;
1096 self->handle = handle;
1097
1098 Py_BEGIN_ALLOW_THREADS
Antoine Pitrou525f40d2017-10-19 21:46:40 +02001099 ret = WriteFile(handle, self->user_buffer.buf,
1100 (DWORD)self->user_buffer.len,
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001101 &written, &self->overlapped);
1102 Py_END_ALLOW_THREADS
1103
1104 self->error = err = ret ? ERROR_SUCCESS : GetLastError();
1105 switch (err) {
1106 case ERROR_SUCCESS:
1107 case ERROR_IO_PENDING:
1108 Py_RETURN_NONE;
1109 default:
Victor Stinner54850852019-01-11 14:35:14 +01001110 Overlapped_clear(self);
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001111 return SetFromWindowsErr(err);
1112 }
1113}
1114
1115PyDoc_STRVAR(
1116 Overlapped_WSASend_doc,
1117 "WSASend(handle, buf, flags) -> Overlapped[bytes_transferred]\n\n"
1118 "Start overlapped send");
1119
1120static PyObject *
1121Overlapped_WSASend(OverlappedObject *self, PyObject *args)
1122{
1123 HANDLE handle;
1124 PyObject *bufobj;
1125 DWORD flags;
1126 DWORD written;
1127 WSABUF wsabuf;
1128 int ret;
1129 DWORD err;
1130
1131 if (!PyArg_ParseTuple(args, F_HANDLE "O" F_DWORD,
1132 &handle, &bufobj, &flags))
1133 return NULL;
1134
1135 if (self->type != TYPE_NONE) {
1136 PyErr_SetString(PyExc_ValueError, "operation already attempted");
1137 return NULL;
1138 }
1139
Antoine Pitrou525f40d2017-10-19 21:46:40 +02001140 if (!PyArg_Parse(bufobj, "y*", &self->user_buffer))
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001141 return NULL;
1142
1143#if SIZEOF_SIZE_T > SIZEOF_LONG
Antoine Pitrou525f40d2017-10-19 21:46:40 +02001144 if (self->user_buffer.len > (Py_ssize_t)ULONG_MAX) {
1145 PyBuffer_Release(&self->user_buffer);
Oren Milmand83c23b2017-08-15 19:04:18 +03001146 PyErr_SetString(PyExc_ValueError, "buffer too large");
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001147 return NULL;
1148 }
1149#endif
1150
1151 self->type = TYPE_WRITE;
1152 self->handle = handle;
Antoine Pitrou525f40d2017-10-19 21:46:40 +02001153 wsabuf.len = (DWORD)self->user_buffer.len;
1154 wsabuf.buf = self->user_buffer.buf;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001155
1156 Py_BEGIN_ALLOW_THREADS
1157 ret = WSASend((SOCKET)handle, &wsabuf, 1, &written, flags,
1158 &self->overlapped, NULL);
1159 Py_END_ALLOW_THREADS
1160
1161 self->error = err = (ret < 0 ? WSAGetLastError() : ERROR_SUCCESS);
1162 switch (err) {
1163 case ERROR_SUCCESS:
1164 case ERROR_IO_PENDING:
1165 Py_RETURN_NONE;
1166 default:
Victor Stinner54850852019-01-11 14:35:14 +01001167 Overlapped_clear(self);
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001168 return SetFromWindowsErr(err);
1169 }
1170}
1171
1172PyDoc_STRVAR(
1173 Overlapped_AcceptEx_doc,
1174 "AcceptEx(listen_handle, accept_handle) -> Overlapped[address_as_bytes]\n\n"
1175 "Start overlapped wait for client to connect");
1176
1177static PyObject *
1178Overlapped_AcceptEx(OverlappedObject *self, PyObject *args)
1179{
1180 SOCKET ListenSocket;
1181 SOCKET AcceptSocket;
1182 DWORD BytesReceived;
1183 DWORD size;
1184 PyObject *buf;
1185 BOOL ret;
1186 DWORD err;
1187
1188 if (!PyArg_ParseTuple(args, F_HANDLE F_HANDLE,
1189 &ListenSocket, &AcceptSocket))
1190 return NULL;
1191
1192 if (self->type != TYPE_NONE) {
1193 PyErr_SetString(PyExc_ValueError, "operation already attempted");
1194 return NULL;
1195 }
1196
1197 size = sizeof(struct sockaddr_in6) + 16;
1198 buf = PyBytes_FromStringAndSize(NULL, size*2);
1199 if (!buf)
1200 return NULL;
1201
1202 self->type = TYPE_ACCEPT;
1203 self->handle = (HANDLE)ListenSocket;
Antoine Pitrou525f40d2017-10-19 21:46:40 +02001204 self->allocated_buffer = buf;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001205
1206 Py_BEGIN_ALLOW_THREADS
1207 ret = Py_AcceptEx(ListenSocket, AcceptSocket, PyBytes_AS_STRING(buf),
1208 0, size, size, &BytesReceived, &self->overlapped);
1209 Py_END_ALLOW_THREADS
1210
1211 self->error = err = ret ? ERROR_SUCCESS : WSAGetLastError();
1212 switch (err) {
1213 case ERROR_SUCCESS:
1214 case ERROR_IO_PENDING:
1215 Py_RETURN_NONE;
1216 default:
Victor Stinner54850852019-01-11 14:35:14 +01001217 Overlapped_clear(self);
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001218 return SetFromWindowsErr(err);
1219 }
1220}
1221
1222
1223static int
1224parse_address(PyObject *obj, SOCKADDR *Address, int Length)
1225{
Steve Dowercc16be82016-09-08 10:35:16 -07001226 Py_UNICODE *Host;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001227 unsigned short Port;
1228 unsigned long FlowInfo;
1229 unsigned long ScopeId;
1230
1231 memset(Address, 0, Length);
1232
Steve Dowercc16be82016-09-08 10:35:16 -07001233 if (PyArg_ParseTuple(obj, "uH", &Host, &Port))
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001234 {
1235 Address->sa_family = AF_INET;
Steve Dowercc16be82016-09-08 10:35:16 -07001236 if (WSAStringToAddressW(Host, AF_INET, NULL, Address, &Length) < 0) {
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001237 SetFromWindowsErr(WSAGetLastError());
1238 return -1;
1239 }
1240 ((SOCKADDR_IN*)Address)->sin_port = htons(Port);
1241 return Length;
1242 }
Oren Milman1d1d3e92017-08-20 18:35:36 +03001243 else if (PyArg_ParseTuple(obj,
1244 "uHkk;ConnectEx(): illegal address_as_bytes "
1245 "argument", &Host, &Port, &FlowInfo, &ScopeId))
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001246 {
1247 PyErr_Clear();
1248 Address->sa_family = AF_INET6;
Steve Dowercc16be82016-09-08 10:35:16 -07001249 if (WSAStringToAddressW(Host, AF_INET6, NULL, Address, &Length) < 0) {
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001250 SetFromWindowsErr(WSAGetLastError());
1251 return -1;
1252 }
1253 ((SOCKADDR_IN6*)Address)->sin6_port = htons(Port);
1254 ((SOCKADDR_IN6*)Address)->sin6_flowinfo = FlowInfo;
1255 ((SOCKADDR_IN6*)Address)->sin6_scope_id = ScopeId;
1256 return Length;
1257 }
1258
1259 return -1;
1260}
1261
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001262PyDoc_STRVAR(
1263 Overlapped_ConnectEx_doc,
1264 "ConnectEx(client_handle, address_as_bytes) -> Overlapped[None]\n\n"
1265 "Start overlapped connect. client_handle should be unbound.");
1266
1267static PyObject *
1268Overlapped_ConnectEx(OverlappedObject *self, PyObject *args)
1269{
1270 SOCKET ConnectSocket;
1271 PyObject *AddressObj;
1272 char AddressBuf[sizeof(struct sockaddr_in6)];
1273 SOCKADDR *Address = (SOCKADDR*)AddressBuf;
1274 int Length;
1275 BOOL ret;
1276 DWORD err;
1277
Oren Milman1d1d3e92017-08-20 18:35:36 +03001278 if (!PyArg_ParseTuple(args, F_HANDLE "O!:ConnectEx",
1279 &ConnectSocket, &PyTuple_Type, &AddressObj))
1280 {
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001281 return NULL;
Oren Milman1d1d3e92017-08-20 18:35:36 +03001282 }
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001283
1284 if (self->type != TYPE_NONE) {
1285 PyErr_SetString(PyExc_ValueError, "operation already attempted");
1286 return NULL;
1287 }
1288
1289 Length = sizeof(AddressBuf);
1290 Length = parse_address(AddressObj, Address, Length);
1291 if (Length < 0)
1292 return NULL;
1293
1294 self->type = TYPE_CONNECT;
1295 self->handle = (HANDLE)ConnectSocket;
1296
1297 Py_BEGIN_ALLOW_THREADS
1298 ret = Py_ConnectEx(ConnectSocket, Address, Length,
1299 NULL, 0, NULL, &self->overlapped);
1300 Py_END_ALLOW_THREADS
1301
1302 self->error = err = ret ? ERROR_SUCCESS : WSAGetLastError();
1303 switch (err) {
1304 case ERROR_SUCCESS:
1305 case ERROR_IO_PENDING:
1306 Py_RETURN_NONE;
1307 default:
Victor Stinner54850852019-01-11 14:35:14 +01001308 Overlapped_clear(self);
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001309 return SetFromWindowsErr(err);
1310 }
1311}
1312
1313PyDoc_STRVAR(
1314 Overlapped_DisconnectEx_doc,
1315 "DisconnectEx(handle, flags) -> Overlapped[None]\n\n"
1316 "Start overlapped connect. client_handle should be unbound.");
1317
1318static PyObject *
1319Overlapped_DisconnectEx(OverlappedObject *self, PyObject *args)
1320{
1321 SOCKET Socket;
1322 DWORD flags;
1323 BOOL ret;
1324 DWORD err;
1325
1326 if (!PyArg_ParseTuple(args, F_HANDLE F_DWORD, &Socket, &flags))
1327 return NULL;
1328
1329 if (self->type != TYPE_NONE) {
1330 PyErr_SetString(PyExc_ValueError, "operation already attempted");
1331 return NULL;
1332 }
1333
1334 self->type = TYPE_DISCONNECT;
1335 self->handle = (HANDLE)Socket;
1336
1337 Py_BEGIN_ALLOW_THREADS
1338 ret = Py_DisconnectEx(Socket, &self->overlapped, flags, 0);
1339 Py_END_ALLOW_THREADS
1340
1341 self->error = err = ret ? ERROR_SUCCESS : WSAGetLastError();
1342 switch (err) {
1343 case ERROR_SUCCESS:
1344 case ERROR_IO_PENDING:
1345 Py_RETURN_NONE;
1346 default:
Victor Stinner54850852019-01-11 14:35:14 +01001347 Overlapped_clear(self);
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001348 return SetFromWindowsErr(err);
1349 }
1350}
1351
1352PyDoc_STRVAR(
Andrew Svetlova19fb3c2018-02-25 19:32:14 +03001353 Overlapped_TransmitFile_doc,
1354 "TransmitFile(socket, file, offset, offset_high, "
1355 "count_to_write, count_per_send, flags) "
1356 "-> Overlapped[None]\n\n"
1357 "Transmit file data over a connected socket.");
1358
1359static PyObject *
1360Overlapped_TransmitFile(OverlappedObject *self, PyObject *args)
1361{
1362 SOCKET Socket;
1363 HANDLE File;
1364 DWORD offset;
1365 DWORD offset_high;
1366 DWORD count_to_write;
1367 DWORD count_per_send;
1368 DWORD flags;
1369 BOOL ret;
1370 DWORD err;
1371
1372 if (!PyArg_ParseTuple(args,
1373 F_HANDLE F_HANDLE F_DWORD F_DWORD
1374 F_DWORD F_DWORD F_DWORD,
1375 &Socket, &File, &offset, &offset_high,
1376 &count_to_write, &count_per_send,
1377 &flags))
1378 return NULL;
1379
1380 if (self->type != TYPE_NONE) {
1381 PyErr_SetString(PyExc_ValueError, "operation already attempted");
1382 return NULL;
1383 }
1384
1385 self->type = TYPE_TRANSMIT_FILE;
1386 self->handle = (HANDLE)Socket;
1387 self->overlapped.Offset = offset;
1388 self->overlapped.OffsetHigh = offset_high;
1389
1390 Py_BEGIN_ALLOW_THREADS
1391 ret = Py_TransmitFile(Socket, File, count_to_write, count_per_send,
1392 &self->overlapped,
1393 NULL, flags);
1394 Py_END_ALLOW_THREADS
1395
1396 self->error = err = ret ? ERROR_SUCCESS : WSAGetLastError();
1397 switch (err) {
1398 case ERROR_SUCCESS:
1399 case ERROR_IO_PENDING:
1400 Py_RETURN_NONE;
1401 default:
Victor Stinner54850852019-01-11 14:35:14 +01001402 Overlapped_clear(self);
Andrew Svetlova19fb3c2018-02-25 19:32:14 +03001403 return SetFromWindowsErr(err);
1404 }
1405}
1406
1407PyDoc_STRVAR(
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001408 Overlapped_ConnectNamedPipe_doc,
1409 "ConnectNamedPipe(handle) -> Overlapped[None]\n\n"
1410 "Start overlapped wait for a client to connect.");
1411
1412static PyObject *
1413Overlapped_ConnectNamedPipe(OverlappedObject *self, PyObject *args)
1414{
1415 HANDLE Pipe;
1416 BOOL ret;
1417 DWORD err;
1418
1419 if (!PyArg_ParseTuple(args, F_HANDLE, &Pipe))
1420 return NULL;
1421
1422 if (self->type != TYPE_NONE) {
1423 PyErr_SetString(PyExc_ValueError, "operation already attempted");
1424 return NULL;
1425 }
1426
1427 self->type = TYPE_CONNECT_NAMED_PIPE;
1428 self->handle = Pipe;
1429
1430 Py_BEGIN_ALLOW_THREADS
1431 ret = ConnectNamedPipe(Pipe, &self->overlapped);
1432 Py_END_ALLOW_THREADS
1433
1434 self->error = err = ret ? ERROR_SUCCESS : GetLastError();
1435 switch (err) {
1436 case ERROR_PIPE_CONNECTED:
1437 mark_as_completed(&self->overlapped);
Victor Stinner2b77c542015-01-22 23:50:03 +01001438 Py_RETURN_TRUE;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001439 case ERROR_SUCCESS:
1440 case ERROR_IO_PENDING:
Victor Stinner2b77c542015-01-22 23:50:03 +01001441 Py_RETURN_FALSE;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001442 default:
Victor Stinner54850852019-01-11 14:35:14 +01001443 Overlapped_clear(self);
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001444 return SetFromWindowsErr(err);
1445 }
1446}
1447
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001448PyDoc_STRVAR(
Victor Stinner7ffa2c52015-01-22 22:55:08 +01001449 ConnectPipe_doc,
1450 "ConnectPipe(addr) -> pipe_handle\n\n"
1451 "Connect to the pipe for asynchronous I/O (overlapped).");
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001452
1453static PyObject *
Andrew Svetlovbafd4b52019-05-28 12:52:15 +03001454overlapped_ConnectPipe(PyObject *self, PyObject *args)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001455{
Victor Stinner7ffa2c52015-01-22 22:55:08 +01001456 PyObject *AddressObj;
1457 wchar_t *Address;
1458 HANDLE PipeHandle;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001459
Victor Stinner7ffa2c52015-01-22 22:55:08 +01001460 if (!PyArg_ParseTuple(args, "U", &AddressObj))
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001461 return NULL;
1462
Victor Stinner7ffa2c52015-01-22 22:55:08 +01001463 Address = PyUnicode_AsWideCharString(AddressObj, NULL);
1464 if (Address == NULL)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001465 return NULL;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001466
Victor Stinner498b1f62015-01-26 22:43:39 +01001467 Py_BEGIN_ALLOW_THREADS
Victor Stinner7ffa2c52015-01-22 22:55:08 +01001468 PipeHandle = CreateFileW(Address,
1469 GENERIC_READ | GENERIC_WRITE,
1470 0, NULL, OPEN_EXISTING,
1471 FILE_FLAG_OVERLAPPED, NULL);
Victor Stinner498b1f62015-01-26 22:43:39 +01001472 Py_END_ALLOW_THREADS
1473
Victor Stinner7ffa2c52015-01-22 22:55:08 +01001474 PyMem_Free(Address);
1475 if (PipeHandle == INVALID_HANDLE_VALUE)
1476 return SetFromWindowsErr(0);
1477 return Py_BuildValue(F_HANDLE, PipeHandle);
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001478}
1479
1480static PyObject*
1481Overlapped_getaddress(OverlappedObject *self)
1482{
1483 return PyLong_FromVoidPtr(&self->overlapped);
1484}
1485
1486static PyObject*
1487Overlapped_getpending(OverlappedObject *self)
1488{
1489 return PyBool_FromLong(!HasOverlappedIoCompleted(&self->overlapped) &&
1490 self->type != TYPE_NOT_STARTED);
1491}
1492
Victor Stinner54850852019-01-11 14:35:14 +01001493static int
1494Overlapped_traverse(OverlappedObject *self, visitproc visit, void *arg)
1495{
1496 switch (self->type) {
1497 case TYPE_READ:
1498 case TYPE_ACCEPT:
1499 Py_VISIT(self->allocated_buffer);
1500 break;
1501 case TYPE_WRITE:
Andrew Svetlovbafd4b52019-05-28 12:52:15 +03001502 case TYPE_WRITE_TO:
Victor Stinner54850852019-01-11 14:35:14 +01001503 case TYPE_READINTO:
1504 if (self->user_buffer.obj) {
1505 Py_VISIT(&self->user_buffer.obj);
1506 }
1507 break;
Andrew Svetlovbafd4b52019-05-28 12:52:15 +03001508 case TYPE_READ_FROM:
1509 if(self->read_from.result) {
1510 Py_VISIT(self->read_from.result);
1511 }
1512 if(self->read_from.allocated_buffer) {
1513 Py_VISIT(self->read_from.allocated_buffer);
1514 }
Victor Stinner54850852019-01-11 14:35:14 +01001515 }
1516 return 0;
1517}
1518
Andrew Svetlovbafd4b52019-05-28 12:52:15 +03001519// UDP functions
1520
1521PyDoc_STRVAR(
1522 WSAConnect_doc,
1523 "WSAConnect(client_handle, address_as_bytes) -> Overlapped[None]\n\n"
1524 "Bind a remote address to a connectionless (UDP) socket");
1525
1526/*
1527 * Note: WSAConnect does not support Overlapped I/O so this function should
1528 * _only_ be used for connectionless sockets (UDP).
1529 */
1530static PyObject *
1531overlapped_WSAConnect(PyObject *self, PyObject *args)
1532{
1533 SOCKET ConnectSocket;
1534 PyObject *AddressObj;
1535 char AddressBuf[sizeof(struct sockaddr_in6)];
1536 SOCKADDR *Address = (SOCKADDR*)AddressBuf;
1537 int Length;
1538 int err;
1539
1540 if (!PyArg_ParseTuple(args, F_HANDLE "O", &ConnectSocket, &AddressObj)) {
1541 return NULL;
1542 }
1543
1544 Length = sizeof(AddressBuf);
1545 Length = parse_address(AddressObj, Address, Length);
1546 if (Length < 0) {
1547 return NULL;
1548 }
1549
1550 Py_BEGIN_ALLOW_THREADS
1551 // WSAConnect does not support overlapped I/O so this call will
1552 // successfully complete immediately.
1553 err = WSAConnect(ConnectSocket, Address, Length,
1554 NULL, NULL, NULL, NULL);
1555 Py_END_ALLOW_THREADS
1556
1557 if (err == 0) {
1558 Py_RETURN_NONE;
1559 }
1560 else {
1561 return SetFromWindowsErr(WSAGetLastError());
1562 }
1563}
1564
1565PyDoc_STRVAR(
1566 Overlapped_WSASendTo_doc,
1567 "WSASendTo(handle, buf, flags, address_as_bytes) -> "
1568 "Overlapped[bytes_transferred]\n\n"
1569 "Start overlapped sendto over a connectionless (UDP) socket");
1570
1571static PyObject *
1572Overlapped_WSASendTo(OverlappedObject *self, PyObject *args)
1573{
1574 HANDLE handle;
1575 PyObject *bufobj;
1576 DWORD flags;
1577 PyObject *AddressObj;
1578 char AddressBuf[sizeof(struct sockaddr_in6)];
1579 SOCKADDR *Address = (SOCKADDR*)AddressBuf;
1580 int AddressLength;
1581 DWORD written;
1582 WSABUF wsabuf;
1583 int ret;
1584 DWORD err;
1585
1586 if (!PyArg_ParseTuple(args, F_HANDLE "O" F_DWORD "O",
1587 &handle, &bufobj, &flags, &AddressObj))
1588 {
1589 return NULL;
1590 }
1591
1592 // Parse the "to" address
1593 AddressLength = sizeof(AddressBuf);
1594 AddressLength = parse_address(AddressObj, Address, AddressLength);
1595 if (AddressLength < 0) {
1596 return NULL;
1597 }
1598
1599 if (self->type != TYPE_NONE) {
1600 PyErr_SetString(PyExc_ValueError, "operation already attempted");
1601 return NULL;
1602 }
1603
1604 if (!PyArg_Parse(bufobj, "y*", &self->user_buffer)) {
1605 return NULL;
1606 }
1607
1608#if SIZEOF_SIZE_T > SIZEOF_LONG
1609 if (self->user_buffer.len > (Py_ssize_t)ULONG_MAX) {
1610 PyBuffer_Release(&self->user_buffer);
1611 PyErr_SetString(PyExc_ValueError, "buffer too large");
1612 return NULL;
1613 }
1614#endif
1615
1616 self->type = TYPE_WRITE_TO;
1617 self->handle = handle;
1618 wsabuf.len = (DWORD)self->user_buffer.len;
1619 wsabuf.buf = self->user_buffer.buf;
1620
1621 Py_BEGIN_ALLOW_THREADS
1622 ret = WSASendTo((SOCKET)handle, &wsabuf, 1, &written, flags,
1623 Address, AddressLength, &self->overlapped, NULL);
1624 Py_END_ALLOW_THREADS
1625
1626 self->error = err = (ret == SOCKET_ERROR ? WSAGetLastError() :
1627 ERROR_SUCCESS);
1628
1629 switch(err) {
1630 case ERROR_SUCCESS:
1631 case ERROR_IO_PENDING:
1632 Py_RETURN_NONE;
1633 default:
1634 self->type = TYPE_NOT_STARTED;
1635 return SetFromWindowsErr(err);
1636 }
1637}
1638
1639
1640
1641PyDoc_STRVAR(
1642 Overlapped_WSARecvFrom_doc,
1643 "RecvFile(handle, size, flags) -> Overlapped[(message, (host, port))]\n\n"
1644 "Start overlapped receive");
1645
1646static PyObject *
1647Overlapped_WSARecvFrom(OverlappedObject *self, PyObject *args)
1648{
1649 HANDLE handle;
1650 DWORD size;
1651 DWORD flags = 0;
1652 DWORD nread;
1653 PyObject *buf;
1654 WSABUF wsabuf;
1655 int ret;
1656 DWORD err;
1657
1658 if (!PyArg_ParseTuple(args, F_HANDLE F_DWORD "|" F_DWORD,
1659 &handle, &size, &flags))
1660 {
1661 return NULL;
1662 }
1663
1664 if (self->type != TYPE_NONE) {
1665 PyErr_SetString(PyExc_ValueError, "operation already attempted");
1666 return NULL;
1667 }
1668
1669#if SIZEOF_SIZE_T <= SIZEOF_LONG
1670 size = Py_MIN(size, (DWORD)PY_SSIZE_T_MAX);
1671#endif
1672 buf = PyBytes_FromStringAndSize(NULL, Py_MAX(size, 1));
1673 if (buf == NULL) {
1674 return NULL;
1675 }
1676
1677 wsabuf.len = size;
1678 wsabuf.buf = PyBytes_AS_STRING(buf);
1679
1680 self->type = TYPE_READ_FROM;
1681 self->handle = handle;
1682 self->read_from.allocated_buffer = buf;
1683 memset(&self->read_from.address, 0, sizeof(self->read_from.address));
1684 self->read_from.address_length = sizeof(self->read_from.address);
1685
1686 Py_BEGIN_ALLOW_THREADS
1687 ret = WSARecvFrom((SOCKET)handle, &wsabuf, 1, &nread, &flags,
1688 (SOCKADDR*)&self->read_from.address,
1689 &self->read_from.address_length,
1690 &self->overlapped, NULL);
1691 Py_END_ALLOW_THREADS
1692
1693 self->error = err = (ret < 0 ? WSAGetLastError() : ERROR_SUCCESS);
1694
1695 switch(err) {
1696 case ERROR_BROKEN_PIPE:
1697 mark_as_completed(&self->overlapped);
1698 return SetFromWindowsErr(err);
1699 case ERROR_SUCCESS:
1700 case ERROR_MORE_DATA:
1701 case ERROR_IO_PENDING:
1702 Py_RETURN_NONE;
1703 default:
1704 self->type = TYPE_NOT_STARTED;
1705 return SetFromWindowsErr(err);
1706 }
1707}
1708
Victor Stinner54850852019-01-11 14:35:14 +01001709
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001710static PyMethodDef Overlapped_methods[] = {
1711 {"getresult", (PyCFunction) Overlapped_getresult,
1712 METH_VARARGS, Overlapped_getresult_doc},
1713 {"cancel", (PyCFunction) Overlapped_cancel,
1714 METH_NOARGS, Overlapped_cancel_doc},
1715 {"ReadFile", (PyCFunction) Overlapped_ReadFile,
1716 METH_VARARGS, Overlapped_ReadFile_doc},
Antoine Pitrou525f40d2017-10-19 21:46:40 +02001717 {"ReadFileInto", (PyCFunction) Overlapped_ReadFileInto,
1718 METH_VARARGS, Overlapped_ReadFileInto_doc},
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001719 {"WSARecv", (PyCFunction) Overlapped_WSARecv,
1720 METH_VARARGS, Overlapped_WSARecv_doc},
Antoine Pitrou525f40d2017-10-19 21:46:40 +02001721 {"WSARecvInto", (PyCFunction) Overlapped_WSARecvInto,
1722 METH_VARARGS, Overlapped_WSARecvInto_doc},
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001723 {"WriteFile", (PyCFunction) Overlapped_WriteFile,
1724 METH_VARARGS, Overlapped_WriteFile_doc},
1725 {"WSASend", (PyCFunction) Overlapped_WSASend,
1726 METH_VARARGS, Overlapped_WSASend_doc},
1727 {"AcceptEx", (PyCFunction) Overlapped_AcceptEx,
1728 METH_VARARGS, Overlapped_AcceptEx_doc},
1729 {"ConnectEx", (PyCFunction) Overlapped_ConnectEx,
1730 METH_VARARGS, Overlapped_ConnectEx_doc},
1731 {"DisconnectEx", (PyCFunction) Overlapped_DisconnectEx,
1732 METH_VARARGS, Overlapped_DisconnectEx_doc},
Andrew Svetlova19fb3c2018-02-25 19:32:14 +03001733 {"TransmitFile", (PyCFunction) Overlapped_TransmitFile,
1734 METH_VARARGS, Overlapped_TransmitFile_doc},
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001735 {"ConnectNamedPipe", (PyCFunction) Overlapped_ConnectNamedPipe,
1736 METH_VARARGS, Overlapped_ConnectNamedPipe_doc},
Andrew Svetlovbafd4b52019-05-28 12:52:15 +03001737 {"WSARecvFrom", (PyCFunction) Overlapped_WSARecvFrom,
1738 METH_VARARGS, Overlapped_WSARecvFrom_doc },
1739 {"WSASendTo", (PyCFunction) Overlapped_WSASendTo,
1740 METH_VARARGS, Overlapped_WSASendTo_doc },
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001741 {NULL}
1742};
1743
1744static PyMemberDef Overlapped_members[] = {
1745 {"error", T_ULONG,
1746 offsetof(OverlappedObject, error),
1747 READONLY, "Error from last operation"},
1748 {"event", T_HANDLE,
1749 offsetof(OverlappedObject, overlapped) + offsetof(OVERLAPPED, hEvent),
1750 READONLY, "Overlapped event handle"},
1751 {NULL}
1752};
1753
1754static PyGetSetDef Overlapped_getsets[] = {
1755 {"address", (getter)Overlapped_getaddress, NULL,
1756 "Address of overlapped structure"},
1757 {"pending", (getter)Overlapped_getpending, NULL,
1758 "Whether the operation is pending"},
1759 {NULL},
1760};
1761
1762PyTypeObject OverlappedType = {
1763 PyVarObject_HEAD_INIT(NULL, 0)
1764 /* tp_name */ "_overlapped.Overlapped",
1765 /* tp_basicsize */ sizeof(OverlappedObject),
1766 /* tp_itemsize */ 0,
1767 /* tp_dealloc */ (destructor) Overlapped_dealloc,
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001768 /* tp_vectorcall_offset */ 0,
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001769 /* tp_getattr */ 0,
1770 /* tp_setattr */ 0,
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001771 /* tp_as_async */ 0,
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001772 /* tp_repr */ 0,
1773 /* tp_as_number */ 0,
1774 /* tp_as_sequence */ 0,
1775 /* tp_as_mapping */ 0,
1776 /* tp_hash */ 0,
1777 /* tp_call */ 0,
1778 /* tp_str */ 0,
1779 /* tp_getattro */ 0,
1780 /* tp_setattro */ 0,
1781 /* tp_as_buffer */ 0,
1782 /* tp_flags */ Py_TPFLAGS_DEFAULT,
1783 /* tp_doc */ "OVERLAPPED structure wrapper",
Victor Stinner54850852019-01-11 14:35:14 +01001784 /* tp_traverse */ (traverseproc)Overlapped_traverse,
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001785 /* tp_clear */ 0,
1786 /* tp_richcompare */ 0,
1787 /* tp_weaklistoffset */ 0,
1788 /* tp_iter */ 0,
1789 /* tp_iternext */ 0,
1790 /* tp_methods */ Overlapped_methods,
1791 /* tp_members */ Overlapped_members,
1792 /* tp_getset */ Overlapped_getsets,
1793 /* tp_base */ 0,
1794 /* tp_dict */ 0,
1795 /* tp_descr_get */ 0,
1796 /* tp_descr_set */ 0,
1797 /* tp_dictoffset */ 0,
1798 /* tp_init */ 0,
1799 /* tp_alloc */ 0,
1800 /* tp_new */ Overlapped_new,
1801};
1802
1803static PyMethodDef overlapped_functions[] = {
1804 {"CreateIoCompletionPort", overlapped_CreateIoCompletionPort,
1805 METH_VARARGS, CreateIoCompletionPort_doc},
1806 {"GetQueuedCompletionStatus", overlapped_GetQueuedCompletionStatus,
1807 METH_VARARGS, GetQueuedCompletionStatus_doc},
1808 {"PostQueuedCompletionStatus", overlapped_PostQueuedCompletionStatus,
1809 METH_VARARGS, PostQueuedCompletionStatus_doc},
1810 {"FormatMessage", overlapped_FormatMessage,
1811 METH_VARARGS, FormatMessage_doc},
1812 {"BindLocal", overlapped_BindLocal,
1813 METH_VARARGS, BindLocal_doc},
Guido van Rossum90fb9142013-10-30 14:44:05 -07001814 {"RegisterWaitWithQueue", overlapped_RegisterWaitWithQueue,
1815 METH_VARARGS, RegisterWaitWithQueue_doc},
1816 {"UnregisterWait", overlapped_UnregisterWait,
1817 METH_VARARGS, UnregisterWait_doc},
Victor Stinnerd0a28de2015-01-21 23:39:51 +01001818 {"UnregisterWaitEx", overlapped_UnregisterWaitEx,
1819 METH_VARARGS, UnregisterWaitEx_doc},
Guido van Rossum90fb9142013-10-30 14:44:05 -07001820 {"CreateEvent", overlapped_CreateEvent,
1821 METH_VARARGS, CreateEvent_doc},
1822 {"SetEvent", overlapped_SetEvent,
1823 METH_VARARGS, SetEvent_doc},
1824 {"ResetEvent", overlapped_ResetEvent,
1825 METH_VARARGS, ResetEvent_doc},
Andrew Svetlovbafd4b52019-05-28 12:52:15 +03001826 {"ConnectPipe", overlapped_ConnectPipe,
Victor Stinner7ffa2c52015-01-22 22:55:08 +01001827 METH_VARARGS, ConnectPipe_doc},
Andrew Svetlovbafd4b52019-05-28 12:52:15 +03001828 {"WSAConnect", overlapped_WSAConnect,
1829 METH_VARARGS, WSAConnect_doc},
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001830 {NULL}
1831};
1832
1833static struct PyModuleDef overlapped_module = {
1834 PyModuleDef_HEAD_INIT,
1835 "_overlapped",
1836 NULL,
1837 -1,
1838 overlapped_functions,
1839 NULL,
1840 NULL,
1841 NULL,
1842 NULL
1843};
1844
1845#define WINAPI_CONSTANT(fmt, con) \
1846 PyDict_SetItemString(d, #con, Py_BuildValue(fmt, con))
1847
1848PyMODINIT_FUNC
1849PyInit__overlapped(void)
1850{
1851 PyObject *m, *d;
1852
1853 /* Ensure WSAStartup() called before initializing function pointers */
1854 m = PyImport_ImportModule("_socket");
1855 if (!m)
1856 return NULL;
1857 Py_DECREF(m);
1858
1859 if (initialize_function_pointers() < 0)
1860 return NULL;
1861
1862 if (PyType_Ready(&OverlappedType) < 0)
1863 return NULL;
1864
1865 m = PyModule_Create(&overlapped_module);
1866 if (PyModule_AddObject(m, "Overlapped", (PyObject *)&OverlappedType) < 0)
1867 return NULL;
1868
1869 d = PyModule_GetDict(m);
1870
1871 WINAPI_CONSTANT(F_DWORD, ERROR_IO_PENDING);
1872 WINAPI_CONSTANT(F_DWORD, ERROR_NETNAME_DELETED);
Andrew Svetlov7c684072018-01-27 21:22:47 +02001873 WINAPI_CONSTANT(F_DWORD, ERROR_OPERATION_ABORTED);
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001874 WINAPI_CONSTANT(F_DWORD, ERROR_SEM_TIMEOUT);
Victor Stinner7ffa2c52015-01-22 22:55:08 +01001875 WINAPI_CONSTANT(F_DWORD, ERROR_PIPE_BUSY);
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001876 WINAPI_CONSTANT(F_DWORD, INFINITE);
1877 WINAPI_CONSTANT(F_HANDLE, INVALID_HANDLE_VALUE);
1878 WINAPI_CONSTANT(F_HANDLE, NULL);
1879 WINAPI_CONSTANT(F_DWORD, SO_UPDATE_ACCEPT_CONTEXT);
1880 WINAPI_CONSTANT(F_DWORD, SO_UPDATE_CONNECT_CONTEXT);
1881 WINAPI_CONSTANT(F_DWORD, TF_REUSE_SOCKET);
1882
1883 return m;
1884}