Fix WSASend/WSARecv usage w.r.t. WSABUF parameter.

The documentation states that the buffer must be kept alive during the whole operation, so using a stack allocated buffer is illegal.
This commit is contained in:
Sönke Ludwig 2017-06-26 23:31:22 +02:00
parent ef065762b3
commit a263637bd3

View file

@ -92,8 +92,9 @@ final class WinAPIEventDriverSockets : EventDriverSockets {
if (m_sockets[fd].common.refCount) // FD already in use? if (m_sockets[fd].common.refCount) // FD already in use?
return StreamSocketFD.invalid; return StreamSocketFD.invalid;
uint enable = 1; // done by wsaasyncselect
() @trusted { ioctlsocket(socket, FIONBIO, &enable); } (); //uint enable = 1;
//() @trusted { ioctlsocket(socket, FIONBIO, &enable); } ();
void setupOverlapped(ref WSAOVERLAPPEDX overlapped) @trusted @nogc nothrow { void setupOverlapped(ref WSAOVERLAPPEDX overlapped) @trusted @nogc nothrow {
overlapped.Internal = 0; overlapped.Internal = 0;
@ -200,16 +201,15 @@ final class WinAPIEventDriverSockets : EventDriverSockets {
override void read(StreamSocketFD socket, ubyte[] buffer, IOMode mode, IOCallback on_read_finish) override void read(StreamSocketFD socket, ubyte[] buffer, IOMode mode, IOCallback on_read_finish)
{ {
WSABUF buf; auto slot = () @trusted { return &m_sockets[socket].streamSocket(); } ();
buf.len = buffer.length; slot.read.buffer = buffer;
buf.buf = () @trusted { return buffer.ptr; } (); slot.read.mode = mode;
slot.read.wsabuf[0].len = buffer.length;
slot.read.wsabuf[0].buf = () @trusted { return buffer.ptr; } ();
m_sockets[socket].streamSocket.read.buffer = buffer; auto ovl = mode == IOMode.immediate ? null : &slot.read.overlapped;
m_sockets[socket].streamSocket.read.mode = mode;
auto ovl = mode == IOMode.immediate ? null : &m_sockets[socket].streamSocket.read.overlapped;
DWORD flags = 0; DWORD flags = 0;
auto ret = () @trusted { return WSARecv(socket, &buf, 1, null, &flags, ovl, &onIOReadCompleted); } (); auto ret = () @trusted { return WSARecv(socket, &slot.read.wsabuf[0], slot.read.wsabuf.length, null, &flags, ovl, &onIOReadCompleted); } ();
if (ret == SOCKET_ERROR) { if (ret == SOCKET_ERROR) {
auto err = WSAGetLastError(); auto err = WSAGetLastError();
if (err == WSA_IO_PENDING) { if (err == WSA_IO_PENDING) {
@ -222,7 +222,7 @@ final class WinAPIEventDriverSockets : EventDriverSockets {
return; return;
} }
} }
m_sockets[socket].streamSocket.read.callback = on_read_finish; slot.read.callback = on_read_finish;
m_core.addWaiter(); m_core.addWaiter();
} }
@ -255,12 +255,11 @@ final class WinAPIEventDriverSockets : EventDriverSockets {
return; return;
} }
WSABUF buf; slot.streamSocket.read.wsabuf[0].len = slot.streamSocket.read.buffer.length;
buf.len = slot.streamSocket.read.buffer.length; slot.streamSocket.read.wsabuf[0].buf = () @trusted { return cast(ubyte*)slot.streamSocket.read.buffer.ptr; } ();
buf.buf = () @trusted { return cast(ubyte*)slot.streamSocket.read.buffer.ptr; } ();
auto ovl = slot.streamSocket.read.mode == IOMode.immediate ? null : &slot.streamSocket.read.overlapped; auto ovl = slot.streamSocket.read.mode == IOMode.immediate ? null : &slot.streamSocket.read.overlapped;
DWORD flags = 0; DWORD flags = 0;
auto ret = () @trusted { return WSARecv(slot.common.fd, &buf, 1, null, &flags, ovl, &onIOReadCompleted); } (); auto ret = () @trusted { return WSARecv(slot.common.fd, &slot.streamSocket.read.wsabuf[0], slot.streamSocket.read.wsabuf.length, null, &flags, ovl, &onIOReadCompleted); } ();
if (ret == SOCKET_ERROR) { if (ret == SOCKET_ERROR) {
auto err = WSAGetLastError(); auto err = WSAGetLastError();
if (err == WSA_IO_PENDING) { if (err == WSA_IO_PENDING) {
@ -275,15 +274,14 @@ final class WinAPIEventDriverSockets : EventDriverSockets {
override void write(StreamSocketFD socket, const(ubyte)[] buffer, IOMode mode, IOCallback on_write_finish) override void write(StreamSocketFD socket, const(ubyte)[] buffer, IOMode mode, IOCallback on_write_finish)
{ {
WSABUF buf; auto slot = () @trusted { return &m_sockets[socket].streamSocket(); } ();
buf.len = buffer.length; slot.write.buffer = buffer;
buf.buf = () @trusted { return cast(ubyte*)buffer.ptr; } (); slot.write.mode = mode;
slot.write.wsabuf[0].len = buffer.length;
m_sockets[socket].streamSocket.write.buffer = buffer; slot.write.wsabuf[0].buf = () @trusted { return cast(ubyte*)buffer.ptr; } ();
m_sockets[socket].streamSocket.write.mode = mode;
auto ovl = mode == IOMode.immediate ? null : &m_sockets[socket].streamSocket.write.overlapped; auto ovl = mode == IOMode.immediate ? null : &m_sockets[socket].streamSocket.write.overlapped;
auto ret = () @trusted { return WSASend(socket, &buf, 1, null, 0, ovl, &onIOWriteCompleted); } (); auto ret = () @trusted { return WSASend(socket, &slot.write.wsabuf[0], slot.write.wsabuf.length, null, 0, ovl, &onIOWriteCompleted); } ();
if (ret == SOCKET_ERROR) { if (ret == SOCKET_ERROR) {
auto err = WSAGetLastError(); auto err = WSAGetLastError();
if (err == WSA_IO_PENDING) { if (err == WSA_IO_PENDING) {
@ -328,11 +326,10 @@ final class WinAPIEventDriverSockets : EventDriverSockets {
return; return;
} }
WSABUF buf; slot.streamSocket.write.wsabuf[0].len = slot.streamSocket.write.buffer.length;
buf.len = slot.streamSocket.write.buffer.length; slot.streamSocket.write.wsabuf[0].buf = () @trusted { return cast(ubyte*)slot.streamSocket.write.buffer.ptr; } ();
buf.buf = () @trusted { return cast(ubyte*)slot.streamSocket.write.buffer.ptr; } ();
auto ovl = slot.streamSocket.write.mode == IOMode.immediate ? null : &slot.streamSocket.write.overlapped; auto ovl = slot.streamSocket.write.mode == IOMode.immediate ? null : &slot.streamSocket.write.overlapped;
auto ret = () @trusted { return WSASend(slot.common.fd, &buf, 1, null, 0, ovl, &onIOWriteCompleted); } (); auto ret = () @trusted { return WSASend(slot.common.fd, &slot.streamSocket.write.wsabuf[0], slot.streamSocket.write.wsabuf.length, null, 0, ovl, &onIOWriteCompleted); } ();
if (ret == SOCKET_ERROR) { if (ret == SOCKET_ERROR) {
auto err = WSAGetLastError(); auto err = WSAGetLastError();
if (err == WSA_IO_PENDING) { if (err == WSA_IO_PENDING) {
@ -592,6 +589,7 @@ static struct StreamDirection(bool RO) {
WSAOVERLAPPEDX overlapped; WSAOVERLAPPEDX overlapped;
static if (RO) const(ubyte)[] buffer; static if (RO) const(ubyte)[] buffer;
else ubyte[] buffer; else ubyte[] buffer;
WSABUF[1] wsabuf;
size_t bytesTransferred; size_t bytesTransferred;
IOMode mode; IOMode mode;
IOCallback callback; IOCallback callback;