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