blob: 52ed0bc284bcc0c14026925208c7f549f53ef271 [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 |
Zackery Spytza6563652019-09-09 03:20:39 -0600503 FORMAT_MESSAGE_FROM_SYSTEM |
504 FORMAT_MESSAGE_IGNORE_INSERTS,
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700505 NULL,
506 code,
507 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
508 (LPWSTR) &lpMsgBuf,
509 0,
510 NULL);
511 if (n) {
512 while (iswspace(lpMsgBuf[n-1]))
513 --n;
514 lpMsgBuf[n] = L'\0';
515 res = Py_BuildValue("u", lpMsgBuf);
516 } else {
517 res = PyUnicode_FromFormat("unknown error code %u", code);
518 }
519 LocalFree(lpMsgBuf);
520 return res;
521}
522
523
524/*
525 * Mark operation as completed - used when reading produces ERROR_BROKEN_PIPE
526 */
527
528static void
529mark_as_completed(OVERLAPPED *ov)
530{
531 ov->Internal = 0;
532 if (ov->hEvent != NULL)
533 SetEvent(ov->hEvent);
534}
535
536/*
537 * A Python object wrapping an OVERLAPPED structure and other useful data
538 * for overlapped I/O
539 */
540
541PyDoc_STRVAR(
542 Overlapped_doc,
543 "Overlapped object");
544
545static PyObject *
546Overlapped_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
547{
548 OverlappedObject *self;
549 HANDLE event = INVALID_HANDLE_VALUE;
550 static char *kwlist[] = {"event", NULL};
551
552 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|" F_HANDLE, kwlist, &event))
553 return NULL;
554
555 if (event == INVALID_HANDLE_VALUE) {
556 event = CreateEvent(NULL, TRUE, FALSE, NULL);
557 if (event == NULL)
558 return SetFromWindowsErr(0);
559 }
560
561 self = PyObject_New(OverlappedObject, type);
562 if (self == NULL) {
563 if (event != NULL)
564 CloseHandle(event);
565 return NULL;
566 }
567
568 self->handle = NULL;
569 self->error = 0;
570 self->type = TYPE_NONE;
Antoine Pitrou525f40d2017-10-19 21:46:40 +0200571 self->allocated_buffer = NULL;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700572 memset(&self->overlapped, 0, sizeof(OVERLAPPED));
Antoine Pitrou525f40d2017-10-19 21:46:40 +0200573 memset(&self->user_buffer, 0, sizeof(Py_buffer));
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700574 if (event)
575 self->overlapped.hEvent = event;
576 return (PyObject *)self;
577}
578
Victor Stinner54850852019-01-11 14:35:14 +0100579
580/* Note (bpo-32710): OverlappedType.tp_clear is not defined to not release
581 buffers while overlapped are still running, to prevent a crash. */
582static int
583Overlapped_clear(OverlappedObject *self)
584{
585 switch (self->type) {
Andrew Svetlovbafd4b52019-05-28 12:52:15 +0300586 case TYPE_READ:
587 case TYPE_ACCEPT: {
588 Py_CLEAR(self->allocated_buffer);
589 break;
Victor Stinner54850852019-01-11 14:35:14 +0100590 }
Andrew Svetlovbafd4b52019-05-28 12:52:15 +0300591 case TYPE_READ_FROM: {
592 // An initial call to WSARecvFrom will only allocate the buffer.
593 // The result tuple of (message, address) is only
594 // allocated _after_ a message has been received.
595 if(self->read_from.result) {
596 // We've received a message, free the result tuple.
597 Py_CLEAR(self->read_from.result);
598 }
599 if(self->read_from.allocated_buffer) {
600 Py_CLEAR(self->read_from.allocated_buffer);
601 }
602 break;
603 }
604 case TYPE_WRITE:
605 case TYPE_WRITE_TO:
606 case TYPE_READINTO: {
607 if (self->user_buffer.obj) {
608 PyBuffer_Release(&self->user_buffer);
609 }
610 break;
611 }
Victor Stinner54850852019-01-11 14:35:14 +0100612 }
613 self->type = TYPE_NOT_STARTED;
614 return 0;
615}
616
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700617static void
618Overlapped_dealloc(OverlappedObject *self)
619{
620 DWORD bytes;
621 DWORD olderr = GetLastError();
622 BOOL wait = FALSE;
623 BOOL ret;
624
625 if (!HasOverlappedIoCompleted(&self->overlapped) &&
626 self->type != TYPE_NOT_STARTED)
627 {
628 if (Py_CancelIoEx && Py_CancelIoEx(self->handle, &self->overlapped))
629 wait = TRUE;
630
631 Py_BEGIN_ALLOW_THREADS
632 ret = GetOverlappedResult(self->handle, &self->overlapped,
633 &bytes, wait);
634 Py_END_ALLOW_THREADS
635
636 switch (ret ? ERROR_SUCCESS : GetLastError()) {
637 case ERROR_SUCCESS:
638 case ERROR_NOT_FOUND:
639 case ERROR_OPERATION_ABORTED:
640 break;
641 default:
642 PyErr_Format(
643 PyExc_RuntimeError,
644 "%R still has pending operation at "
645 "deallocation, the process may crash", self);
646 PyErr_WriteUnraisable(NULL);
647 }
648 }
649
Victor Stinner54850852019-01-11 14:35:14 +0100650 if (self->overlapped.hEvent != NULL) {
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700651 CloseHandle(self->overlapped.hEvent);
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700652 }
Victor Stinner54850852019-01-11 14:35:14 +0100653
654 Overlapped_clear(self);
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700655 PyObject_Del(self);
656 SetLastError(olderr);
657}
658
Andrew Svetlovbafd4b52019-05-28 12:52:15 +0300659
660/* Convert IPv4 sockaddr to a Python str. */
661
662static PyObject *
663make_ipv4_addr(const struct sockaddr_in *addr)
664{
665 char buf[INET_ADDRSTRLEN];
666 if (inet_ntop(AF_INET, &addr->sin_addr, buf, sizeof(buf)) == NULL) {
667 PyErr_SetFromErrno(PyExc_OSError);
668 return NULL;
669 }
670 return PyUnicode_FromString(buf);
671}
672
673#ifdef ENABLE_IPV6
674/* Convert IPv6 sockaddr to a Python str. */
675
676static PyObject *
677make_ipv6_addr(const struct sockaddr_in6 *addr)
678{
679 char buf[INET6_ADDRSTRLEN];
680 if (inet_ntop(AF_INET6, &addr->sin6_addr, buf, sizeof(buf)) == NULL) {
681 PyErr_SetFromErrno(PyExc_OSError);
682 return NULL;
683 }
684 return PyUnicode_FromString(buf);
685}
686#endif
687
688static PyObject*
689unparse_address(LPSOCKADDR Address, DWORD Length)
690{
691 /* The function is adopted from mocketmodule.c makesockaddr()*/
692
693 switch(Address->sa_family) {
694 case AF_INET: {
695 const struct sockaddr_in *a = (const struct sockaddr_in *)Address;
696 PyObject *addrobj = make_ipv4_addr(a);
697 PyObject *ret = NULL;
698 if (addrobj) {
699 ret = Py_BuildValue("Oi", addrobj, ntohs(a->sin_port));
700 Py_DECREF(addrobj);
701 }
702 return ret;
703 }
704#ifdef ENABLE_IPV6
705 case AF_INET6: {
706 const struct sockaddr_in6 *a = (const struct sockaddr_in6 *)Address;
707 PyObject *addrobj = make_ipv6_addr(a);
708 PyObject *ret = NULL;
709 if (addrobj) {
710 ret = Py_BuildValue("OiII",
711 addrobj,
712 ntohs(a->sin6_port),
713 ntohl(a->sin6_flowinfo),
714 a->sin6_scope_id);
715 Py_DECREF(addrobj);
716 }
717 return ret;
718 }
719#endif /* ENABLE_IPV6 */
720 default: {
721 return SetFromWindowsErr(ERROR_INVALID_PARAMETER);
722 }
723 }
724}
725
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700726PyDoc_STRVAR(
727 Overlapped_cancel_doc,
728 "cancel() -> None\n\n"
729 "Cancel overlapped operation");
730
731static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530732Overlapped_cancel(OverlappedObject *self, PyObject *Py_UNUSED(ignored))
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700733{
734 BOOL ret = TRUE;
735
736 if (self->type == TYPE_NOT_STARTED
737 || self->type == TYPE_WAIT_NAMED_PIPE_AND_CONNECT)
738 Py_RETURN_NONE;
739
740 if (!HasOverlappedIoCompleted(&self->overlapped)) {
741 Py_BEGIN_ALLOW_THREADS
742 if (Py_CancelIoEx)
743 ret = Py_CancelIoEx(self->handle, &self->overlapped);
744 else
745 ret = CancelIo(self->handle);
746 Py_END_ALLOW_THREADS
747 }
748
749 /* CancelIoEx returns ERROR_NOT_FOUND if the I/O completed in-between */
750 if (!ret && GetLastError() != ERROR_NOT_FOUND)
751 return SetFromWindowsErr(0);
752 Py_RETURN_NONE;
753}
754
755PyDoc_STRVAR(
756 Overlapped_getresult_doc,
757 "getresult(wait=False) -> result\n\n"
758 "Retrieve result of operation. If wait is true then it blocks\n"
759 "until the operation is finished. If wait is false and the\n"
760 "operation is still pending then an error is raised.");
761
762static PyObject *
763Overlapped_getresult(OverlappedObject *self, PyObject *args)
764{
765 BOOL wait = FALSE;
766 DWORD transferred = 0;
767 BOOL ret;
768 DWORD err;
Andrew Svetlovbafd4b52019-05-28 12:52:15 +0300769 PyObject *addr;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700770
771 if (!PyArg_ParseTuple(args, "|" F_BOOL, &wait))
772 return NULL;
773
774 if (self->type == TYPE_NONE) {
775 PyErr_SetString(PyExc_ValueError, "operation not yet attempted");
776 return NULL;
777 }
778
779 if (self->type == TYPE_NOT_STARTED) {
780 PyErr_SetString(PyExc_ValueError, "operation failed to start");
781 return NULL;
782 }
783
784 Py_BEGIN_ALLOW_THREADS
785 ret = GetOverlappedResult(self->handle, &self->overlapped, &transferred,
786 wait);
787 Py_END_ALLOW_THREADS
788
789 self->error = err = ret ? ERROR_SUCCESS : GetLastError();
790 switch (err) {
791 case ERROR_SUCCESS:
792 case ERROR_MORE_DATA:
793 break;
794 case ERROR_BROKEN_PIPE:
Andrew Svetlovbafd4b52019-05-28 12:52:15 +0300795 if (self->type == TYPE_READ || self->type == TYPE_READINTO) {
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700796 break;
Andrew Svetlovbafd4b52019-05-28 12:52:15 +0300797 }
798 else if (self->type == TYPE_READ_FROM &&
799 (self->read_from.result != NULL ||
800 self->read_from.allocated_buffer != NULL))
801 {
802 break;
803 }
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700804 /* fall through */
805 default:
806 return SetFromWindowsErr(err);
807 }
808
809 switch (self->type) {
810 case TYPE_READ:
Antoine Pitrou525f40d2017-10-19 21:46:40 +0200811 assert(PyBytes_CheckExact(self->allocated_buffer));
812 if (transferred != PyBytes_GET_SIZE(self->allocated_buffer) &&
813 _PyBytes_Resize(&self->allocated_buffer, transferred))
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700814 return NULL;
Andrew Svetlovbafd4b52019-05-28 12:52:15 +0300815
Antoine Pitrou525f40d2017-10-19 21:46:40 +0200816 Py_INCREF(self->allocated_buffer);
817 return self->allocated_buffer;
Andrew Svetlovbafd4b52019-05-28 12:52:15 +0300818 case TYPE_READ_FROM:
819 assert(PyBytes_CheckExact(self->read_from.allocated_buffer));
820
821 if (transferred != PyBytes_GET_SIZE(
822 self->read_from.allocated_buffer) &&
823 _PyBytes_Resize(&self->read_from.allocated_buffer, transferred))
824 {
825 return NULL;
826 }
827
828 // unparse the address
829 addr = unparse_address((SOCKADDR*)&self->read_from.address,
830 self->read_from.address_length);
831
832 if (addr == NULL) {
833 return NULL;
834 }
835
836 // The result is a two item tuple: (message, address)
837 self->read_from.result = PyTuple_New(2);
838 if (self->read_from.result == NULL) {
839 Py_CLEAR(addr);
840 return NULL;
841 }
842
843 // first item: message
844 Py_INCREF(self->read_from.allocated_buffer);
845 PyTuple_SET_ITEM(self->read_from.result, 0,
846 self->read_from.allocated_buffer);
847 // second item: address
848 PyTuple_SET_ITEM(self->read_from.result, 1, addr);
849
850 Py_INCREF(self->read_from.result);
851 return self->read_from.result;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700852 default:
853 return PyLong_FromUnsignedLong((unsigned long) transferred);
854 }
855}
856
Antoine Pitrou525f40d2017-10-19 21:46:40 +0200857static PyObject *
858do_ReadFile(OverlappedObject *self, HANDLE handle,
859 char *bufstart, DWORD buflen)
860{
861 DWORD nread;
862 int ret;
863 DWORD err;
864
865 Py_BEGIN_ALLOW_THREADS
866 ret = ReadFile(handle, bufstart, buflen, &nread,
867 &self->overlapped);
868 Py_END_ALLOW_THREADS
869
870 self->error = err = ret ? ERROR_SUCCESS : GetLastError();
871 switch (err) {
872 case ERROR_BROKEN_PIPE:
873 mark_as_completed(&self->overlapped);
874 return SetFromWindowsErr(err);
875 case ERROR_SUCCESS:
876 case ERROR_MORE_DATA:
877 case ERROR_IO_PENDING:
878 Py_RETURN_NONE;
879 default:
Victor Stinner54850852019-01-11 14:35:14 +0100880 Overlapped_clear(self);
Antoine Pitrou525f40d2017-10-19 21:46:40 +0200881 return SetFromWindowsErr(err);
882 }
883}
884
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700885PyDoc_STRVAR(
886 Overlapped_ReadFile_doc,
887 "ReadFile(handle, size) -> Overlapped[message]\n\n"
888 "Start overlapped read");
889
890static PyObject *
891Overlapped_ReadFile(OverlappedObject *self, PyObject *args)
892{
893 HANDLE handle;
894 DWORD size;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700895 PyObject *buf;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700896
897 if (!PyArg_ParseTuple(args, F_HANDLE F_DWORD, &handle, &size))
898 return NULL;
899
900 if (self->type != TYPE_NONE) {
901 PyErr_SetString(PyExc_ValueError, "operation already attempted");
902 return NULL;
903 }
904
905#if SIZEOF_SIZE_T <= SIZEOF_LONG
906 size = Py_MIN(size, (DWORD)PY_SSIZE_T_MAX);
907#endif
908 buf = PyBytes_FromStringAndSize(NULL, Py_MAX(size, 1));
909 if (buf == NULL)
910 return NULL;
911
912 self->type = TYPE_READ;
913 self->handle = handle;
Antoine Pitrou525f40d2017-10-19 21:46:40 +0200914 self->allocated_buffer = buf;
915
916 return do_ReadFile(self, handle, PyBytes_AS_STRING(buf), size);
917}
918
919PyDoc_STRVAR(
920 Overlapped_ReadFileInto_doc,
921 "ReadFileInto(handle, buf) -> Overlapped[bytes_transferred]\n\n"
922 "Start overlapped receive");
923
924static PyObject *
925Overlapped_ReadFileInto(OverlappedObject *self, PyObject *args)
926{
927 HANDLE handle;
928 PyObject *bufobj;
929
930 if (!PyArg_ParseTuple(args, F_HANDLE "O", &handle, &bufobj))
931 return NULL;
932
933 if (self->type != TYPE_NONE) {
934 PyErr_SetString(PyExc_ValueError, "operation already attempted");
935 return NULL;
936 }
937
938 if (!PyArg_Parse(bufobj, "y*", &self->user_buffer))
939 return NULL;
940
941#if SIZEOF_SIZE_T > SIZEOF_LONG
942 if (self->user_buffer.len > (Py_ssize_t)ULONG_MAX) {
943 PyBuffer_Release(&self->user_buffer);
944 PyErr_SetString(PyExc_ValueError, "buffer too large");
945 return NULL;
946 }
947#endif
948
949 self->type = TYPE_READINTO;
950 self->handle = handle;
951
952 return do_ReadFile(self, handle, self->user_buffer.buf,
953 (DWORD)self->user_buffer.len);
954}
955
956static PyObject *
957do_WSARecv(OverlappedObject *self, HANDLE handle,
958 char *bufstart, DWORD buflen, DWORD flags)
959{
960 DWORD nread;
961 WSABUF wsabuf;
962 int ret;
963 DWORD err;
Serhiy Storchakabdf42982017-10-26 16:59:40 +0300964
Antoine Pitrou525f40d2017-10-19 21:46:40 +0200965 wsabuf.buf = bufstart;
966 wsabuf.len = buflen;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700967
968 Py_BEGIN_ALLOW_THREADS
Antoine Pitrou525f40d2017-10-19 21:46:40 +0200969 ret = WSARecv((SOCKET)handle, &wsabuf, 1, &nread, &flags,
970 &self->overlapped, NULL);
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700971 Py_END_ALLOW_THREADS
972
Antoine Pitrou525f40d2017-10-19 21:46:40 +0200973 self->error = err = (ret < 0 ? WSAGetLastError() : ERROR_SUCCESS);
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700974 switch (err) {
975 case ERROR_BROKEN_PIPE:
976 mark_as_completed(&self->overlapped);
Victor Stinner41063d22015-01-26 22:30:49 +0100977 return SetFromWindowsErr(err);
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700978 case ERROR_SUCCESS:
979 case ERROR_MORE_DATA:
980 case ERROR_IO_PENDING:
981 Py_RETURN_NONE;
982 default:
Victor Stinner54850852019-01-11 14:35:14 +0100983 Overlapped_clear(self);
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700984 return SetFromWindowsErr(err);
985 }
986}
987
988PyDoc_STRVAR(
989 Overlapped_WSARecv_doc,
990 "RecvFile(handle, size, flags) -> Overlapped[message]\n\n"
991 "Start overlapped receive");
992
993static PyObject *
994Overlapped_WSARecv(OverlappedObject *self, PyObject *args)
995{
996 HANDLE handle;
997 DWORD size;
998 DWORD flags = 0;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700999 PyObject *buf;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001000
1001 if (!PyArg_ParseTuple(args, F_HANDLE F_DWORD "|" F_DWORD,
1002 &handle, &size, &flags))
1003 return NULL;
1004
1005 if (self->type != TYPE_NONE) {
1006 PyErr_SetString(PyExc_ValueError, "operation already attempted");
1007 return NULL;
1008 }
1009
1010#if SIZEOF_SIZE_T <= SIZEOF_LONG
1011 size = Py_MIN(size, (DWORD)PY_SSIZE_T_MAX);
1012#endif
1013 buf = PyBytes_FromStringAndSize(NULL, Py_MAX(size, 1));
1014 if (buf == NULL)
1015 return NULL;
1016
1017 self->type = TYPE_READ;
1018 self->handle = handle;
Antoine Pitrou525f40d2017-10-19 21:46:40 +02001019 self->allocated_buffer = buf;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001020
Antoine Pitrou525f40d2017-10-19 21:46:40 +02001021 return do_WSARecv(self, handle, PyBytes_AS_STRING(buf), size, flags);
1022}
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001023
Antoine Pitrou525f40d2017-10-19 21:46:40 +02001024PyDoc_STRVAR(
1025 Overlapped_WSARecvInto_doc,
1026 "WSARecvInto(handle, buf, flags) -> Overlapped[bytes_transferred]\n\n"
1027 "Start overlapped receive");
1028
1029static PyObject *
1030Overlapped_WSARecvInto(OverlappedObject *self, PyObject *args)
1031{
1032 HANDLE handle;
1033 PyObject *bufobj;
1034 DWORD flags;
1035
1036 if (!PyArg_ParseTuple(args, F_HANDLE "O" F_DWORD,
1037 &handle, &bufobj, &flags))
1038 return NULL;
1039
1040 if (self->type != TYPE_NONE) {
1041 PyErr_SetString(PyExc_ValueError, "operation already attempted");
1042 return NULL;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001043 }
Antoine Pitrou525f40d2017-10-19 21:46:40 +02001044
1045 if (!PyArg_Parse(bufobj, "y*", &self->user_buffer))
1046 return NULL;
1047
1048#if SIZEOF_SIZE_T > SIZEOF_LONG
1049 if (self->user_buffer.len > (Py_ssize_t)ULONG_MAX) {
1050 PyBuffer_Release(&self->user_buffer);
1051 PyErr_SetString(PyExc_ValueError, "buffer too large");
1052 return NULL;
1053 }
1054#endif
1055
1056 self->type = TYPE_READINTO;
1057 self->handle = handle;
1058
1059 return do_WSARecv(self, handle, self->user_buffer.buf,
1060 (DWORD)self->user_buffer.len, flags);
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001061}
1062
1063PyDoc_STRVAR(
1064 Overlapped_WriteFile_doc,
1065 "WriteFile(handle, buf) -> Overlapped[bytes_transferred]\n\n"
1066 "Start overlapped write");
1067
1068static PyObject *
1069Overlapped_WriteFile(OverlappedObject *self, PyObject *args)
1070{
1071 HANDLE handle;
1072 PyObject *bufobj;
1073 DWORD written;
1074 BOOL ret;
1075 DWORD err;
1076
1077 if (!PyArg_ParseTuple(args, F_HANDLE "O", &handle, &bufobj))
1078 return NULL;
1079
1080 if (self->type != TYPE_NONE) {
1081 PyErr_SetString(PyExc_ValueError, "operation already attempted");
1082 return NULL;
1083 }
1084
Antoine Pitrou525f40d2017-10-19 21:46:40 +02001085 if (!PyArg_Parse(bufobj, "y*", &self->user_buffer))
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001086 return NULL;
1087
1088#if SIZEOF_SIZE_T > SIZEOF_LONG
Antoine Pitrou525f40d2017-10-19 21:46:40 +02001089 if (self->user_buffer.len > (Py_ssize_t)ULONG_MAX) {
1090 PyBuffer_Release(&self->user_buffer);
Oren Milmand83c23b2017-08-15 19:04:18 +03001091 PyErr_SetString(PyExc_ValueError, "buffer too large");
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001092 return NULL;
1093 }
1094#endif
1095
1096 self->type = TYPE_WRITE;
1097 self->handle = handle;
1098
1099 Py_BEGIN_ALLOW_THREADS
Antoine Pitrou525f40d2017-10-19 21:46:40 +02001100 ret = WriteFile(handle, self->user_buffer.buf,
1101 (DWORD)self->user_buffer.len,
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001102 &written, &self->overlapped);
1103 Py_END_ALLOW_THREADS
1104
1105 self->error = err = ret ? ERROR_SUCCESS : GetLastError();
1106 switch (err) {
1107 case ERROR_SUCCESS:
1108 case ERROR_IO_PENDING:
1109 Py_RETURN_NONE;
1110 default:
Victor Stinner54850852019-01-11 14:35:14 +01001111 Overlapped_clear(self);
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001112 return SetFromWindowsErr(err);
1113 }
1114}
1115
1116PyDoc_STRVAR(
1117 Overlapped_WSASend_doc,
1118 "WSASend(handle, buf, flags) -> Overlapped[bytes_transferred]\n\n"
1119 "Start overlapped send");
1120
1121static PyObject *
1122Overlapped_WSASend(OverlappedObject *self, PyObject *args)
1123{
1124 HANDLE handle;
1125 PyObject *bufobj;
1126 DWORD flags;
1127 DWORD written;
1128 WSABUF wsabuf;
1129 int ret;
1130 DWORD err;
1131
1132 if (!PyArg_ParseTuple(args, F_HANDLE "O" F_DWORD,
1133 &handle, &bufobj, &flags))
1134 return NULL;
1135
1136 if (self->type != TYPE_NONE) {
1137 PyErr_SetString(PyExc_ValueError, "operation already attempted");
1138 return NULL;
1139 }
1140
Antoine Pitrou525f40d2017-10-19 21:46:40 +02001141 if (!PyArg_Parse(bufobj, "y*", &self->user_buffer))
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001142 return NULL;
1143
1144#if SIZEOF_SIZE_T > SIZEOF_LONG
Antoine Pitrou525f40d2017-10-19 21:46:40 +02001145 if (self->user_buffer.len > (Py_ssize_t)ULONG_MAX) {
1146 PyBuffer_Release(&self->user_buffer);
Oren Milmand83c23b2017-08-15 19:04:18 +03001147 PyErr_SetString(PyExc_ValueError, "buffer too large");
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001148 return NULL;
1149 }
1150#endif
1151
1152 self->type = TYPE_WRITE;
1153 self->handle = handle;
Antoine Pitrou525f40d2017-10-19 21:46:40 +02001154 wsabuf.len = (DWORD)self->user_buffer.len;
1155 wsabuf.buf = self->user_buffer.buf;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001156
1157 Py_BEGIN_ALLOW_THREADS
1158 ret = WSASend((SOCKET)handle, &wsabuf, 1, &written, flags,
1159 &self->overlapped, NULL);
1160 Py_END_ALLOW_THREADS
1161
1162 self->error = err = (ret < 0 ? WSAGetLastError() : ERROR_SUCCESS);
1163 switch (err) {
1164 case ERROR_SUCCESS:
1165 case ERROR_IO_PENDING:
1166 Py_RETURN_NONE;
1167 default:
Victor Stinner54850852019-01-11 14:35:14 +01001168 Overlapped_clear(self);
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001169 return SetFromWindowsErr(err);
1170 }
1171}
1172
1173PyDoc_STRVAR(
1174 Overlapped_AcceptEx_doc,
1175 "AcceptEx(listen_handle, accept_handle) -> Overlapped[address_as_bytes]\n\n"
1176 "Start overlapped wait for client to connect");
1177
1178static PyObject *
1179Overlapped_AcceptEx(OverlappedObject *self, PyObject *args)
1180{
1181 SOCKET ListenSocket;
1182 SOCKET AcceptSocket;
1183 DWORD BytesReceived;
1184 DWORD size;
1185 PyObject *buf;
1186 BOOL ret;
1187 DWORD err;
1188
1189 if (!PyArg_ParseTuple(args, F_HANDLE F_HANDLE,
1190 &ListenSocket, &AcceptSocket))
1191 return NULL;
1192
1193 if (self->type != TYPE_NONE) {
1194 PyErr_SetString(PyExc_ValueError, "operation already attempted");
1195 return NULL;
1196 }
1197
1198 size = sizeof(struct sockaddr_in6) + 16;
1199 buf = PyBytes_FromStringAndSize(NULL, size*2);
1200 if (!buf)
1201 return NULL;
1202
1203 self->type = TYPE_ACCEPT;
1204 self->handle = (HANDLE)ListenSocket;
Antoine Pitrou525f40d2017-10-19 21:46:40 +02001205 self->allocated_buffer = buf;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001206
1207 Py_BEGIN_ALLOW_THREADS
1208 ret = Py_AcceptEx(ListenSocket, AcceptSocket, PyBytes_AS_STRING(buf),
1209 0, size, size, &BytesReceived, &self->overlapped);
1210 Py_END_ALLOW_THREADS
1211
1212 self->error = err = ret ? ERROR_SUCCESS : WSAGetLastError();
1213 switch (err) {
1214 case ERROR_SUCCESS:
1215 case ERROR_IO_PENDING:
1216 Py_RETURN_NONE;
1217 default:
Victor Stinner54850852019-01-11 14:35:14 +01001218 Overlapped_clear(self);
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001219 return SetFromWindowsErr(err);
1220 }
1221}
1222
1223
1224static int
1225parse_address(PyObject *obj, SOCKADDR *Address, int Length)
1226{
Steve Dowercc16be82016-09-08 10:35:16 -07001227 Py_UNICODE *Host;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001228 unsigned short Port;
1229 unsigned long FlowInfo;
1230 unsigned long ScopeId;
1231
1232 memset(Address, 0, Length);
1233
Steve Dowercc16be82016-09-08 10:35:16 -07001234 if (PyArg_ParseTuple(obj, "uH", &Host, &Port))
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001235 {
1236 Address->sa_family = AF_INET;
Steve Dowercc16be82016-09-08 10:35:16 -07001237 if (WSAStringToAddressW(Host, AF_INET, NULL, Address, &Length) < 0) {
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001238 SetFromWindowsErr(WSAGetLastError());
1239 return -1;
1240 }
1241 ((SOCKADDR_IN*)Address)->sin_port = htons(Port);
1242 return Length;
1243 }
Oren Milman1d1d3e92017-08-20 18:35:36 +03001244 else if (PyArg_ParseTuple(obj,
1245 "uHkk;ConnectEx(): illegal address_as_bytes "
1246 "argument", &Host, &Port, &FlowInfo, &ScopeId))
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001247 {
1248 PyErr_Clear();
1249 Address->sa_family = AF_INET6;
Steve Dowercc16be82016-09-08 10:35:16 -07001250 if (WSAStringToAddressW(Host, AF_INET6, NULL, Address, &Length) < 0) {
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001251 SetFromWindowsErr(WSAGetLastError());
1252 return -1;
1253 }
1254 ((SOCKADDR_IN6*)Address)->sin6_port = htons(Port);
1255 ((SOCKADDR_IN6*)Address)->sin6_flowinfo = FlowInfo;
1256 ((SOCKADDR_IN6*)Address)->sin6_scope_id = ScopeId;
1257 return Length;
1258 }
1259
1260 return -1;
1261}
1262
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001263PyDoc_STRVAR(
1264 Overlapped_ConnectEx_doc,
1265 "ConnectEx(client_handle, address_as_bytes) -> Overlapped[None]\n\n"
1266 "Start overlapped connect. client_handle should be unbound.");
1267
1268static PyObject *
1269Overlapped_ConnectEx(OverlappedObject *self, PyObject *args)
1270{
1271 SOCKET ConnectSocket;
1272 PyObject *AddressObj;
1273 char AddressBuf[sizeof(struct sockaddr_in6)];
1274 SOCKADDR *Address = (SOCKADDR*)AddressBuf;
1275 int Length;
1276 BOOL ret;
1277 DWORD err;
1278
Oren Milman1d1d3e92017-08-20 18:35:36 +03001279 if (!PyArg_ParseTuple(args, F_HANDLE "O!:ConnectEx",
1280 &ConnectSocket, &PyTuple_Type, &AddressObj))
1281 {
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001282 return NULL;
Oren Milman1d1d3e92017-08-20 18:35:36 +03001283 }
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001284
1285 if (self->type != TYPE_NONE) {
1286 PyErr_SetString(PyExc_ValueError, "operation already attempted");
1287 return NULL;
1288 }
1289
1290 Length = sizeof(AddressBuf);
1291 Length = parse_address(AddressObj, Address, Length);
1292 if (Length < 0)
1293 return NULL;
1294
1295 self->type = TYPE_CONNECT;
1296 self->handle = (HANDLE)ConnectSocket;
1297
1298 Py_BEGIN_ALLOW_THREADS
1299 ret = Py_ConnectEx(ConnectSocket, Address, Length,
1300 NULL, 0, NULL, &self->overlapped);
1301 Py_END_ALLOW_THREADS
1302
1303 self->error = err = ret ? ERROR_SUCCESS : WSAGetLastError();
1304 switch (err) {
1305 case ERROR_SUCCESS:
1306 case ERROR_IO_PENDING:
1307 Py_RETURN_NONE;
1308 default:
Victor Stinner54850852019-01-11 14:35:14 +01001309 Overlapped_clear(self);
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001310 return SetFromWindowsErr(err);
1311 }
1312}
1313
1314PyDoc_STRVAR(
1315 Overlapped_DisconnectEx_doc,
1316 "DisconnectEx(handle, flags) -> Overlapped[None]\n\n"
1317 "Start overlapped connect. client_handle should be unbound.");
1318
1319static PyObject *
1320Overlapped_DisconnectEx(OverlappedObject *self, PyObject *args)
1321{
1322 SOCKET Socket;
1323 DWORD flags;
1324 BOOL ret;
1325 DWORD err;
1326
1327 if (!PyArg_ParseTuple(args, F_HANDLE F_DWORD, &Socket, &flags))
1328 return NULL;
1329
1330 if (self->type != TYPE_NONE) {
1331 PyErr_SetString(PyExc_ValueError, "operation already attempted");
1332 return NULL;
1333 }
1334
1335 self->type = TYPE_DISCONNECT;
1336 self->handle = (HANDLE)Socket;
1337
1338 Py_BEGIN_ALLOW_THREADS
1339 ret = Py_DisconnectEx(Socket, &self->overlapped, flags, 0);
1340 Py_END_ALLOW_THREADS
1341
1342 self->error = err = ret ? ERROR_SUCCESS : WSAGetLastError();
1343 switch (err) {
1344 case ERROR_SUCCESS:
1345 case ERROR_IO_PENDING:
1346 Py_RETURN_NONE;
1347 default:
Victor Stinner54850852019-01-11 14:35:14 +01001348 Overlapped_clear(self);
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001349 return SetFromWindowsErr(err);
1350 }
1351}
1352
1353PyDoc_STRVAR(
Andrew Svetlova19fb3c2018-02-25 19:32:14 +03001354 Overlapped_TransmitFile_doc,
1355 "TransmitFile(socket, file, offset, offset_high, "
1356 "count_to_write, count_per_send, flags) "
1357 "-> Overlapped[None]\n\n"
1358 "Transmit file data over a connected socket.");
1359
1360static PyObject *
1361Overlapped_TransmitFile(OverlappedObject *self, PyObject *args)
1362{
1363 SOCKET Socket;
1364 HANDLE File;
1365 DWORD offset;
1366 DWORD offset_high;
1367 DWORD count_to_write;
1368 DWORD count_per_send;
1369 DWORD flags;
1370 BOOL ret;
1371 DWORD err;
1372
1373 if (!PyArg_ParseTuple(args,
1374 F_HANDLE F_HANDLE F_DWORD F_DWORD
1375 F_DWORD F_DWORD F_DWORD,
1376 &Socket, &File, &offset, &offset_high,
1377 &count_to_write, &count_per_send,
1378 &flags))
1379 return NULL;
1380
1381 if (self->type != TYPE_NONE) {
1382 PyErr_SetString(PyExc_ValueError, "operation already attempted");
1383 return NULL;
1384 }
1385
1386 self->type = TYPE_TRANSMIT_FILE;
1387 self->handle = (HANDLE)Socket;
1388 self->overlapped.Offset = offset;
1389 self->overlapped.OffsetHigh = offset_high;
1390
1391 Py_BEGIN_ALLOW_THREADS
1392 ret = Py_TransmitFile(Socket, File, count_to_write, count_per_send,
1393 &self->overlapped,
1394 NULL, flags);
1395 Py_END_ALLOW_THREADS
1396
1397 self->error = err = ret ? ERROR_SUCCESS : WSAGetLastError();
1398 switch (err) {
1399 case ERROR_SUCCESS:
1400 case ERROR_IO_PENDING:
1401 Py_RETURN_NONE;
1402 default:
Victor Stinner54850852019-01-11 14:35:14 +01001403 Overlapped_clear(self);
Andrew Svetlova19fb3c2018-02-25 19:32:14 +03001404 return SetFromWindowsErr(err);
1405 }
1406}
1407
1408PyDoc_STRVAR(
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001409 Overlapped_ConnectNamedPipe_doc,
1410 "ConnectNamedPipe(handle) -> Overlapped[None]\n\n"
1411 "Start overlapped wait for a client to connect.");
1412
1413static PyObject *
1414Overlapped_ConnectNamedPipe(OverlappedObject *self, PyObject *args)
1415{
1416 HANDLE Pipe;
1417 BOOL ret;
1418 DWORD err;
1419
1420 if (!PyArg_ParseTuple(args, F_HANDLE, &Pipe))
1421 return NULL;
1422
1423 if (self->type != TYPE_NONE) {
1424 PyErr_SetString(PyExc_ValueError, "operation already attempted");
1425 return NULL;
1426 }
1427
1428 self->type = TYPE_CONNECT_NAMED_PIPE;
1429 self->handle = Pipe;
1430
1431 Py_BEGIN_ALLOW_THREADS
1432 ret = ConnectNamedPipe(Pipe, &self->overlapped);
1433 Py_END_ALLOW_THREADS
1434
1435 self->error = err = ret ? ERROR_SUCCESS : GetLastError();
1436 switch (err) {
1437 case ERROR_PIPE_CONNECTED:
1438 mark_as_completed(&self->overlapped);
Victor Stinner2b77c542015-01-22 23:50:03 +01001439 Py_RETURN_TRUE;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001440 case ERROR_SUCCESS:
1441 case ERROR_IO_PENDING:
Victor Stinner2b77c542015-01-22 23:50:03 +01001442 Py_RETURN_FALSE;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001443 default:
Victor Stinner54850852019-01-11 14:35:14 +01001444 Overlapped_clear(self);
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001445 return SetFromWindowsErr(err);
1446 }
1447}
1448
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001449PyDoc_STRVAR(
Victor Stinner7ffa2c52015-01-22 22:55:08 +01001450 ConnectPipe_doc,
1451 "ConnectPipe(addr) -> pipe_handle\n\n"
1452 "Connect to the pipe for asynchronous I/O (overlapped).");
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001453
1454static PyObject *
Andrew Svetlovbafd4b52019-05-28 12:52:15 +03001455overlapped_ConnectPipe(PyObject *self, PyObject *args)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001456{
Victor Stinner7ffa2c52015-01-22 22:55:08 +01001457 PyObject *AddressObj;
1458 wchar_t *Address;
1459 HANDLE PipeHandle;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001460
Victor Stinner7ffa2c52015-01-22 22:55:08 +01001461 if (!PyArg_ParseTuple(args, "U", &AddressObj))
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001462 return NULL;
1463
Victor Stinner7ffa2c52015-01-22 22:55:08 +01001464 Address = PyUnicode_AsWideCharString(AddressObj, NULL);
1465 if (Address == NULL)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001466 return NULL;
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001467
Victor Stinner498b1f62015-01-26 22:43:39 +01001468 Py_BEGIN_ALLOW_THREADS
Victor Stinner7ffa2c52015-01-22 22:55:08 +01001469 PipeHandle = CreateFileW(Address,
1470 GENERIC_READ | GENERIC_WRITE,
1471 0, NULL, OPEN_EXISTING,
1472 FILE_FLAG_OVERLAPPED, NULL);
Victor Stinner498b1f62015-01-26 22:43:39 +01001473 Py_END_ALLOW_THREADS
1474
Victor Stinner7ffa2c52015-01-22 22:55:08 +01001475 PyMem_Free(Address);
1476 if (PipeHandle == INVALID_HANDLE_VALUE)
1477 return SetFromWindowsErr(0);
1478 return Py_BuildValue(F_HANDLE, PipeHandle);
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001479}
1480
1481static PyObject*
1482Overlapped_getaddress(OverlappedObject *self)
1483{
1484 return PyLong_FromVoidPtr(&self->overlapped);
1485}
1486
1487static PyObject*
1488Overlapped_getpending(OverlappedObject *self)
1489{
1490 return PyBool_FromLong(!HasOverlappedIoCompleted(&self->overlapped) &&
1491 self->type != TYPE_NOT_STARTED);
1492}
1493
Victor Stinner54850852019-01-11 14:35:14 +01001494static int
1495Overlapped_traverse(OverlappedObject *self, visitproc visit, void *arg)
1496{
1497 switch (self->type) {
1498 case TYPE_READ:
1499 case TYPE_ACCEPT:
1500 Py_VISIT(self->allocated_buffer);
1501 break;
1502 case TYPE_WRITE:
Andrew Svetlovbafd4b52019-05-28 12:52:15 +03001503 case TYPE_WRITE_TO:
Victor Stinner54850852019-01-11 14:35:14 +01001504 case TYPE_READINTO:
1505 if (self->user_buffer.obj) {
1506 Py_VISIT(&self->user_buffer.obj);
1507 }
1508 break;
Andrew Svetlovbafd4b52019-05-28 12:52:15 +03001509 case TYPE_READ_FROM:
1510 if(self->read_from.result) {
1511 Py_VISIT(self->read_from.result);
1512 }
1513 if(self->read_from.allocated_buffer) {
1514 Py_VISIT(self->read_from.allocated_buffer);
1515 }
Victor Stinner54850852019-01-11 14:35:14 +01001516 }
1517 return 0;
1518}
1519
Andrew Svetlovbafd4b52019-05-28 12:52:15 +03001520// UDP functions
1521
1522PyDoc_STRVAR(
1523 WSAConnect_doc,
1524 "WSAConnect(client_handle, address_as_bytes) -> Overlapped[None]\n\n"
1525 "Bind a remote address to a connectionless (UDP) socket");
1526
1527/*
1528 * Note: WSAConnect does not support Overlapped I/O so this function should
1529 * _only_ be used for connectionless sockets (UDP).
1530 */
1531static PyObject *
1532overlapped_WSAConnect(PyObject *self, PyObject *args)
1533{
1534 SOCKET ConnectSocket;
1535 PyObject *AddressObj;
1536 char AddressBuf[sizeof(struct sockaddr_in6)];
1537 SOCKADDR *Address = (SOCKADDR*)AddressBuf;
1538 int Length;
1539 int err;
1540
1541 if (!PyArg_ParseTuple(args, F_HANDLE "O", &ConnectSocket, &AddressObj)) {
1542 return NULL;
1543 }
1544
1545 Length = sizeof(AddressBuf);
1546 Length = parse_address(AddressObj, Address, Length);
1547 if (Length < 0) {
1548 return NULL;
1549 }
1550
1551 Py_BEGIN_ALLOW_THREADS
1552 // WSAConnect does not support overlapped I/O so this call will
1553 // successfully complete immediately.
1554 err = WSAConnect(ConnectSocket, Address, Length,
1555 NULL, NULL, NULL, NULL);
1556 Py_END_ALLOW_THREADS
1557
1558 if (err == 0) {
1559 Py_RETURN_NONE;
1560 }
1561 else {
1562 return SetFromWindowsErr(WSAGetLastError());
1563 }
1564}
1565
1566PyDoc_STRVAR(
1567 Overlapped_WSASendTo_doc,
1568 "WSASendTo(handle, buf, flags, address_as_bytes) -> "
1569 "Overlapped[bytes_transferred]\n\n"
1570 "Start overlapped sendto over a connectionless (UDP) socket");
1571
1572static PyObject *
1573Overlapped_WSASendTo(OverlappedObject *self, PyObject *args)
1574{
1575 HANDLE handle;
1576 PyObject *bufobj;
1577 DWORD flags;
1578 PyObject *AddressObj;
1579 char AddressBuf[sizeof(struct sockaddr_in6)];
1580 SOCKADDR *Address = (SOCKADDR*)AddressBuf;
1581 int AddressLength;
1582 DWORD written;
1583 WSABUF wsabuf;
1584 int ret;
1585 DWORD err;
1586
1587 if (!PyArg_ParseTuple(args, F_HANDLE "O" F_DWORD "O",
1588 &handle, &bufobj, &flags, &AddressObj))
1589 {
1590 return NULL;
1591 }
1592
1593 // Parse the "to" address
1594 AddressLength = sizeof(AddressBuf);
1595 AddressLength = parse_address(AddressObj, Address, AddressLength);
1596 if (AddressLength < 0) {
1597 return NULL;
1598 }
1599
1600 if (self->type != TYPE_NONE) {
1601 PyErr_SetString(PyExc_ValueError, "operation already attempted");
1602 return NULL;
1603 }
1604
1605 if (!PyArg_Parse(bufobj, "y*", &self->user_buffer)) {
1606 return NULL;
1607 }
1608
1609#if SIZEOF_SIZE_T > SIZEOF_LONG
1610 if (self->user_buffer.len > (Py_ssize_t)ULONG_MAX) {
1611 PyBuffer_Release(&self->user_buffer);
1612 PyErr_SetString(PyExc_ValueError, "buffer too large");
1613 return NULL;
1614 }
1615#endif
1616
1617 self->type = TYPE_WRITE_TO;
1618 self->handle = handle;
1619 wsabuf.len = (DWORD)self->user_buffer.len;
1620 wsabuf.buf = self->user_buffer.buf;
1621
1622 Py_BEGIN_ALLOW_THREADS
1623 ret = WSASendTo((SOCKET)handle, &wsabuf, 1, &written, flags,
1624 Address, AddressLength, &self->overlapped, NULL);
1625 Py_END_ALLOW_THREADS
1626
1627 self->error = err = (ret == SOCKET_ERROR ? WSAGetLastError() :
1628 ERROR_SUCCESS);
1629
1630 switch(err) {
1631 case ERROR_SUCCESS:
1632 case ERROR_IO_PENDING:
1633 Py_RETURN_NONE;
1634 default:
1635 self->type = TYPE_NOT_STARTED;
1636 return SetFromWindowsErr(err);
1637 }
1638}
1639
1640
1641
1642PyDoc_STRVAR(
1643 Overlapped_WSARecvFrom_doc,
1644 "RecvFile(handle, size, flags) -> Overlapped[(message, (host, port))]\n\n"
1645 "Start overlapped receive");
1646
1647static PyObject *
1648Overlapped_WSARecvFrom(OverlappedObject *self, PyObject *args)
1649{
1650 HANDLE handle;
1651 DWORD size;
1652 DWORD flags = 0;
1653 DWORD nread;
1654 PyObject *buf;
1655 WSABUF wsabuf;
1656 int ret;
1657 DWORD err;
1658
1659 if (!PyArg_ParseTuple(args, F_HANDLE F_DWORD "|" F_DWORD,
1660 &handle, &size, &flags))
1661 {
1662 return NULL;
1663 }
1664
1665 if (self->type != TYPE_NONE) {
1666 PyErr_SetString(PyExc_ValueError, "operation already attempted");
1667 return NULL;
1668 }
1669
1670#if SIZEOF_SIZE_T <= SIZEOF_LONG
1671 size = Py_MIN(size, (DWORD)PY_SSIZE_T_MAX);
1672#endif
1673 buf = PyBytes_FromStringAndSize(NULL, Py_MAX(size, 1));
1674 if (buf == NULL) {
1675 return NULL;
1676 }
1677
1678 wsabuf.len = size;
1679 wsabuf.buf = PyBytes_AS_STRING(buf);
1680
1681 self->type = TYPE_READ_FROM;
1682 self->handle = handle;
1683 self->read_from.allocated_buffer = buf;
1684 memset(&self->read_from.address, 0, sizeof(self->read_from.address));
1685 self->read_from.address_length = sizeof(self->read_from.address);
1686
1687 Py_BEGIN_ALLOW_THREADS
1688 ret = WSARecvFrom((SOCKET)handle, &wsabuf, 1, &nread, &flags,
1689 (SOCKADDR*)&self->read_from.address,
1690 &self->read_from.address_length,
1691 &self->overlapped, NULL);
1692 Py_END_ALLOW_THREADS
1693
1694 self->error = err = (ret < 0 ? WSAGetLastError() : ERROR_SUCCESS);
1695
1696 switch(err) {
1697 case ERROR_BROKEN_PIPE:
1698 mark_as_completed(&self->overlapped);
1699 return SetFromWindowsErr(err);
1700 case ERROR_SUCCESS:
1701 case ERROR_MORE_DATA:
1702 case ERROR_IO_PENDING:
1703 Py_RETURN_NONE;
1704 default:
1705 self->type = TYPE_NOT_STARTED;
1706 return SetFromWindowsErr(err);
1707 }
1708}
1709
Victor Stinner54850852019-01-11 14:35:14 +01001710
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001711static PyMethodDef Overlapped_methods[] = {
1712 {"getresult", (PyCFunction) Overlapped_getresult,
1713 METH_VARARGS, Overlapped_getresult_doc},
1714 {"cancel", (PyCFunction) Overlapped_cancel,
1715 METH_NOARGS, Overlapped_cancel_doc},
1716 {"ReadFile", (PyCFunction) Overlapped_ReadFile,
1717 METH_VARARGS, Overlapped_ReadFile_doc},
Antoine Pitrou525f40d2017-10-19 21:46:40 +02001718 {"ReadFileInto", (PyCFunction) Overlapped_ReadFileInto,
1719 METH_VARARGS, Overlapped_ReadFileInto_doc},
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001720 {"WSARecv", (PyCFunction) Overlapped_WSARecv,
1721 METH_VARARGS, Overlapped_WSARecv_doc},
Antoine Pitrou525f40d2017-10-19 21:46:40 +02001722 {"WSARecvInto", (PyCFunction) Overlapped_WSARecvInto,
1723 METH_VARARGS, Overlapped_WSARecvInto_doc},
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001724 {"WriteFile", (PyCFunction) Overlapped_WriteFile,
1725 METH_VARARGS, Overlapped_WriteFile_doc},
1726 {"WSASend", (PyCFunction) Overlapped_WSASend,
1727 METH_VARARGS, Overlapped_WSASend_doc},
1728 {"AcceptEx", (PyCFunction) Overlapped_AcceptEx,
1729 METH_VARARGS, Overlapped_AcceptEx_doc},
1730 {"ConnectEx", (PyCFunction) Overlapped_ConnectEx,
1731 METH_VARARGS, Overlapped_ConnectEx_doc},
1732 {"DisconnectEx", (PyCFunction) Overlapped_DisconnectEx,
1733 METH_VARARGS, Overlapped_DisconnectEx_doc},
Andrew Svetlova19fb3c2018-02-25 19:32:14 +03001734 {"TransmitFile", (PyCFunction) Overlapped_TransmitFile,
1735 METH_VARARGS, Overlapped_TransmitFile_doc},
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001736 {"ConnectNamedPipe", (PyCFunction) Overlapped_ConnectNamedPipe,
1737 METH_VARARGS, Overlapped_ConnectNamedPipe_doc},
Andrew Svetlovbafd4b52019-05-28 12:52:15 +03001738 {"WSARecvFrom", (PyCFunction) Overlapped_WSARecvFrom,
1739 METH_VARARGS, Overlapped_WSARecvFrom_doc },
1740 {"WSASendTo", (PyCFunction) Overlapped_WSASendTo,
1741 METH_VARARGS, Overlapped_WSASendTo_doc },
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001742 {NULL}
1743};
1744
1745static PyMemberDef Overlapped_members[] = {
1746 {"error", T_ULONG,
1747 offsetof(OverlappedObject, error),
1748 READONLY, "Error from last operation"},
1749 {"event", T_HANDLE,
1750 offsetof(OverlappedObject, overlapped) + offsetof(OVERLAPPED, hEvent),
1751 READONLY, "Overlapped event handle"},
1752 {NULL}
1753};
1754
1755static PyGetSetDef Overlapped_getsets[] = {
1756 {"address", (getter)Overlapped_getaddress, NULL,
1757 "Address of overlapped structure"},
1758 {"pending", (getter)Overlapped_getpending, NULL,
1759 "Whether the operation is pending"},
1760 {NULL},
1761};
1762
1763PyTypeObject OverlappedType = {
1764 PyVarObject_HEAD_INIT(NULL, 0)
1765 /* tp_name */ "_overlapped.Overlapped",
1766 /* tp_basicsize */ sizeof(OverlappedObject),
1767 /* tp_itemsize */ 0,
1768 /* tp_dealloc */ (destructor) Overlapped_dealloc,
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001769 /* tp_vectorcall_offset */ 0,
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001770 /* tp_getattr */ 0,
1771 /* tp_setattr */ 0,
Jeroen Demeyer530f5062019-05-31 04:13:39 +02001772 /* tp_as_async */ 0,
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001773 /* tp_repr */ 0,
1774 /* tp_as_number */ 0,
1775 /* tp_as_sequence */ 0,
1776 /* tp_as_mapping */ 0,
1777 /* tp_hash */ 0,
1778 /* tp_call */ 0,
1779 /* tp_str */ 0,
1780 /* tp_getattro */ 0,
1781 /* tp_setattro */ 0,
1782 /* tp_as_buffer */ 0,
1783 /* tp_flags */ Py_TPFLAGS_DEFAULT,
1784 /* tp_doc */ "OVERLAPPED structure wrapper",
Victor Stinner54850852019-01-11 14:35:14 +01001785 /* tp_traverse */ (traverseproc)Overlapped_traverse,
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001786 /* tp_clear */ 0,
1787 /* tp_richcompare */ 0,
1788 /* tp_weaklistoffset */ 0,
1789 /* tp_iter */ 0,
1790 /* tp_iternext */ 0,
1791 /* tp_methods */ Overlapped_methods,
1792 /* tp_members */ Overlapped_members,
1793 /* tp_getset */ Overlapped_getsets,
1794 /* tp_base */ 0,
1795 /* tp_dict */ 0,
1796 /* tp_descr_get */ 0,
1797 /* tp_descr_set */ 0,
1798 /* tp_dictoffset */ 0,
1799 /* tp_init */ 0,
1800 /* tp_alloc */ 0,
1801 /* tp_new */ Overlapped_new,
1802};
1803
1804static PyMethodDef overlapped_functions[] = {
1805 {"CreateIoCompletionPort", overlapped_CreateIoCompletionPort,
1806 METH_VARARGS, CreateIoCompletionPort_doc},
1807 {"GetQueuedCompletionStatus", overlapped_GetQueuedCompletionStatus,
1808 METH_VARARGS, GetQueuedCompletionStatus_doc},
1809 {"PostQueuedCompletionStatus", overlapped_PostQueuedCompletionStatus,
1810 METH_VARARGS, PostQueuedCompletionStatus_doc},
1811 {"FormatMessage", overlapped_FormatMessage,
1812 METH_VARARGS, FormatMessage_doc},
1813 {"BindLocal", overlapped_BindLocal,
1814 METH_VARARGS, BindLocal_doc},
Guido van Rossum90fb9142013-10-30 14:44:05 -07001815 {"RegisterWaitWithQueue", overlapped_RegisterWaitWithQueue,
1816 METH_VARARGS, RegisterWaitWithQueue_doc},
1817 {"UnregisterWait", overlapped_UnregisterWait,
1818 METH_VARARGS, UnregisterWait_doc},
Victor Stinnerd0a28de2015-01-21 23:39:51 +01001819 {"UnregisterWaitEx", overlapped_UnregisterWaitEx,
1820 METH_VARARGS, UnregisterWaitEx_doc},
Guido van Rossum90fb9142013-10-30 14:44:05 -07001821 {"CreateEvent", overlapped_CreateEvent,
1822 METH_VARARGS, CreateEvent_doc},
1823 {"SetEvent", overlapped_SetEvent,
1824 METH_VARARGS, SetEvent_doc},
1825 {"ResetEvent", overlapped_ResetEvent,
1826 METH_VARARGS, ResetEvent_doc},
Andrew Svetlovbafd4b52019-05-28 12:52:15 +03001827 {"ConnectPipe", overlapped_ConnectPipe,
Victor Stinner7ffa2c52015-01-22 22:55:08 +01001828 METH_VARARGS, ConnectPipe_doc},
Andrew Svetlovbafd4b52019-05-28 12:52:15 +03001829 {"WSAConnect", overlapped_WSAConnect,
1830 METH_VARARGS, WSAConnect_doc},
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001831 {NULL}
1832};
1833
1834static struct PyModuleDef overlapped_module = {
1835 PyModuleDef_HEAD_INIT,
1836 "_overlapped",
1837 NULL,
1838 -1,
1839 overlapped_functions,
1840 NULL,
1841 NULL,
1842 NULL,
1843 NULL
1844};
1845
1846#define WINAPI_CONSTANT(fmt, con) \
1847 PyDict_SetItemString(d, #con, Py_BuildValue(fmt, con))
1848
1849PyMODINIT_FUNC
1850PyInit__overlapped(void)
1851{
1852 PyObject *m, *d;
1853
1854 /* Ensure WSAStartup() called before initializing function pointers */
1855 m = PyImport_ImportModule("_socket");
1856 if (!m)
1857 return NULL;
1858 Py_DECREF(m);
1859
1860 if (initialize_function_pointers() < 0)
1861 return NULL;
1862
1863 if (PyType_Ready(&OverlappedType) < 0)
1864 return NULL;
1865
1866 m = PyModule_Create(&overlapped_module);
1867 if (PyModule_AddObject(m, "Overlapped", (PyObject *)&OverlappedType) < 0)
1868 return NULL;
1869
1870 d = PyModule_GetDict(m);
1871
1872 WINAPI_CONSTANT(F_DWORD, ERROR_IO_PENDING);
1873 WINAPI_CONSTANT(F_DWORD, ERROR_NETNAME_DELETED);
Andrew Svetlov7c684072018-01-27 21:22:47 +02001874 WINAPI_CONSTANT(F_DWORD, ERROR_OPERATION_ABORTED);
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001875 WINAPI_CONSTANT(F_DWORD, ERROR_SEM_TIMEOUT);
Victor Stinner7ffa2c52015-01-22 22:55:08 +01001876 WINAPI_CONSTANT(F_DWORD, ERROR_PIPE_BUSY);
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07001877 WINAPI_CONSTANT(F_DWORD, INFINITE);
1878 WINAPI_CONSTANT(F_HANDLE, INVALID_HANDLE_VALUE);
1879 WINAPI_CONSTANT(F_HANDLE, NULL);
1880 WINAPI_CONSTANT(F_DWORD, SO_UPDATE_ACCEPT_CONTEXT);
1881 WINAPI_CONSTANT(F_DWORD, SO_UPDATE_CONNECT_CONTEXT);
1882 WINAPI_CONSTANT(F_DWORD, TF_REUSE_SOCKET);
1883
1884 return m;
1885}