xref: /third_party/python/Modules/overlapped.c (revision 7db96d56)
1/*
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"         // PyMemberDef
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
26#define F_HANDLE F_POINTER
27#define F_ULONG_PTR F_POINTER
28#define F_DWORD "k"
29#define F_BOOL "i"
30#define F_UINT "I"
31
32#define T_HANDLE T_POINTER
33
34/*[python input]
35class OVERLAPPED_converter(CConverter):
36    type = 'OVERLAPPED *'
37    format_unit = '"F_POINTER"'
38
39class HANDLE_converter(CConverter):
40    type = 'HANDLE'
41    format_unit = '"F_HANDLE"'
42
43class ULONG_PTR_converter(CConverter):
44    type = 'ULONG_PTR'
45    format_unit = '"F_ULONG_PTR"'
46
47class DWORD_converter(CConverter):
48    type = 'DWORD'
49    format_unit = 'k'
50
51class BOOL_converter(CConverter):
52    type = 'BOOL'
53    format_unit = 'i'
54[python start generated code]*/
55/*[python end generated code: output=da39a3ee5e6b4b0d input=83bb8c2c2514f2a8]*/
56
57/*[clinic input]
58module _overlapped
59class _overlapped.Overlapped "OverlappedObject *" "&OverlappedType"
60[clinic start generated code]*/
61/*[clinic end generated code: output=da39a3ee5e6b4b0d input=92e5a799db35b96c]*/
62
63
64enum {TYPE_NONE, TYPE_NOT_STARTED, TYPE_READ, TYPE_READINTO, TYPE_WRITE,
65      TYPE_ACCEPT, TYPE_CONNECT, TYPE_DISCONNECT, TYPE_CONNECT_NAMED_PIPE,
66      TYPE_WAIT_NAMED_PIPE_AND_CONNECT, TYPE_TRANSMIT_FILE, TYPE_READ_FROM,
67      TYPE_WRITE_TO, TYPE_READ_FROM_INTO};
68
69typedef struct {
70    PyObject_HEAD
71    OVERLAPPED overlapped;
72    /* For convenience, we store the file handle too */
73    HANDLE handle;
74    /* Error returned by last method call */
75    DWORD error;
76    /* Type of operation */
77    DWORD type;
78    union {
79        /* Buffer allocated by us: TYPE_READ and TYPE_ACCEPT */
80        PyObject *allocated_buffer;
81        /* Buffer passed by the user: TYPE_WRITE, TYPE_WRITE_TO, and TYPE_READINTO */
82        Py_buffer user_buffer;
83
84        /* Data used for reading from a connectionless socket:
85           TYPE_READ_FROM */
86        struct {
87            // A (buffer, (host, port)) tuple
88            PyObject *result;
89            // The actual read buffer
90            PyObject *allocated_buffer;
91            struct sockaddr_in6 address;
92            int address_length;
93        } read_from;
94
95        /* Data used for reading from a connectionless socket:
96           TYPE_READ_FROM_INTO */
97        struct {
98            // A (number of bytes read, (host, port)) tuple
99            PyObject* result;
100            /* Buffer passed by the user */
101            Py_buffer user_buffer;
102            struct sockaddr_in6 address;
103            int address_length;
104        } read_from_into;
105    };
106} OverlappedObject;
107
108typedef struct {
109    PyTypeObject *overlapped_type;
110} OverlappedState;
111
112static inline OverlappedState*
113overlapped_get_state(PyObject *module)
114{
115    void *state = PyModule_GetState(module);
116    assert(state != NULL);
117    return (OverlappedState *)state;
118}
119
120
121static inline void
122steal_buffer(Py_buffer * dst, Py_buffer * src)
123{
124    memcpy(dst, src, sizeof(Py_buffer));
125    memset(src, 0, sizeof(Py_buffer));
126}
127
128/*
129 * Map Windows error codes to subclasses of OSError
130 */
131
132static PyObject *
133SetFromWindowsErr(DWORD err)
134{
135    PyObject *exception_type;
136
137    if (err == 0)
138        err = GetLastError();
139    switch (err) {
140        case ERROR_CONNECTION_REFUSED:
141            exception_type = PyExc_ConnectionRefusedError;
142            break;
143        case ERROR_CONNECTION_ABORTED:
144            exception_type = PyExc_ConnectionAbortedError;
145            break;
146        default:
147            exception_type = PyExc_OSError;
148    }
149    return PyErr_SetExcFromWindowsErr(exception_type, err);
150}
151
152/*
153 * Some functions should be loaded at runtime
154 */
155
156static LPFN_ACCEPTEX Py_AcceptEx = NULL;
157static LPFN_CONNECTEX Py_ConnectEx = NULL;
158static LPFN_DISCONNECTEX Py_DisconnectEx = NULL;
159static LPFN_TRANSMITFILE Py_TransmitFile = NULL;
160
161#define GET_WSA_POINTER(s, x)                                           \
162    (SOCKET_ERROR != WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER,    \
163                              &Guid##x, sizeof(Guid##x), &Py_##x,       \
164                              sizeof(Py_##x), &dwBytes, NULL, NULL))
165
166static int
167initialize_function_pointers(void)
168{
169    GUID GuidAcceptEx = WSAID_ACCEPTEX;
170    GUID GuidConnectEx = WSAID_CONNECTEX;
171    GUID GuidDisconnectEx = WSAID_DISCONNECTEX;
172    GUID GuidTransmitFile = WSAID_TRANSMITFILE;
173    SOCKET s;
174    DWORD dwBytes;
175
176    if (Py_AcceptEx != NULL &&
177        Py_ConnectEx != NULL &&
178        Py_DisconnectEx != NULL &&
179        Py_TransmitFile != NULL)
180    {
181        // All function pointers are initialized already
182        // by previous module import
183        return 0;
184    }
185
186    s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
187    if (s == INVALID_SOCKET) {
188        SetFromWindowsErr(WSAGetLastError());
189        return -1;
190    }
191
192    if (!GET_WSA_POINTER(s, AcceptEx) ||
193        !GET_WSA_POINTER(s, ConnectEx) ||
194        !GET_WSA_POINTER(s, DisconnectEx) ||
195        !GET_WSA_POINTER(s, TransmitFile))
196    {
197        closesocket(s);
198        SetFromWindowsErr(WSAGetLastError());
199        return -1;
200    }
201
202    closesocket(s);
203    return 0;
204}
205
206/*
207 * Completion port stuff
208 */
209
210/*[clinic input]
211_overlapped.CreateIoCompletionPort
212
213    handle as FileHandle: HANDLE
214    port as ExistingCompletionPort: HANDLE
215    key as CompletionKey: ULONG_PTR
216    concurrency as NumberOfConcurrentThreads: DWORD
217    /
218
219Create a completion port or register a handle with a port.
220[clinic start generated code]*/
221
222static PyObject *
223_overlapped_CreateIoCompletionPort_impl(PyObject *module, HANDLE FileHandle,
224                                        HANDLE ExistingCompletionPort,
225                                        ULONG_PTR CompletionKey,
226                                        DWORD NumberOfConcurrentThreads)
227/*[clinic end generated code: output=24ede2b0f05e5433 input=847bae4d0efe1976]*/
228{
229    HANDLE ret;
230
231    Py_BEGIN_ALLOW_THREADS
232    ret = CreateIoCompletionPort(FileHandle, ExistingCompletionPort,
233                                 CompletionKey, NumberOfConcurrentThreads);
234    Py_END_ALLOW_THREADS
235
236    if (ret == NULL)
237        return SetFromWindowsErr(0);
238    return Py_BuildValue(F_HANDLE, ret);
239}
240
241/*[clinic input]
242_overlapped.GetQueuedCompletionStatus
243
244    port as CompletionPort: HANDLE
245    msecs as Milliseconds: DWORD
246    /
247
248Get a message from completion port.
249
250Wait for up to msecs milliseconds.
251[clinic start generated code]*/
252
253static PyObject *
254_overlapped_GetQueuedCompletionStatus_impl(PyObject *module,
255                                           HANDLE CompletionPort,
256                                           DWORD Milliseconds)
257/*[clinic end generated code: output=68314171628dddb7 input=94a042d14c4f6410]*/
258{
259    DWORD NumberOfBytes = 0;
260    ULONG_PTR CompletionKey = 0;
261    OVERLAPPED *Overlapped = NULL;
262    DWORD err;
263    BOOL ret;
264
265    Py_BEGIN_ALLOW_THREADS
266    ret = GetQueuedCompletionStatus(CompletionPort, &NumberOfBytes,
267                                    &CompletionKey, &Overlapped, Milliseconds);
268    Py_END_ALLOW_THREADS
269
270    err = ret ? ERROR_SUCCESS : GetLastError();
271    if (Overlapped == NULL) {
272        if (err == WAIT_TIMEOUT)
273            Py_RETURN_NONE;
274        else
275            return SetFromWindowsErr(err);
276    }
277    return Py_BuildValue(F_DWORD F_DWORD F_ULONG_PTR F_POINTER,
278                         err, NumberOfBytes, CompletionKey, Overlapped);
279}
280
281/*[clinic input]
282_overlapped.PostQueuedCompletionStatus
283
284    port as CompletionPort: HANDLE
285    bytes as NumberOfBytes: DWORD
286    key as CompletionKey: ULONG_PTR
287    address as Overlapped: OVERLAPPED
288    /
289
290Post a message to completion port.
291[clinic start generated code]*/
292
293static PyObject *
294_overlapped_PostQueuedCompletionStatus_impl(PyObject *module,
295                                            HANDLE CompletionPort,
296                                            DWORD NumberOfBytes,
297                                            ULONG_PTR CompletionKey,
298                                            OVERLAPPED *Overlapped)
299/*[clinic end generated code: output=93e73f2933a43e9e input=e936202d87937aca]*/
300{
301    BOOL ret;
302
303    Py_BEGIN_ALLOW_THREADS
304    ret = PostQueuedCompletionStatus(CompletionPort, NumberOfBytes,
305                                     CompletionKey, Overlapped);
306    Py_END_ALLOW_THREADS
307
308    if (!ret)
309        return SetFromWindowsErr(0);
310    Py_RETURN_NONE;
311}
312
313/*
314 * Wait for a handle
315 */
316
317struct PostCallbackData {
318    HANDLE CompletionPort;
319    LPOVERLAPPED Overlapped;
320};
321
322static VOID CALLBACK
323PostToQueueCallback(PVOID lpParameter, BOOLEAN TimerOrWaitFired)
324{
325    struct PostCallbackData *p = (struct PostCallbackData*) lpParameter;
326
327    PostQueuedCompletionStatus(p->CompletionPort, TimerOrWaitFired,
328                               0, p->Overlapped);
329    /* ignore possible error! */
330    PyMem_RawFree(p);
331}
332
333/*[clinic input]
334_overlapped.RegisterWaitWithQueue
335
336    Object: HANDLE
337    CompletionPort: HANDLE
338    Overlapped: OVERLAPPED
339    Timeout as Milliseconds: DWORD
340    /
341
342Register wait for Object; when complete CompletionPort is notified.
343[clinic start generated code]*/
344
345static PyObject *
346_overlapped_RegisterWaitWithQueue_impl(PyObject *module, HANDLE Object,
347                                       HANDLE CompletionPort,
348                                       OVERLAPPED *Overlapped,
349                                       DWORD Milliseconds)
350/*[clinic end generated code: output=c2ace732e447fe45 input=2dd4efee44abe8ee]*/
351{
352    HANDLE NewWaitObject;
353    struct PostCallbackData data = {CompletionPort, Overlapped}, *pdata;
354
355    /* Use PyMem_RawMalloc() rather than PyMem_Malloc(), since
356       PostToQueueCallback() will call PyMem_Free() from a new C thread
357       which doesn't hold the GIL. */
358    pdata = PyMem_RawMalloc(sizeof(struct PostCallbackData));
359    if (pdata == NULL)
360        return SetFromWindowsErr(0);
361
362    *pdata = data;
363
364    if (!RegisterWaitForSingleObject(
365            &NewWaitObject, Object, PostToQueueCallback, pdata, Milliseconds,
366            WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE))
367    {
368        PyMem_RawFree(pdata);
369        return SetFromWindowsErr(0);
370    }
371
372    return Py_BuildValue(F_HANDLE, NewWaitObject);
373}
374
375/*[clinic input]
376_overlapped.UnregisterWait
377
378    WaitHandle: HANDLE
379    /
380
381Unregister wait handle.
382[clinic start generated code]*/
383
384static PyObject *
385_overlapped_UnregisterWait_impl(PyObject *module, HANDLE WaitHandle)
386/*[clinic end generated code: output=ec90cd955a9a617d input=a56709544cb2df0f]*/
387{
388    BOOL ret;
389
390    Py_BEGIN_ALLOW_THREADS
391    ret = UnregisterWait(WaitHandle);
392    Py_END_ALLOW_THREADS
393
394    if (!ret)
395        return SetFromWindowsErr(0);
396    Py_RETURN_NONE;
397}
398
399/*[clinic input]
400_overlapped.UnregisterWaitEx
401
402    WaitHandle: HANDLE
403    Event: HANDLE
404    /
405
406Unregister wait handle.
407[clinic start generated code]*/
408
409static PyObject *
410_overlapped_UnregisterWaitEx_impl(PyObject *module, HANDLE WaitHandle,
411                                  HANDLE Event)
412/*[clinic end generated code: output=2e3d84c1d5f65b92 input=953cddc1de50fab9]*/
413{
414    BOOL ret;
415
416    Py_BEGIN_ALLOW_THREADS
417    ret = UnregisterWaitEx(WaitHandle, Event);
418    Py_END_ALLOW_THREADS
419
420    if (!ret)
421        return SetFromWindowsErr(0);
422    Py_RETURN_NONE;
423}
424
425/*
426 * Event functions -- currently only used by tests
427 */
428
429/*[clinic input]
430_overlapped.CreateEvent
431
432    EventAttributes: object
433    ManualReset: BOOL
434    InitialState: BOOL
435    Name: Py_UNICODE(accept={str, NoneType})
436    /
437
438Create an event.
439
440EventAttributes must be None.
441[clinic start generated code]*/
442
443static PyObject *
444_overlapped_CreateEvent_impl(PyObject *module, PyObject *EventAttributes,
445                             BOOL ManualReset, BOOL InitialState,
446                             const Py_UNICODE *Name)
447/*[clinic end generated code: output=8e04f0916c17b13d input=dbc36ae14375ba24]*/
448{
449    HANDLE Event;
450
451    if (EventAttributes != Py_None) {
452        PyErr_SetString(PyExc_ValueError, "EventAttributes must be None");
453        return NULL;
454    }
455
456    Py_BEGIN_ALLOW_THREADS
457    Event = CreateEventW(NULL, ManualReset, InitialState, Name);
458    Py_END_ALLOW_THREADS
459
460    if (Event == NULL)
461        return SetFromWindowsErr(0);
462    return Py_BuildValue(F_HANDLE, Event);
463}
464
465/*[clinic input]
466_overlapped.SetEvent
467
468    Handle: HANDLE
469    /
470
471Set event.
472[clinic start generated code]*/
473
474static PyObject *
475_overlapped_SetEvent_impl(PyObject *module, HANDLE Handle)
476/*[clinic end generated code: output=5b8d974216b0e569 input=d8b0d26eb7391e80]*/
477{
478    BOOL ret;
479
480    Py_BEGIN_ALLOW_THREADS
481    ret = SetEvent(Handle);
482    Py_END_ALLOW_THREADS
483
484    if (!ret)
485        return SetFromWindowsErr(0);
486    Py_RETURN_NONE;
487}
488
489/*[clinic input]
490_overlapped.ResetEvent
491
492    Handle: HANDLE
493    /
494
495Reset event.
496[clinic start generated code]*/
497
498static PyObject *
499_overlapped_ResetEvent_impl(PyObject *module, HANDLE Handle)
500/*[clinic end generated code: output=066537a8405cddb2 input=d4e089c9ba84ff2f]*/
501{
502    BOOL ret;
503
504    Py_BEGIN_ALLOW_THREADS
505    ret = ResetEvent(Handle);
506    Py_END_ALLOW_THREADS
507
508    if (!ret)
509        return SetFromWindowsErr(0);
510    Py_RETURN_NONE;
511}
512
513/*
514 * Bind socket handle to local port without doing slow getaddrinfo()
515 */
516
517/*[clinic input]
518_overlapped.BindLocal
519
520    handle as Socket: HANDLE
521    family as Family: int
522    /
523
524Bind a socket handle to an arbitrary local port.
525
526family should be AF_INET or AF_INET6.
527[clinic start generated code]*/
528
529static PyObject *
530_overlapped_BindLocal_impl(PyObject *module, HANDLE Socket, int Family)
531/*[clinic end generated code: output=edb93862697aed9c input=a0e7b5c2f541170c]*/
532{
533    BOOL ret;
534
535    if (Family == AF_INET) {
536        struct sockaddr_in addr;
537        memset(&addr, 0, sizeof(addr));
538        addr.sin_family = AF_INET;
539        addr.sin_port = 0;
540        addr.sin_addr.S_un.S_addr = INADDR_ANY;
541        ret = bind((SOCKET)Socket, (SOCKADDR*)&addr, sizeof(addr))
542                != SOCKET_ERROR;
543    } else if (Family == AF_INET6) {
544        struct sockaddr_in6 addr;
545        memset(&addr, 0, sizeof(addr));
546        addr.sin6_family = AF_INET6;
547        addr.sin6_port = 0;
548        addr.sin6_addr = in6addr_any;
549        ret = bind((SOCKET)Socket, (SOCKADDR*)&addr, sizeof(addr))
550                != SOCKET_ERROR;
551    } else {
552        PyErr_SetString(PyExc_ValueError, "expected tuple of length 2 or 4");
553        return NULL;
554    }
555
556    if (!ret)
557        return SetFromWindowsErr(WSAGetLastError());
558    Py_RETURN_NONE;
559}
560
561/*
562 * Windows equivalent of os.strerror() -- compare _ctypes/callproc.c
563 */
564
565/*[clinic input]
566_overlapped.FormatMessage
567
568    error_code as code: DWORD
569    /
570
571Return error message for an error code.
572[clinic start generated code]*/
573
574static PyObject *
575_overlapped_FormatMessage_impl(PyObject *module, DWORD code)
576/*[clinic end generated code: output=02c964ff22407c6b input=644bb5b80326179e]*/
577{
578    DWORD n;
579    WCHAR *lpMsgBuf;
580    PyObject *res;
581
582    n = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
583                       FORMAT_MESSAGE_FROM_SYSTEM |
584                       FORMAT_MESSAGE_IGNORE_INSERTS,
585                       NULL,
586                       code,
587                       MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
588                       (LPWSTR) &lpMsgBuf,
589                       0,
590                       NULL);
591    if (n) {
592        while (iswspace(lpMsgBuf[n-1]))
593            --n;
594        lpMsgBuf[n] = L'\0';
595        res = Py_BuildValue("u", lpMsgBuf);
596    } else {
597        res = PyUnicode_FromFormat("unknown error code %u", code);
598    }
599    LocalFree(lpMsgBuf);
600    return res;
601}
602
603
604/*
605 * Mark operation as completed - used when reading produces ERROR_BROKEN_PIPE
606 */
607
608static inline void
609mark_as_completed(OVERLAPPED *ov)
610{
611    ov->Internal = 0;
612    if (ov->hEvent != NULL)
613        SetEvent(ov->hEvent);
614}
615
616/*
617 * A Python object wrapping an OVERLAPPED structure and other useful data
618 * for overlapped I/O
619 */
620
621/*[clinic input]
622@classmethod
623_overlapped.Overlapped.__new__
624
625    event: HANDLE(c_default='INVALID_HANDLE_VALUE') = _overlapped.INVALID_HANDLE_VALUE
626
627OVERLAPPED structure wrapper.
628[clinic start generated code]*/
629
630static PyObject *
631_overlapped_Overlapped_impl(PyTypeObject *type, HANDLE event)
632/*[clinic end generated code: output=6da60504a18eb421 input=26b8a7429e629e95]*/
633{
634    OverlappedObject *self;
635
636    if (event == INVALID_HANDLE_VALUE) {
637        event = CreateEvent(NULL, TRUE, FALSE, NULL);
638        if (event == NULL)
639            return SetFromWindowsErr(0);
640    }
641
642    self = PyObject_New(OverlappedObject, type);
643    if (self == NULL) {
644        if (event != NULL)
645            CloseHandle(event);
646        return NULL;
647    }
648
649    self->handle = NULL;
650    self->error = 0;
651    self->type = TYPE_NONE;
652    self->allocated_buffer = NULL;
653    memset(&self->overlapped, 0, sizeof(OVERLAPPED));
654    memset(&self->user_buffer, 0, sizeof(Py_buffer));
655    if (event)
656        self->overlapped.hEvent = event;
657    return (PyObject *)self;
658}
659
660
661/* Note (bpo-32710): OverlappedType.tp_clear is not defined to not release
662   buffers while overlapped are still running, to prevent a crash. */
663static int
664Overlapped_clear(OverlappedObject *self)
665{
666    switch (self->type) {
667        case TYPE_READ:
668        case TYPE_ACCEPT: {
669            Py_CLEAR(self->allocated_buffer);
670            break;
671        }
672        case TYPE_READ_FROM: {
673            // An initial call to WSARecvFrom will only allocate the buffer.
674            // The result tuple of (message, address) is only
675            // allocated _after_ a message has been received.
676            if(self->read_from.result) {
677                // We've received a message, free the result tuple.
678                Py_CLEAR(self->read_from.result);
679            }
680            if(self->read_from.allocated_buffer) {
681                Py_CLEAR(self->read_from.allocated_buffer);
682            }
683            break;
684        }
685        case TYPE_READ_FROM_INTO: {
686            if (self->read_from_into.result) {
687                // We've received a message, free the result tuple.
688                Py_CLEAR(self->read_from_into.result);
689            }
690            if (self->read_from_into.user_buffer.obj) {
691                PyBuffer_Release(&self->read_from_into.user_buffer);
692            }
693            break;
694        }
695        case TYPE_WRITE:
696        case TYPE_WRITE_TO:
697        case TYPE_READINTO: {
698            if (self->user_buffer.obj) {
699                PyBuffer_Release(&self->user_buffer);
700            }
701            break;
702        }
703    }
704    self->type = TYPE_NOT_STARTED;
705    return 0;
706}
707
708static void
709Overlapped_dealloc(OverlappedObject *self)
710{
711    DWORD bytes;
712    DWORD olderr = GetLastError();
713    BOOL wait = FALSE;
714    BOOL ret;
715
716    if (!HasOverlappedIoCompleted(&self->overlapped) &&
717        self->type != TYPE_NOT_STARTED)
718    {
719        Py_BEGIN_ALLOW_THREADS
720        if (CancelIoEx(self->handle, &self->overlapped))
721            wait = TRUE;
722
723        ret = GetOverlappedResult(self->handle, &self->overlapped,
724                                  &bytes, wait);
725        Py_END_ALLOW_THREADS
726
727        switch (ret ? ERROR_SUCCESS : GetLastError()) {
728            case ERROR_SUCCESS:
729            case ERROR_NOT_FOUND:
730            case ERROR_OPERATION_ABORTED:
731                break;
732            default:
733                PyErr_Format(
734                    PyExc_RuntimeError,
735                    "%R still has pending operation at "
736                    "deallocation, the process may crash", self);
737                PyErr_WriteUnraisable(NULL);
738        }
739    }
740
741    if (self->overlapped.hEvent != NULL) {
742        CloseHandle(self->overlapped.hEvent);
743    }
744
745    Overlapped_clear(self);
746    SetLastError(olderr);
747
748    PyTypeObject *tp = Py_TYPE(self);
749    PyObject_Free(self);
750    Py_DECREF(tp);
751}
752
753
754/* Convert IPv4 sockaddr to a Python str. */
755
756static PyObject *
757make_ipv4_addr(const struct sockaddr_in *addr)
758{
759        char buf[INET_ADDRSTRLEN];
760        if (inet_ntop(AF_INET, &addr->sin_addr, buf, sizeof(buf)) == NULL) {
761                PyErr_SetFromErrno(PyExc_OSError);
762                return NULL;
763        }
764        return PyUnicode_FromString(buf);
765}
766
767/* Convert IPv6 sockaddr to a Python str. */
768
769static PyObject *
770make_ipv6_addr(const struct sockaddr_in6 *addr)
771{
772        char buf[INET6_ADDRSTRLEN];
773        if (inet_ntop(AF_INET6, &addr->sin6_addr, buf, sizeof(buf)) == NULL) {
774                PyErr_SetFromErrno(PyExc_OSError);
775                return NULL;
776        }
777        return PyUnicode_FromString(buf);
778}
779
780static PyObject*
781unparse_address(LPSOCKADDR Address, DWORD Length)
782{
783        /* The function is adopted from mocketmodule.c makesockaddr()*/
784
785    switch(Address->sa_family) {
786        case AF_INET: {
787            const struct sockaddr_in *a = (const struct sockaddr_in *)Address;
788            PyObject *addrobj = make_ipv4_addr(a);
789            PyObject *ret = NULL;
790            if (addrobj) {
791                ret = Py_BuildValue("Oi", addrobj, ntohs(a->sin_port));
792                Py_DECREF(addrobj);
793            }
794            return ret;
795        }
796        case AF_INET6: {
797            const struct sockaddr_in6 *a = (const struct sockaddr_in6 *)Address;
798            PyObject *addrobj = make_ipv6_addr(a);
799            PyObject *ret = NULL;
800            if (addrobj) {
801                ret = Py_BuildValue("OiII",
802                                    addrobj,
803                                    ntohs(a->sin6_port),
804                                    ntohl(a->sin6_flowinfo),
805                                    a->sin6_scope_id);
806                Py_DECREF(addrobj);
807            }
808            return ret;
809        }
810        default: {
811            PyErr_SetString(PyExc_ValueError, "recvfrom returned unsupported address family");
812            return NULL;
813        }
814    }
815}
816
817/*[clinic input]
818_overlapped.Overlapped.cancel
819
820Cancel overlapped operation.
821[clinic start generated code]*/
822
823static PyObject *
824_overlapped_Overlapped_cancel_impl(OverlappedObject *self)
825/*[clinic end generated code: output=54ad7aeece89901c input=80eb67c7b57dbcf1]*/
826{
827    BOOL ret = TRUE;
828
829    if (self->type == TYPE_NOT_STARTED
830        || self->type == TYPE_WAIT_NAMED_PIPE_AND_CONNECT)
831        Py_RETURN_NONE;
832
833    if (!HasOverlappedIoCompleted(&self->overlapped)) {
834        Py_BEGIN_ALLOW_THREADS
835        ret = CancelIoEx(self->handle, &self->overlapped);
836        Py_END_ALLOW_THREADS
837    }
838
839    /* CancelIoEx returns ERROR_NOT_FOUND if the I/O completed in-between */
840    if (!ret && GetLastError() != ERROR_NOT_FOUND)
841        return SetFromWindowsErr(0);
842    Py_RETURN_NONE;
843}
844
845/*[clinic input]
846_overlapped.Overlapped.getresult
847
848    wait: BOOL(c_default='FALSE') = False
849    /
850
851Retrieve result of operation.
852
853If wait is true then it blocks until the operation is finished.  If wait
854is false and the operation is still pending then an error is raised.
855[clinic start generated code]*/
856
857static PyObject *
858_overlapped_Overlapped_getresult_impl(OverlappedObject *self, BOOL wait)
859/*[clinic end generated code: output=8c9bd04d08994f6c input=aa5b03e9897ca074]*/
860{
861    DWORD transferred = 0;
862    BOOL ret;
863    DWORD err;
864    PyObject *addr;
865
866    if (self->type == TYPE_NONE) {
867        PyErr_SetString(PyExc_ValueError, "operation not yet attempted");
868        return NULL;
869    }
870
871    if (self->type == TYPE_NOT_STARTED) {
872        PyErr_SetString(PyExc_ValueError, "operation failed to start");
873        return NULL;
874    }
875
876    Py_BEGIN_ALLOW_THREADS
877    ret = GetOverlappedResult(self->handle, &self->overlapped, &transferred,
878                              wait);
879    Py_END_ALLOW_THREADS
880
881    self->error = err = ret ? ERROR_SUCCESS : GetLastError();
882    switch (err) {
883        case ERROR_SUCCESS:
884        case ERROR_MORE_DATA:
885            break;
886        case ERROR_BROKEN_PIPE:
887            if (self->type == TYPE_READ || self->type == TYPE_READINTO) {
888                break;
889            }
890            else if (self->type == TYPE_READ_FROM &&
891                     (self->read_from.result != NULL ||
892                      self->read_from.allocated_buffer != NULL))
893            {
894                break;
895            }
896            else if (self->type == TYPE_READ_FROM_INTO &&
897                     self->read_from_into.result != NULL)
898            {
899                break;
900            }
901            /* fall through */
902        default:
903            return SetFromWindowsErr(err);
904    }
905
906    switch (self->type) {
907        case TYPE_READ:
908            assert(PyBytes_CheckExact(self->allocated_buffer));
909            if (transferred != PyBytes_GET_SIZE(self->allocated_buffer) &&
910                _PyBytes_Resize(&self->allocated_buffer, transferred))
911                return NULL;
912
913            Py_INCREF(self->allocated_buffer);
914            return self->allocated_buffer;
915        case TYPE_READ_FROM:
916            assert(PyBytes_CheckExact(self->read_from.allocated_buffer));
917
918            if (transferred != PyBytes_GET_SIZE(
919                    self->read_from.allocated_buffer) &&
920                _PyBytes_Resize(&self->read_from.allocated_buffer, transferred))
921            {
922                return NULL;
923            }
924
925            // unparse the address
926            addr = unparse_address((SOCKADDR*)&self->read_from.address,
927                                   self->read_from.address_length);
928
929            if (addr == NULL) {
930                return NULL;
931            }
932
933            // The result is a two item tuple: (message, address)
934            self->read_from.result = PyTuple_New(2);
935            if (self->read_from.result == NULL) {
936                Py_CLEAR(addr);
937                return NULL;
938            }
939
940            // first item: message
941            Py_INCREF(self->read_from.allocated_buffer);
942            PyTuple_SET_ITEM(self->read_from.result, 0,
943                             self->read_from.allocated_buffer);
944            // second item: address
945            PyTuple_SET_ITEM(self->read_from.result, 1, addr);
946
947            Py_INCREF(self->read_from.result);
948            return self->read_from.result;
949        case TYPE_READ_FROM_INTO:
950            // unparse the address
951            addr = unparse_address((SOCKADDR*)&self->read_from_into.address,
952                self->read_from_into.address_length);
953
954            if (addr == NULL) {
955                return NULL;
956            }
957
958            // The result is a two item tuple: (number of bytes read, address)
959            self->read_from_into.result = PyTuple_New(2);
960            if (self->read_from_into.result == NULL) {
961                Py_CLEAR(addr);
962                return NULL;
963            }
964
965            // first item: number of bytes read
966            PyTuple_SET_ITEM(self->read_from_into.result, 0,
967                PyLong_FromUnsignedLong((unsigned long)transferred));
968            // second item: address
969            PyTuple_SET_ITEM(self->read_from_into.result, 1, addr);
970
971            Py_INCREF(self->read_from_into.result);
972            return self->read_from_into.result;
973        default:
974            return PyLong_FromUnsignedLong((unsigned long) transferred);
975    }
976}
977
978static PyObject *
979do_ReadFile(OverlappedObject *self, HANDLE handle,
980            char *bufstart, DWORD buflen)
981{
982    DWORD nread;
983    int ret;
984    DWORD err;
985
986    Py_BEGIN_ALLOW_THREADS
987    ret = ReadFile(handle, bufstart, buflen, &nread,
988                   &self->overlapped);
989    Py_END_ALLOW_THREADS
990
991    self->error = err = ret ? ERROR_SUCCESS : GetLastError();
992    switch (err) {
993        case ERROR_BROKEN_PIPE:
994            mark_as_completed(&self->overlapped);
995            return SetFromWindowsErr(err);
996        case ERROR_SUCCESS:
997        case ERROR_MORE_DATA:
998        case ERROR_IO_PENDING:
999            Py_RETURN_NONE;
1000        default:
1001            Overlapped_clear(self);
1002            return SetFromWindowsErr(err);
1003    }
1004}
1005
1006/*[clinic input]
1007_overlapped.Overlapped.ReadFile
1008
1009    handle: HANDLE
1010    size: DWORD
1011    /
1012
1013Start overlapped read.
1014[clinic start generated code]*/
1015
1016static PyObject *
1017_overlapped_Overlapped_ReadFile_impl(OverlappedObject *self, HANDLE handle,
1018                                     DWORD size)
1019/*[clinic end generated code: output=4c8557e16941e4ae input=98c495baa0342425]*/
1020{
1021    PyObject *buf;
1022
1023    if (self->type != TYPE_NONE) {
1024        PyErr_SetString(PyExc_ValueError, "operation already attempted");
1025        return NULL;
1026    }
1027
1028#if SIZEOF_SIZE_T <= SIZEOF_LONG
1029    size = Py_MIN(size, (DWORD)PY_SSIZE_T_MAX);
1030#endif
1031    buf = PyBytes_FromStringAndSize(NULL, Py_MAX(size, 1));
1032    if (buf == NULL)
1033        return NULL;
1034
1035    self->type = TYPE_READ;
1036    self->handle = handle;
1037    self->allocated_buffer = buf;
1038
1039    return do_ReadFile(self, handle, PyBytes_AS_STRING(buf), size);
1040}
1041
1042/*[clinic input]
1043_overlapped.Overlapped.ReadFileInto
1044
1045    handle: HANDLE
1046    buf as bufobj: Py_buffer
1047    /
1048
1049Start overlapped receive.
1050[clinic start generated code]*/
1051
1052static PyObject *
1053_overlapped_Overlapped_ReadFileInto_impl(OverlappedObject *self,
1054                                         HANDLE handle, Py_buffer *bufobj)
1055/*[clinic end generated code: output=8754744506023071 input=4f037ba09939e32d]*/
1056{
1057    if (self->type != TYPE_NONE) {
1058        PyErr_SetString(PyExc_ValueError, "operation already attempted");
1059        return NULL;
1060    }
1061
1062#if SIZEOF_SIZE_T > SIZEOF_LONG
1063    if (bufobj->len > (Py_ssize_t)ULONG_MAX) {
1064        PyErr_SetString(PyExc_ValueError, "buffer too large");
1065        return NULL;
1066    }
1067#endif
1068    steal_buffer(&self->user_buffer, bufobj);
1069
1070    self->type = TYPE_READINTO;
1071    self->handle = handle;
1072
1073    return do_ReadFile(self, handle, self->user_buffer.buf,
1074                       (DWORD)self->user_buffer.len);
1075}
1076
1077static PyObject *
1078do_WSARecv(OverlappedObject *self, HANDLE handle,
1079           char *bufstart, DWORD buflen, DWORD flags)
1080{
1081    DWORD nread;
1082    WSABUF wsabuf;
1083    int ret;
1084    DWORD err;
1085
1086    wsabuf.buf = bufstart;
1087    wsabuf.len = buflen;
1088
1089    Py_BEGIN_ALLOW_THREADS
1090    ret = WSARecv((SOCKET)handle, &wsabuf, 1, &nread, &flags,
1091                  &self->overlapped, NULL);
1092    Py_END_ALLOW_THREADS
1093
1094    self->error = err = (ret < 0 ? WSAGetLastError() : ERROR_SUCCESS);
1095    switch (err) {
1096        case ERROR_BROKEN_PIPE:
1097            mark_as_completed(&self->overlapped);
1098            return SetFromWindowsErr(err);
1099        case ERROR_SUCCESS:
1100        case ERROR_MORE_DATA:
1101        case ERROR_IO_PENDING:
1102            Py_RETURN_NONE;
1103        default:
1104            Overlapped_clear(self);
1105            return SetFromWindowsErr(err);
1106    }
1107}
1108
1109
1110/*[clinic input]
1111_overlapped.Overlapped.WSARecv
1112
1113    handle: HANDLE
1114    size: DWORD
1115    flags: DWORD = 0
1116    /
1117
1118Start overlapped receive.
1119[clinic start generated code]*/
1120
1121static PyObject *
1122_overlapped_Overlapped_WSARecv_impl(OverlappedObject *self, HANDLE handle,
1123                                    DWORD size, DWORD flags)
1124/*[clinic end generated code: output=3a5e9c61ff040906 input=8c04e506cc3d741a]*/
1125{
1126    PyObject *buf;
1127
1128    if (self->type != TYPE_NONE) {
1129        PyErr_SetString(PyExc_ValueError, "operation already attempted");
1130        return NULL;
1131    }
1132
1133#if SIZEOF_SIZE_T <= SIZEOF_LONG
1134    size = Py_MIN(size, (DWORD)PY_SSIZE_T_MAX);
1135#endif
1136    buf = PyBytes_FromStringAndSize(NULL, Py_MAX(size, 1));
1137    if (buf == NULL)
1138        return NULL;
1139
1140    self->type = TYPE_READ;
1141    self->handle = handle;
1142    self->allocated_buffer = buf;
1143
1144    return do_WSARecv(self, handle, PyBytes_AS_STRING(buf), size, flags);
1145}
1146
1147/*[clinic input]
1148_overlapped.Overlapped.WSARecvInto
1149
1150    handle: HANDLE
1151    buf as bufobj: Py_buffer
1152    flags: DWORD
1153    /
1154
1155Start overlapped receive.
1156[clinic start generated code]*/
1157
1158static PyObject *
1159_overlapped_Overlapped_WSARecvInto_impl(OverlappedObject *self,
1160                                        HANDLE handle, Py_buffer *bufobj,
1161                                        DWORD flags)
1162/*[clinic end generated code: output=59ae7688786cf86b input=73e7fa00db633edd]*/
1163{
1164    if (self->type != TYPE_NONE) {
1165        PyErr_SetString(PyExc_ValueError, "operation already attempted");
1166        return NULL;
1167    }
1168
1169#if SIZEOF_SIZE_T > SIZEOF_LONG
1170    if (bufobj->len > (Py_ssize_t)ULONG_MAX) {
1171        PyErr_SetString(PyExc_ValueError, "buffer too large");
1172        return NULL;
1173    }
1174#endif
1175    steal_buffer(&self->user_buffer, bufobj);
1176
1177    self->type = TYPE_READINTO;
1178    self->handle = handle;
1179
1180    return do_WSARecv(self, handle, self->user_buffer.buf,
1181                      (DWORD)self->user_buffer.len, flags);
1182}
1183
1184/*[clinic input]
1185_overlapped.Overlapped.WriteFile
1186
1187    handle: HANDLE
1188    buf as bufobj: Py_buffer
1189    /
1190
1191Start overlapped write.
1192[clinic start generated code]*/
1193
1194static PyObject *
1195_overlapped_Overlapped_WriteFile_impl(OverlappedObject *self, HANDLE handle,
1196                                      Py_buffer *bufobj)
1197/*[clinic end generated code: output=fa5d5880a1bf04b1 input=ac54424c362abfc1]*/
1198{
1199    DWORD written;
1200    BOOL ret;
1201    DWORD err;
1202
1203    if (self->type != TYPE_NONE) {
1204        PyErr_SetString(PyExc_ValueError, "operation already attempted");
1205        return NULL;
1206    }
1207
1208#if SIZEOF_SIZE_T > SIZEOF_LONG
1209    if (bufobj->len > (Py_ssize_t)ULONG_MAX) {
1210        PyErr_SetString(PyExc_ValueError, "buffer too large");
1211        return NULL;
1212    }
1213#endif
1214    steal_buffer(&self->user_buffer, bufobj);
1215
1216    self->type = TYPE_WRITE;
1217    self->handle = handle;
1218
1219    Py_BEGIN_ALLOW_THREADS
1220    ret = WriteFile(handle, self->user_buffer.buf,
1221                    (DWORD)self->user_buffer.len,
1222                    &written, &self->overlapped);
1223    Py_END_ALLOW_THREADS
1224
1225    self->error = err = ret ? ERROR_SUCCESS : GetLastError();
1226    switch (err) {
1227        case ERROR_SUCCESS:
1228        case ERROR_IO_PENDING:
1229            Py_RETURN_NONE;
1230        default:
1231            Overlapped_clear(self);
1232            return SetFromWindowsErr(err);
1233    }
1234}
1235
1236/*[clinic input]
1237_overlapped.Overlapped.WSASend
1238
1239    handle: HANDLE
1240    buf as bufobj: Py_buffer
1241    flags: DWORD
1242    /
1243
1244Start overlapped send.
1245[clinic start generated code]*/
1246
1247static PyObject *
1248_overlapped_Overlapped_WSASend_impl(OverlappedObject *self, HANDLE handle,
1249                                    Py_buffer *bufobj, DWORD flags)
1250/*[clinic end generated code: output=3baaa6e1f7fe229e input=c4167420ba2f93d8]*/
1251{
1252    DWORD written;
1253    WSABUF wsabuf;
1254    int ret;
1255    DWORD err;
1256
1257    if (self->type != TYPE_NONE) {
1258        PyErr_SetString(PyExc_ValueError, "operation already attempted");
1259        return NULL;
1260    }
1261
1262#if SIZEOF_SIZE_T > SIZEOF_LONG
1263    if (bufobj->len > (Py_ssize_t)ULONG_MAX) {
1264        PyErr_SetString(PyExc_ValueError, "buffer too large");
1265        return NULL;
1266    }
1267#endif
1268    steal_buffer(&self->user_buffer, bufobj);
1269
1270    self->type = TYPE_WRITE;
1271    self->handle = handle;
1272    wsabuf.len = (DWORD)self->user_buffer.len;
1273    wsabuf.buf = self->user_buffer.buf;
1274
1275    Py_BEGIN_ALLOW_THREADS
1276    ret = WSASend((SOCKET)handle, &wsabuf, 1, &written, flags,
1277                  &self->overlapped, NULL);
1278    Py_END_ALLOW_THREADS
1279
1280    self->error = err = (ret < 0 ? WSAGetLastError() : ERROR_SUCCESS);
1281    switch (err) {
1282        case ERROR_SUCCESS:
1283        case ERROR_IO_PENDING:
1284            Py_RETURN_NONE;
1285        default:
1286            Overlapped_clear(self);
1287            return SetFromWindowsErr(err);
1288    }
1289}
1290
1291/*[clinic input]
1292_overlapped.Overlapped.AcceptEx
1293
1294    listen_handle as ListenSocket: HANDLE
1295    accept_handle as AcceptSocket: HANDLE
1296    /
1297
1298Start overlapped wait for client to connect.
1299[clinic start generated code]*/
1300
1301static PyObject *
1302_overlapped_Overlapped_AcceptEx_impl(OverlappedObject *self,
1303                                     HANDLE ListenSocket,
1304                                     HANDLE AcceptSocket)
1305/*[clinic end generated code: output=9a7381d4232af889 input=b83473224fc3a1c5]*/
1306{
1307    DWORD BytesReceived;
1308    DWORD size;
1309    PyObject *buf;
1310    BOOL ret;
1311    DWORD err;
1312
1313    if (self->type != TYPE_NONE) {
1314        PyErr_SetString(PyExc_ValueError, "operation already attempted");
1315        return NULL;
1316    }
1317
1318    size = sizeof(struct sockaddr_in6) + 16;
1319    buf = PyBytes_FromStringAndSize(NULL, size*2);
1320    if (!buf)
1321        return NULL;
1322
1323    self->type = TYPE_ACCEPT;
1324    self->handle = ListenSocket;
1325    self->allocated_buffer = buf;
1326
1327    Py_BEGIN_ALLOW_THREADS
1328    ret = Py_AcceptEx((SOCKET)ListenSocket, (SOCKET)AcceptSocket,
1329                      PyBytes_AS_STRING(buf), 0, size, size, &BytesReceived,
1330                      &self->overlapped);
1331    Py_END_ALLOW_THREADS
1332
1333    self->error = err = ret ? ERROR_SUCCESS : WSAGetLastError();
1334    switch (err) {
1335        case ERROR_SUCCESS:
1336        case ERROR_IO_PENDING:
1337            Py_RETURN_NONE;
1338        default:
1339            Overlapped_clear(self);
1340            return SetFromWindowsErr(err);
1341    }
1342}
1343
1344
1345static int
1346parse_address(PyObject *obj, SOCKADDR *Address, int Length)
1347{
1348    PyObject *Host_obj;
1349    Py_UNICODE *Host;
1350    unsigned short Port;
1351    unsigned long FlowInfo;
1352    unsigned long ScopeId;
1353
1354    memset(Address, 0, Length);
1355
1356    switch (PyTuple_GET_SIZE(obj)) {
1357    case 2: {
1358        if (!PyArg_ParseTuple(obj, "UH", &Host_obj, &Port)) {
1359            return -1;
1360        }
1361#if USE_UNICODE_WCHAR_CACHE
1362        Host = (wchar_t *)_PyUnicode_AsUnicode(Host_obj);
1363#else /* USE_UNICODE_WCHAR_CACHE */
1364        Host = PyUnicode_AsWideCharString(Host_obj, NULL);
1365#endif /* USE_UNICODE_WCHAR_CACHE */
1366        if (Host == NULL) {
1367            return -1;
1368        }
1369        Address->sa_family = AF_INET;
1370        if (WSAStringToAddressW(Host, AF_INET, NULL, Address, &Length) < 0) {
1371            SetFromWindowsErr(WSAGetLastError());
1372            Length = -1;
1373        }
1374        else {
1375            ((SOCKADDR_IN*)Address)->sin_port = htons(Port);
1376        }
1377#if !USE_UNICODE_WCHAR_CACHE
1378        PyMem_Free(Host);
1379#endif /* USE_UNICODE_WCHAR_CACHE */
1380        return Length;
1381    }
1382    case 4: {
1383        if (!PyArg_ParseTuple(obj,
1384                "UHkk;ConnectEx(): illegal address_as_bytes argument",
1385                &Host_obj, &Port, &FlowInfo, &ScopeId))
1386        {
1387            return -1;
1388        }
1389#if USE_UNICODE_WCHAR_CACHE
1390        Host = (wchar_t *)_PyUnicode_AsUnicode(Host_obj);
1391#else /* USE_UNICODE_WCHAR_CACHE */
1392        Host = PyUnicode_AsWideCharString(Host_obj, NULL);
1393#endif /* USE_UNICODE_WCHAR_CACHE */
1394        if (Host == NULL) {
1395            return -1;
1396        }
1397        Address->sa_family = AF_INET6;
1398        if (WSAStringToAddressW(Host, AF_INET6, NULL, Address, &Length) < 0) {
1399            SetFromWindowsErr(WSAGetLastError());
1400            Length = -1;
1401        }
1402        else {
1403            ((SOCKADDR_IN6*)Address)->sin6_port = htons(Port);
1404            ((SOCKADDR_IN6*)Address)->sin6_flowinfo = FlowInfo;
1405            ((SOCKADDR_IN6*)Address)->sin6_scope_id = ScopeId;
1406        }
1407#if !USE_UNICODE_WCHAR_CACHE
1408        PyMem_Free(Host);
1409#endif /* USE_UNICODE_WCHAR_CACHE */
1410        return Length;
1411    }
1412    default:
1413        PyErr_SetString(PyExc_ValueError, "illegal address_as_bytes argument");
1414        return -1;
1415    }
1416}
1417
1418/*[clinic input]
1419_overlapped.Overlapped.ConnectEx
1420
1421    client_handle as ConnectSocket: HANDLE
1422    address_as_bytes as AddressObj: object(subclass_of='&PyTuple_Type')
1423    /
1424
1425Start overlapped connect.
1426
1427client_handle should be unbound.
1428[clinic start generated code]*/
1429
1430static PyObject *
1431_overlapped_Overlapped_ConnectEx_impl(OverlappedObject *self,
1432                                      HANDLE ConnectSocket,
1433                                      PyObject *AddressObj)
1434/*[clinic end generated code: output=5aebbbdb4f022833 input=d6bbd2d84b156fc1]*/
1435{
1436    char AddressBuf[sizeof(struct sockaddr_in6)];
1437    SOCKADDR *Address = (SOCKADDR*)AddressBuf;
1438    int Length;
1439    BOOL ret;
1440    DWORD err;
1441
1442    if (self->type != TYPE_NONE) {
1443        PyErr_SetString(PyExc_ValueError, "operation already attempted");
1444        return NULL;
1445    }
1446
1447    Length = sizeof(AddressBuf);
1448    Length = parse_address(AddressObj, Address, Length);
1449    if (Length < 0)
1450        return NULL;
1451
1452    self->type = TYPE_CONNECT;
1453    self->handle = ConnectSocket;
1454
1455    Py_BEGIN_ALLOW_THREADS
1456    ret = Py_ConnectEx((SOCKET)ConnectSocket, Address, Length,
1457                       NULL, 0, NULL, &self->overlapped);
1458    Py_END_ALLOW_THREADS
1459
1460    self->error = err = ret ? ERROR_SUCCESS : WSAGetLastError();
1461    switch (err) {
1462        case ERROR_SUCCESS:
1463        case ERROR_IO_PENDING:
1464            Py_RETURN_NONE;
1465        default:
1466            Overlapped_clear(self);
1467            return SetFromWindowsErr(err);
1468    }
1469}
1470
1471/*[clinic input]
1472_overlapped.Overlapped.DisconnectEx
1473
1474    handle as Socket: HANDLE
1475    flags: DWORD
1476    /
1477
1478[clinic start generated code]*/
1479
1480static PyObject *
1481_overlapped_Overlapped_DisconnectEx_impl(OverlappedObject *self,
1482                                         HANDLE Socket, DWORD flags)
1483/*[clinic end generated code: output=8d64ddb8c93c2126 input=680845cdcdf820eb]*/
1484{
1485    BOOL ret;
1486    DWORD err;
1487
1488    if (self->type != TYPE_NONE) {
1489        PyErr_SetString(PyExc_ValueError, "operation already attempted");
1490        return NULL;
1491    }
1492
1493    self->type = TYPE_DISCONNECT;
1494    self->handle = Socket;
1495
1496    Py_BEGIN_ALLOW_THREADS
1497    ret = Py_DisconnectEx((SOCKET)Socket, &self->overlapped, flags, 0);
1498    Py_END_ALLOW_THREADS
1499
1500    self->error = err = ret ? ERROR_SUCCESS : WSAGetLastError();
1501    switch (err) {
1502        case ERROR_SUCCESS:
1503        case ERROR_IO_PENDING:
1504            Py_RETURN_NONE;
1505        default:
1506            Overlapped_clear(self);
1507            return SetFromWindowsErr(err);
1508    }
1509}
1510
1511/*[clinic input]
1512_overlapped.Overlapped.TransmitFile
1513
1514    socket as Socket: HANDLE
1515    file as File: HANDLE
1516    offset: DWORD
1517    offset_high: DWORD
1518    count_to_write: DWORD
1519    count_per_send: DWORD
1520    flags: DWORD
1521    /
1522
1523Transmit file data over a connected socket.
1524[clinic start generated code]*/
1525
1526static PyObject *
1527_overlapped_Overlapped_TransmitFile_impl(OverlappedObject *self,
1528                                         HANDLE Socket, HANDLE File,
1529                                         DWORD offset, DWORD offset_high,
1530                                         DWORD count_to_write,
1531                                         DWORD count_per_send, DWORD flags)
1532/*[clinic end generated code: output=03f3ca5512e678fd input=7e6f97b391f60e8c]*/
1533{
1534    BOOL ret;
1535    DWORD err;
1536
1537    if (self->type != TYPE_NONE) {
1538        PyErr_SetString(PyExc_ValueError, "operation already attempted");
1539        return NULL;
1540    }
1541
1542    self->type = TYPE_TRANSMIT_FILE;
1543    self->handle = Socket;
1544    self->overlapped.Offset = offset;
1545    self->overlapped.OffsetHigh = offset_high;
1546
1547    Py_BEGIN_ALLOW_THREADS
1548    ret = Py_TransmitFile((SOCKET)Socket, File, count_to_write,
1549                          count_per_send, &self->overlapped, NULL, flags);
1550    Py_END_ALLOW_THREADS
1551
1552    self->error = err = ret ? ERROR_SUCCESS : WSAGetLastError();
1553    switch (err) {
1554        case ERROR_SUCCESS:
1555        case ERROR_IO_PENDING:
1556            Py_RETURN_NONE;
1557        default:
1558            Overlapped_clear(self);
1559            return SetFromWindowsErr(err);
1560    }
1561}
1562
1563/*[clinic input]
1564_overlapped.Overlapped.ConnectNamedPipe
1565
1566    handle as Pipe: HANDLE
1567    /
1568
1569Start overlapped wait for a client to connect.
1570[clinic start generated code]*/
1571
1572static PyObject *
1573_overlapped_Overlapped_ConnectNamedPipe_impl(OverlappedObject *self,
1574                                             HANDLE Pipe)
1575/*[clinic end generated code: output=3e69adfe55818abe input=8b0d4cef8a72f7bc]*/
1576{
1577    BOOL ret;
1578    DWORD err;
1579
1580    if (self->type != TYPE_NONE) {
1581        PyErr_SetString(PyExc_ValueError, "operation already attempted");
1582        return NULL;
1583    }
1584
1585    self->type = TYPE_CONNECT_NAMED_PIPE;
1586    self->handle = Pipe;
1587
1588    Py_BEGIN_ALLOW_THREADS
1589    ret = ConnectNamedPipe(Pipe, &self->overlapped);
1590    Py_END_ALLOW_THREADS
1591
1592    self->error = err = ret ? ERROR_SUCCESS : GetLastError();
1593    switch (err) {
1594        case ERROR_PIPE_CONNECTED:
1595            mark_as_completed(&self->overlapped);
1596            Py_RETURN_TRUE;
1597        case ERROR_SUCCESS:
1598        case ERROR_IO_PENDING:
1599            Py_RETURN_FALSE;
1600        default:
1601            Overlapped_clear(self);
1602            return SetFromWindowsErr(err);
1603    }
1604}
1605
1606/*[clinic input]
1607_overlapped.Overlapped.ConnectPipe
1608
1609    addr as Address: Py_UNICODE
1610    /
1611
1612Connect to the pipe for asynchronous I/O (overlapped).
1613[clinic start generated code]*/
1614
1615static PyObject *
1616_overlapped_Overlapped_ConnectPipe_impl(OverlappedObject *self,
1617                                        const Py_UNICODE *Address)
1618/*[clinic end generated code: output=3cc9661667d459d4 input=167c06a274efcefc]*/
1619{
1620    HANDLE PipeHandle;
1621
1622    Py_BEGIN_ALLOW_THREADS
1623    PipeHandle = CreateFileW(Address,
1624                             GENERIC_READ | GENERIC_WRITE,
1625                             0, NULL, OPEN_EXISTING,
1626                             FILE_FLAG_OVERLAPPED, NULL);
1627    Py_END_ALLOW_THREADS
1628
1629    if (PipeHandle == INVALID_HANDLE_VALUE)
1630        return SetFromWindowsErr(0);
1631    return Py_BuildValue(F_HANDLE, PipeHandle);
1632}
1633
1634static PyObject*
1635Overlapped_getaddress(OverlappedObject *self)
1636{
1637    return PyLong_FromVoidPtr(&self->overlapped);
1638}
1639
1640static PyObject*
1641Overlapped_getpending(OverlappedObject *self)
1642{
1643    return PyBool_FromLong(!HasOverlappedIoCompleted(&self->overlapped) &&
1644                           self->type != TYPE_NOT_STARTED);
1645}
1646
1647static int
1648Overlapped_traverse(OverlappedObject *self, visitproc visit, void *arg)
1649{
1650    switch (self->type) {
1651    case TYPE_READ:
1652    case TYPE_ACCEPT:
1653        Py_VISIT(self->allocated_buffer);
1654        break;
1655    case TYPE_WRITE:
1656    case TYPE_WRITE_TO:
1657    case TYPE_READINTO:
1658        if (self->user_buffer.obj) {
1659            Py_VISIT(&self->user_buffer.obj);
1660        }
1661        break;
1662    case TYPE_READ_FROM:
1663        Py_VISIT(self->read_from.result);
1664        Py_VISIT(self->read_from.allocated_buffer);
1665        break;
1666    case TYPE_READ_FROM_INTO:
1667        Py_VISIT(self->read_from_into.result);
1668        if (self->read_from_into.user_buffer.obj) {
1669            Py_VISIT(&self->read_from_into.user_buffer.obj);
1670        }
1671        break;
1672    }
1673    return 0;
1674}
1675
1676// UDP functions
1677
1678/*
1679 * Note: WSAConnect does not support Overlapped I/O so this function should
1680 * _only_ be used for connectionless sockets (UDP).
1681 */
1682
1683/*[clinic input]
1684_overlapped.WSAConnect
1685
1686    client_handle as ConnectSocket: HANDLE
1687    address_as_bytes as AddressObj: object(subclass_of='&PyTuple_Type')
1688    /
1689
1690Bind a remote address to a connectionless (UDP) socket.
1691[clinic start generated code]*/
1692
1693static PyObject *
1694_overlapped_WSAConnect_impl(PyObject *module, HANDLE ConnectSocket,
1695                            PyObject *AddressObj)
1696/*[clinic end generated code: output=ea0b4391e94dad63 input=7cf65313d49c015a]*/
1697{
1698    char AddressBuf[sizeof(struct sockaddr_in6)];
1699    SOCKADDR *Address = (SOCKADDR*)AddressBuf;
1700    int Length;
1701    int err;
1702
1703    Length = sizeof(AddressBuf);
1704    Length = parse_address(AddressObj, Address, Length);
1705    if (Length < 0) {
1706        return NULL;
1707    }
1708
1709    Py_BEGIN_ALLOW_THREADS
1710    // WSAConnect does not support overlapped I/O so this call will
1711    // successfully complete immediately.
1712    err = WSAConnect((SOCKET)ConnectSocket, Address, Length,
1713                        NULL, NULL, NULL, NULL);
1714    Py_END_ALLOW_THREADS
1715
1716    if (err == 0) {
1717        Py_RETURN_NONE;
1718    }
1719    else {
1720        return SetFromWindowsErr(WSAGetLastError());
1721    }
1722}
1723
1724/*[clinic input]
1725_overlapped.Overlapped.WSASendTo
1726
1727    handle: HANDLE
1728    buf as bufobj: Py_buffer
1729    flags: DWORD
1730    address_as_bytes as AddressObj: object(subclass_of='&PyTuple_Type')
1731    /
1732
1733Start overlapped sendto over a connectionless (UDP) socket.
1734[clinic start generated code]*/
1735
1736static PyObject *
1737_overlapped_Overlapped_WSASendTo_impl(OverlappedObject *self, HANDLE handle,
1738                                      Py_buffer *bufobj, DWORD flags,
1739                                      PyObject *AddressObj)
1740/*[clinic end generated code: output=3cdedc4cfaeb70cd input=31f44cd4ab92fc33]*/
1741{
1742    char AddressBuf[sizeof(struct sockaddr_in6)];
1743    SOCKADDR *Address = (SOCKADDR*)AddressBuf;
1744    int AddressLength;
1745    DWORD written;
1746    WSABUF wsabuf;
1747    int ret;
1748    DWORD err;
1749
1750    // Parse the "to" address
1751    AddressLength = sizeof(AddressBuf);
1752    AddressLength = parse_address(AddressObj, Address, AddressLength);
1753    if (AddressLength < 0) {
1754        return NULL;
1755    }
1756
1757    if (self->type != TYPE_NONE) {
1758        PyErr_SetString(PyExc_ValueError, "operation already attempted");
1759        return NULL;
1760    }
1761
1762#if SIZEOF_SIZE_T > SIZEOF_LONG
1763    if (bufobj->len > (Py_ssize_t)ULONG_MAX) {
1764        PyErr_SetString(PyExc_ValueError, "buffer too large");
1765        return NULL;
1766    }
1767#endif
1768    steal_buffer(&self->user_buffer, bufobj);
1769
1770    self->type = TYPE_WRITE_TO;
1771    self->handle = handle;
1772    wsabuf.len = (DWORD)self->user_buffer.len;
1773    wsabuf.buf = self->user_buffer.buf;
1774
1775    Py_BEGIN_ALLOW_THREADS
1776    ret = WSASendTo((SOCKET)handle, &wsabuf, 1, &written, flags,
1777                    Address, AddressLength, &self->overlapped, NULL);
1778    Py_END_ALLOW_THREADS
1779
1780    self->error = err = (ret == SOCKET_ERROR ? WSAGetLastError() :
1781                                               ERROR_SUCCESS);
1782
1783    switch(err) {
1784        case ERROR_SUCCESS:
1785        case ERROR_IO_PENDING:
1786            Py_RETURN_NONE;
1787        default:
1788            self->type = TYPE_NOT_STARTED;
1789            return SetFromWindowsErr(err);
1790    }
1791}
1792
1793
1794
1795PyDoc_STRVAR(
1796    Overlapped_WSARecvFrom_doc,
1797    "RecvFile(handle, size, flags) -> Overlapped[(message, (host, port))]\n\n"
1798    "Start overlapped receive");
1799
1800/*[clinic input]
1801_overlapped.Overlapped.WSARecvFrom
1802
1803    handle: HANDLE
1804    size: DWORD
1805    flags: DWORD = 0
1806    /
1807
1808Start overlapped receive.
1809[clinic start generated code]*/
1810
1811static PyObject *
1812_overlapped_Overlapped_WSARecvFrom_impl(OverlappedObject *self,
1813                                        HANDLE handle, DWORD size,
1814                                        DWORD flags)
1815/*[clinic end generated code: output=13832a2025b86860 input=1b2663fa130e0286]*/
1816{
1817    PyObject *buf;
1818    DWORD nread;
1819    WSABUF wsabuf;
1820    int ret;
1821    DWORD err;
1822
1823    if (self->type != TYPE_NONE) {
1824        PyErr_SetString(PyExc_ValueError, "operation already attempted");
1825        return NULL;
1826    }
1827
1828#if SIZEOF_SIZE_T <= SIZEOF_LONG
1829    size = Py_MIN(size, (DWORD)PY_SSIZE_T_MAX);
1830#endif
1831    buf = PyBytes_FromStringAndSize(NULL, Py_MAX(size, 1));
1832    if (buf == NULL) {
1833        return NULL;
1834    }
1835
1836    wsabuf.buf = PyBytes_AS_STRING(buf);
1837    wsabuf.len = size;
1838
1839    self->type = TYPE_READ_FROM;
1840    self->handle = handle;
1841    self->read_from.allocated_buffer = buf;
1842    memset(&self->read_from.address, 0, sizeof(self->read_from.address));
1843    self->read_from.address_length = sizeof(self->read_from.address);
1844
1845    Py_BEGIN_ALLOW_THREADS
1846    ret = WSARecvFrom((SOCKET)handle, &wsabuf, 1, &nread, &flags,
1847                      (SOCKADDR*)&self->read_from.address,
1848                      &self->read_from.address_length,
1849                      &self->overlapped, NULL);
1850    Py_END_ALLOW_THREADS
1851
1852    self->error = err = (ret < 0 ? WSAGetLastError() : ERROR_SUCCESS);
1853    switch (err) {
1854    case ERROR_BROKEN_PIPE:
1855        mark_as_completed(&self->overlapped);
1856        return SetFromWindowsErr(err);
1857    case ERROR_SUCCESS:
1858    case ERROR_MORE_DATA:
1859    case ERROR_IO_PENDING:
1860        Py_RETURN_NONE;
1861    default:
1862        self->type = TYPE_NOT_STARTED;
1863        return SetFromWindowsErr(err);
1864    }
1865}
1866
1867
1868/*[clinic input]
1869_overlapped.Overlapped.WSARecvFromInto
1870
1871    handle: HANDLE
1872    buf as bufobj: Py_buffer
1873    size: DWORD
1874    flags: DWORD = 0
1875    /
1876
1877Start overlapped receive.
1878[clinic start generated code]*/
1879
1880static PyObject *
1881_overlapped_Overlapped_WSARecvFromInto_impl(OverlappedObject *self,
1882                                            HANDLE handle, Py_buffer *bufobj,
1883                                            DWORD size, DWORD flags)
1884/*[clinic end generated code: output=30c7ea171a691757 input=4be4b08d03531e76]*/
1885{
1886    DWORD nread;
1887    WSABUF wsabuf;
1888    int ret;
1889    DWORD err;
1890
1891    if (self->type != TYPE_NONE) {
1892        PyErr_SetString(PyExc_ValueError, "operation already attempted");
1893        return NULL;
1894    }
1895
1896#if SIZEOF_SIZE_T > SIZEOF_LONG
1897    if (bufobj->len > (Py_ssize_t)ULONG_MAX) {
1898        PyErr_SetString(PyExc_ValueError, "buffer too large");
1899        return NULL;
1900    }
1901#endif
1902
1903    wsabuf.buf = bufobj->buf;
1904    wsabuf.len = size;
1905
1906    self->type = TYPE_READ_FROM_INTO;
1907    self->handle = handle;
1908    steal_buffer(&self->read_from_into.user_buffer, bufobj);
1909    memset(&self->read_from_into.address, 0, sizeof(self->read_from_into.address));
1910    self->read_from_into.address_length = sizeof(self->read_from_into.address);
1911
1912    Py_BEGIN_ALLOW_THREADS
1913    ret = WSARecvFrom((SOCKET)handle, &wsabuf, 1, &nread, &flags,
1914                      (SOCKADDR*)&self->read_from_into.address,
1915                      &self->read_from_into.address_length,
1916                      &self->overlapped, NULL);
1917    Py_END_ALLOW_THREADS
1918
1919    self->error = err = (ret < 0 ? WSAGetLastError() : ERROR_SUCCESS);
1920    switch (err) {
1921    case ERROR_BROKEN_PIPE:
1922        mark_as_completed(&self->overlapped);
1923        return SetFromWindowsErr(err);
1924    case ERROR_SUCCESS:
1925    case ERROR_MORE_DATA:
1926    case ERROR_IO_PENDING:
1927        Py_RETURN_NONE;
1928    default:
1929        self->type = TYPE_NOT_STARTED;
1930        return SetFromWindowsErr(err);
1931    }
1932}
1933
1934
1935#include "clinic/overlapped.c.h"
1936
1937static PyMethodDef Overlapped_methods[] = {
1938    _OVERLAPPED_OVERLAPPED_GETRESULT_METHODDEF
1939    _OVERLAPPED_OVERLAPPED_CANCEL_METHODDEF
1940    _OVERLAPPED_OVERLAPPED_READFILE_METHODDEF
1941    _OVERLAPPED_OVERLAPPED_READFILEINTO_METHODDEF
1942    _OVERLAPPED_OVERLAPPED_WSARECV_METHODDEF
1943    _OVERLAPPED_OVERLAPPED_WSARECVINTO_METHODDEF
1944    _OVERLAPPED_OVERLAPPED_WSARECVFROM_METHODDEF
1945    _OVERLAPPED_OVERLAPPED_WSARECVFROMINTO_METHODDEF
1946    _OVERLAPPED_OVERLAPPED_WRITEFILE_METHODDEF
1947    _OVERLAPPED_OVERLAPPED_WSASEND_METHODDEF
1948    _OVERLAPPED_OVERLAPPED_ACCEPTEX_METHODDEF
1949    _OVERLAPPED_OVERLAPPED_CONNECTEX_METHODDEF
1950    _OVERLAPPED_OVERLAPPED_DISCONNECTEX_METHODDEF
1951    _OVERLAPPED_OVERLAPPED_TRANSMITFILE_METHODDEF
1952    _OVERLAPPED_OVERLAPPED_CONNECTNAMEDPIPE_METHODDEF
1953    _OVERLAPPED_OVERLAPPED_WSARECVFROM_METHODDEF
1954    _OVERLAPPED_OVERLAPPED_WSASENDTO_METHODDEF
1955    {NULL}
1956};
1957
1958static PyMemberDef Overlapped_members[] = {
1959    {"error", T_ULONG,
1960     offsetof(OverlappedObject, error),
1961     READONLY, "Error from last operation"},
1962    {"event", T_HANDLE,
1963     offsetof(OverlappedObject, overlapped) + offsetof(OVERLAPPED, hEvent),
1964     READONLY, "Overlapped event handle"},
1965    {NULL}
1966};
1967
1968static PyGetSetDef Overlapped_getsets[] = {
1969    {"address", (getter)Overlapped_getaddress, NULL,
1970     "Address of overlapped structure"},
1971    {"pending", (getter)Overlapped_getpending, NULL,
1972     "Whether the operation is pending"},
1973    {NULL},
1974};
1975
1976static PyType_Slot overlapped_type_slots[] = {
1977    {Py_tp_dealloc, Overlapped_dealloc},
1978    {Py_tp_doc, (char *)_overlapped_Overlapped__doc__},
1979    {Py_tp_traverse, Overlapped_traverse},
1980    {Py_tp_methods, Overlapped_methods},
1981    {Py_tp_members, Overlapped_members},
1982    {Py_tp_getset, Overlapped_getsets},
1983    {Py_tp_new, _overlapped_Overlapped},
1984    {0,0}
1985};
1986
1987static PyType_Spec overlapped_type_spec = {
1988    .name = "_overlapped.Overlapped",
1989    .basicsize = sizeof(OverlappedObject),
1990    .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE),
1991    .slots = overlapped_type_slots
1992};
1993
1994static PyMethodDef overlapped_functions[] = {
1995    _OVERLAPPED_CREATEIOCOMPLETIONPORT_METHODDEF
1996    _OVERLAPPED_GETQUEUEDCOMPLETIONSTATUS_METHODDEF
1997    _OVERLAPPED_POSTQUEUEDCOMPLETIONSTATUS_METHODDEF
1998    _OVERLAPPED_FORMATMESSAGE_METHODDEF
1999    _OVERLAPPED_BINDLOCAL_METHODDEF
2000    _OVERLAPPED_REGISTERWAITWITHQUEUE_METHODDEF
2001    _OVERLAPPED_UNREGISTERWAIT_METHODDEF
2002    _OVERLAPPED_UNREGISTERWAITEX_METHODDEF
2003    _OVERLAPPED_CREATEEVENT_METHODDEF
2004    _OVERLAPPED_SETEVENT_METHODDEF
2005    _OVERLAPPED_RESETEVENT_METHODDEF
2006    _OVERLAPPED_OVERLAPPED_CONNECTPIPE_METHODDEF
2007    _OVERLAPPED_WSACONNECT_METHODDEF
2008    {NULL}
2009};
2010
2011static int
2012overlapped_traverse(PyObject *module, visitproc visit, void *arg)
2013{
2014    OverlappedState *state = overlapped_get_state(module);
2015    Py_VISIT(state->overlapped_type);
2016    return 0;
2017}
2018
2019static int
2020overlapped_clear(PyObject *module)
2021{
2022    OverlappedState *state = overlapped_get_state(module);
2023    Py_CLEAR(state->overlapped_type);
2024    return 0;
2025}
2026
2027static void
2028overlapped_free(void *module)
2029{
2030    overlapped_clear((PyObject *)module);
2031}
2032
2033#define WINAPI_CONSTANT(fmt, con) \
2034    do { \
2035        PyObject *value = Py_BuildValue(fmt, con); \
2036        if (value == NULL) { \
2037            return -1; \
2038        } \
2039        if (PyModule_AddObject(module, #con, value) < 0 ) { \
2040            Py_DECREF(value); \
2041            return -1; \
2042        } \
2043    } while (0)
2044
2045static int
2046overlapped_exec(PyObject *module)
2047{
2048    /* Ensure WSAStartup() called before initializing function pointers */
2049    PyObject *socket_module = PyImport_ImportModule("_socket");
2050    if (!socket_module) {
2051        return -1;
2052    }
2053
2054    Py_DECREF(socket_module);
2055
2056    if (initialize_function_pointers() < 0) {
2057        return -1;
2058    }
2059
2060    OverlappedState *st = overlapped_get_state(module);
2061    st->overlapped_type = (PyTypeObject *)PyType_FromModuleAndSpec(
2062        module, &overlapped_type_spec, NULL);
2063    if (st->overlapped_type == NULL) {
2064        return -1;
2065    }
2066
2067    if (PyModule_AddType(module, st->overlapped_type) < 0) {
2068        return -1;
2069    }
2070
2071    WINAPI_CONSTANT(F_DWORD,  ERROR_IO_PENDING);
2072    WINAPI_CONSTANT(F_DWORD,  ERROR_NETNAME_DELETED);
2073    WINAPI_CONSTANT(F_DWORD,  ERROR_OPERATION_ABORTED);
2074    WINAPI_CONSTANT(F_DWORD,  ERROR_SEM_TIMEOUT);
2075    WINAPI_CONSTANT(F_DWORD,  ERROR_PIPE_BUSY);
2076    WINAPI_CONSTANT(F_DWORD,  INFINITE);
2077    WINAPI_CONSTANT(F_HANDLE, INVALID_HANDLE_VALUE);
2078    WINAPI_CONSTANT(F_HANDLE, NULL);
2079    WINAPI_CONSTANT(F_DWORD,  SO_UPDATE_ACCEPT_CONTEXT);
2080    WINAPI_CONSTANT(F_DWORD,  SO_UPDATE_CONNECT_CONTEXT);
2081    WINAPI_CONSTANT(F_DWORD,  TF_REUSE_SOCKET);
2082
2083    return 0;
2084}
2085
2086static PyModuleDef_Slot overlapped_slots[] = {
2087    {Py_mod_exec, overlapped_exec},
2088    {0, NULL}
2089};
2090
2091static struct PyModuleDef overlapped_module = {
2092    PyModuleDef_HEAD_INIT,
2093    .m_name = "_overlapped",
2094    .m_size = sizeof(OverlappedState),
2095    .m_methods = overlapped_functions,
2096    .m_slots = overlapped_slots,
2097    .m_traverse = overlapped_traverse,
2098    .m_clear = overlapped_clear,
2099    .m_free = overlapped_free
2100};
2101
2102PyMODINIT_FUNC
2103PyInit__overlapped(void)
2104{
2105    return PyModuleDef_Init(&overlapped_module);
2106}
2107