VirtualBox

source: vbox/trunk/src/VBox/NetworkServices/NAT/RTWinPoll.cpp@ 53349

Last change on this file since 53349 was 52285, checked in by vboxsync, 10 years ago

NAT/Net: Amend r95372 and do return normal poll bits along with POLLERR.

While here, use the same convertion macro for FD_CLOSE/POLLHUP too and
add logging for WSANETWORKEVENTS::iErrorCode.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 4.2 KB
Line 
1/* -*- indent-tabs-mode: nil; -*- */
2#define LOG_GROUP LOG_GROUP_NAT_SERVICE
3
4#include <iprt/asm.h>
5#include <iprt/assert.h>
6#include <iprt/cdefs.h>
7#include <iprt/err.h>
8#include <iprt/string.h>
9
10#include <VBox/err.h>
11#include <VBox/log.h>
12
13#include <Winsock2.h>
14#include <Windows.h>
15#include "winpoll.h"
16
17static HANDLE g_hNetworkEvent;
18
19int
20RTWinPoll(struct pollfd *pFds, unsigned int nfds, int timeout, int *pNready)
21{
22 AssertPtrReturn(pFds, VERR_INVALID_PARAMETER);
23
24 if (g_hNetworkEvent == WSA_INVALID_EVENT)
25 {
26 g_hNetworkEvent = WSACreateEvent();
27 AssertReturn(g_hNetworkEvent != WSA_INVALID_EVENT, VERR_INTERNAL_ERROR);
28 }
29
30 for (unsigned int i = 0; i < nfds; ++i)
31 {
32 long eventMask = 0;
33 short pollEvents = pFds[i].events;
34
35 /* clean revents */
36 pFds[i].revents = 0;
37
38 /* ignore invalid sockets */
39 if (pFds[i].fd == INVALID_SOCKET)
40 continue;
41
42 /**
43 * POLLIN Data other than high priority data may be read without blocking.
44 * This is equivalent to ( POLLRDNORM | POLLRDBAND ).
45 * POLLRDBAND Priority data may be read without blocking.
46 * POLLRDNORM Normal data may be read without blocking.
47 */
48 if (pollEvents & POLLIN)
49 eventMask |= FD_READ | FD_ACCEPT;
50
51 /**
52 * POLLOUT Normal data may be written without blocking. This is equivalent
53 * to POLLWRNORM.
54 * POLLWRNORM Normal data may be written without blocking.
55 */
56 if (pollEvents & POLLOUT)
57 eventMask |= FD_WRITE | FD_CONNECT;
58
59 /**
60 * This is "moral" equivalent to POLLHUP.
61 */
62 eventMask |= FD_CLOSE;
63 WSAEventSelect(pFds[i].fd, g_hNetworkEvent, eventMask);
64 }
65
66 DWORD index = WSAWaitForMultipleEvents(1,
67 &g_hNetworkEvent,
68 FALSE,
69 timeout == RT_INDEFINITE_WAIT ? WSA_INFINITE : timeout,
70 FALSE);
71 if (index != WSA_WAIT_EVENT_0)
72 {
73 if (index == WSA_WAIT_TIMEOUT)
74 return VERR_TIMEOUT;
75 }
76
77 int nready = 0;
78 for (unsigned int i = 0; i < nfds; ++i)
79 {
80 short revents = 0;
81 WSANETWORKEVENTS NetworkEvents;
82 int err;
83
84 if (pFds[i].fd == INVALID_SOCKET)
85 continue;
86
87 RT_ZERO(NetworkEvents);
88
89 err = WSAEnumNetworkEvents(pFds[i].fd,
90 g_hNetworkEvent,
91 &NetworkEvents);
92
93 if (err == SOCKET_ERROR)
94 {
95 if (WSAGetLastError() == WSAENOTSOCK)
96 {
97 pFds[i].revents = POLLNVAL;
98 ++nready;
99 }
100 continue;
101 }
102
103 /* deassociate socket with event */
104 WSAEventSelect(pFds[i].fd, g_hNetworkEvent, 0);
105
106#define WSA_TO_POLL(_wsaev, _pollev) \
107 do { \
108 if (NetworkEvents.lNetworkEvents & (_wsaev)) { \
109 revents |= (_pollev); \
110 if (NetworkEvents.iErrorCode[_wsaev##_BIT] != 0) { \
111 Log2(("sock %d: %s: %R[sockerr]\n", \
112 pFds[i].fd, #_wsaev, \
113 NetworkEvents.iErrorCode[_wsaev##_BIT])); \
114 revents |= POLLERR; \
115 } \
116 } \
117 } while (0)
118
119 WSA_TO_POLL(FD_READ, POLLIN);
120 WSA_TO_POLL(FD_ACCEPT, POLLIN);
121 WSA_TO_POLL(FD_WRITE, POLLOUT);
122 WSA_TO_POLL(FD_CONNECT, POLLOUT);
123 WSA_TO_POLL(FD_CLOSE, POLLHUP | (pFds[i].events & POLLIN));
124
125 Assert((revents & ~(pFds[i].events | POLLHUP | POLLERR)) == 0);
126
127 if (revents != 0)
128 {
129 pFds[i].revents = revents;
130 ++nready;
131 }
132 }
133 WSAResetEvent(g_hNetworkEvent);
134
135 if (pNready)
136 *pNready = nready;
137
138 return VINF_SUCCESS;
139}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette