diff options
author | Andrew Svetlov <andrew.svetlov@gmail.com> | 2018-02-25 16:32:14 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-02-25 16:32:14 (GMT) |
commit | a19fb3c6aaa7632410d1d9dcb395d7101d124da4 (patch) | |
tree | 476902dc75526cc8bb22c41cf213416384c36805 /Modules | |
parent | 5fb632e83136399bad9427ee23ec8b771695290a (diff) | |
download | cpython-a19fb3c6aaa7632410d1d9dcb395d7101d124da4.zip cpython-a19fb3c6aaa7632410d1d9dcb395d7101d124da4.tar.gz cpython-a19fb3c6aaa7632410d1d9dcb395d7101d124da4.tar.bz2 |
bpo-32622: Native sendfile on windows (#5565)
* Support sendfile on Windows Proactor event loop naively.
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/overlapped.c | 64 |
1 files changed, 62 insertions, 2 deletions
diff --git a/Modules/overlapped.c b/Modules/overlapped.c index 447a337..ae7cdda 100644 --- a/Modules/overlapped.c +++ b/Modules/overlapped.c @@ -39,7 +39,7 @@ enum {TYPE_NONE, TYPE_NOT_STARTED, TYPE_READ, TYPE_READINTO, TYPE_WRITE, TYPE_ACCEPT, TYPE_CONNECT, TYPE_DISCONNECT, TYPE_CONNECT_NAMED_PIPE, - TYPE_WAIT_NAMED_PIPE_AND_CONNECT}; + TYPE_WAIT_NAMED_PIPE_AND_CONNECT, TYPE_TRANSMIT_FILE}; typedef struct { PyObject_HEAD @@ -89,6 +89,7 @@ SetFromWindowsErr(DWORD err) static LPFN_ACCEPTEX Py_AcceptEx = NULL; static LPFN_CONNECTEX Py_ConnectEx = NULL; static LPFN_DISCONNECTEX Py_DisconnectEx = NULL; +static LPFN_TRANSMITFILE Py_TransmitFile = NULL; static BOOL (CALLBACK *Py_CancelIoEx)(HANDLE, LPOVERLAPPED) = NULL; #define GET_WSA_POINTER(s, x) \ @@ -102,6 +103,7 @@ initialize_function_pointers(void) GUID GuidAcceptEx = WSAID_ACCEPTEX; GUID GuidConnectEx = WSAID_CONNECTEX; GUID GuidDisconnectEx = WSAID_DISCONNECTEX; + GUID GuidTransmitFile = WSAID_TRANSMITFILE; HINSTANCE hKernel32; SOCKET s; DWORD dwBytes; @@ -114,7 +116,8 @@ initialize_function_pointers(void) if (!GET_WSA_POINTER(s, AcceptEx) || !GET_WSA_POINTER(s, ConnectEx) || - !GET_WSA_POINTER(s, DisconnectEx)) + !GET_WSA_POINTER(s, DisconnectEx) || + !GET_WSA_POINTER(s, TransmitFile)) { closesocket(s); SetFromWindowsErr(WSAGetLastError()); @@ -1195,6 +1198,61 @@ Overlapped_DisconnectEx(OverlappedObject *self, PyObject *args) } PyDoc_STRVAR( + Overlapped_TransmitFile_doc, + "TransmitFile(socket, file, offset, offset_high, " + "count_to_write, count_per_send, flags) " + "-> Overlapped[None]\n\n" + "Transmit file data over a connected socket."); + +static PyObject * +Overlapped_TransmitFile(OverlappedObject *self, PyObject *args) +{ + SOCKET Socket; + HANDLE File; + DWORD offset; + DWORD offset_high; + DWORD count_to_write; + DWORD count_per_send; + DWORD flags; + BOOL ret; + DWORD err; + + if (!PyArg_ParseTuple(args, + F_HANDLE F_HANDLE F_DWORD F_DWORD + F_DWORD F_DWORD F_DWORD, + &Socket, &File, &offset, &offset_high, + &count_to_write, &count_per_send, + &flags)) + return NULL; + + if (self->type != TYPE_NONE) { + PyErr_SetString(PyExc_ValueError, "operation already attempted"); + return NULL; + } + + self->type = TYPE_TRANSMIT_FILE; + self->handle = (HANDLE)Socket; + self->overlapped.Offset = offset; + self->overlapped.OffsetHigh = offset_high; + + Py_BEGIN_ALLOW_THREADS + ret = Py_TransmitFile(Socket, File, count_to_write, count_per_send, + &self->overlapped, + NULL, flags); + Py_END_ALLOW_THREADS + + self->error = err = ret ? ERROR_SUCCESS : WSAGetLastError(); + switch (err) { + case ERROR_SUCCESS: + case ERROR_IO_PENDING: + Py_RETURN_NONE; + default: + self->type = TYPE_NOT_STARTED; + return SetFromWindowsErr(err); + } +} + +PyDoc_STRVAR( Overlapped_ConnectNamedPipe_doc, "ConnectNamedPipe(handle) -> Overlapped[None]\n\n" "Start overlapped wait for a client to connect."); @@ -1303,6 +1361,8 @@ static PyMethodDef Overlapped_methods[] = { METH_VARARGS, Overlapped_ConnectEx_doc}, {"DisconnectEx", (PyCFunction) Overlapped_DisconnectEx, METH_VARARGS, Overlapped_DisconnectEx_doc}, + {"TransmitFile", (PyCFunction) Overlapped_TransmitFile, + METH_VARARGS, Overlapped_TransmitFile_doc}, {"ConnectNamedPipe", (PyCFunction) Overlapped_ConnectNamedPipe, METH_VARARGS, Overlapped_ConnectNamedPipe_doc}, {NULL} |