diff options
author | Martin Willi <martin@revosec.ch> | 2014-06-10 15:58:31 +0200 |
---|---|---|
committer | Martin Willi <martin@revosec.ch> | 2014-06-17 15:19:25 +0200 |
commit | 2d846c2035de26a52d1439b46b0ca7903fa9dca1 (patch) | |
tree | b18c76573e32c79dc697af4297877f58d1c5b16f /src | |
parent | 31f26960761c7f45505957327f303e57551c9997 (diff) | |
download | strongswan-2d846c2035de26a52d1439b46b0ca7903fa9dca1.tar.bz2 strongswan-2d846c2035de26a52d1439b46b0ca7903fa9dca1.tar.xz |
socket-win: Use non-overlapped I/O and socket event selection
The use of overlapped I/O was incorrect, as we passed stack based buffers, but
did not cancel/wait for pending completion on all sockets. Our receive-from-all
socket interface is actually tricky to implement using overlapped I/O. Switch
to WSAEventSelect() event management, which can be canceled properly while
working in a select()-like way.
Diffstat (limited to 'src')
-rw-r--r-- | src/libcharon/plugins/socket_win/socket_win_socket.c | 44 |
1 files changed, 13 insertions, 31 deletions
diff --git a/src/libcharon/plugins/socket_win/socket_win_socket.c b/src/libcharon/plugins/socket_win/socket_win_socket.c index cf7a2ce5a..5ebe04aac 100644 --- a/src/libcharon/plugins/socket_win/socket_win_socket.c +++ b/src/libcharon/plugins/socket_win/socket_win_socket.c @@ -88,10 +88,9 @@ struct private_socket_win_socket_t { METHOD(socket_t, receiver, status_t, private_socket_win_socket_t *this, packet_t **out) { - WSAOVERLAPPED overlapped[SOCKET_COUNT] = {}; char buf[this->max_packet], cbuf[128]; bool old; - DWORD i, len, flags, err; + DWORD i, len, err; WSAMSG msg; WSABUF data; WSACMSGHDR *cmsg; @@ -110,25 +109,7 @@ METHOD(socket_t, receiver, status_t, msg.Control.buf = cbuf; msg.Control.len = sizeof(cbuf); - for (i = 0; i < SOCKET_COUNT; i++) - { - overlapped[i].hEvent = this->events[i]; - - if (this->socks[i] != INVALID_SOCKET) - { - if (this->WSARecvMsg(this->socks[i], &msg, NULL, - &overlapped[i], NULL) == SOCKET_ERROR) - { - err = WSAGetLastError(); - if (err != WSA_IO_PENDING) - { - DBG1(DBG_NET, "reading from socket failed: %d", err); - return FAILED; - } - } - } - } - + /* wait for socket events */ old = thread_cancelability(TRUE); i = WSAWaitForMultipleEvents(SOCKET_COUNT, this->events, FALSE, INFINITE, TRUE); @@ -143,8 +124,8 @@ METHOD(socket_t, receiver, status_t, /* WSAEvents must be reset manually */ WSAResetEvent(this->events[i]); - if (!WSAGetOverlappedResult(this->socks[i], &overlapped[i], - &len, FALSE, &flags)) + if (this->WSARecvMsg(this->socks[i], &msg, &len, + NULL, NULL) == SOCKET_ERROR) { err = WSAGetLastError(); /* ignore WSAECONNRESET; this is returned for any ICMP port unreachable, @@ -152,16 +133,11 @@ METHOD(socket_t, receiver, status_t, * we try to receive. */ if (err != WSAECONNRESET) { - DBG1(DBG_NET, "getting socket result failed: %d", err); + DBG1(DBG_NET, "reading from socket failed: %d", WSAGetLastError()); } return FAILED; } - if (len >= sizeof(buf)) - { - DBG1(DBG_NET, "receive buffer too small, packet discarded"); - return FAILED; - } DBG3(DBG_NET, "received packet %b", buf, (int)len); for (cmsg = WSA_CMSG_FIRSTHDR(&msg); dst == NULL && cmsg != NULL; @@ -370,8 +346,7 @@ static SOCKET open_socket(private_socket_win_socket_t *this, int i) DWORD dwon = TRUE; SOCKET s; - s = WSASocket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, - NULL, 0, WSA_FLAG_OVERLAPPED); + s = WSASocket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, NULL, 0, 0); if (s == INVALID_SOCKET) { DBG1(DBG_NET, "creating socket failed: %d", WSAGetLastError()); @@ -501,6 +476,13 @@ socket_win_socket_t *socket_win_socket_create() destroy(this); return NULL; } + if (WSAEventSelect(this->socks[i], this->events[i], + FD_READ) == SOCKET_ERROR) + { + DBG1(DBG_NET, "WSAEventSelect() failed: %d", WSAGetLastError()); + destroy(this); + return NULL; + } } if (WSAIoctl(this->socks[0], SIO_GET_EXTENSION_FUNCTION_POINTER, |