VirtualBox

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

Last change on this file since 62556 was 62481, checked in by vboxsync, 8 years ago

(C) 2016

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 4.8 KB
Line 
1/* $Id: RTWinPoll.cpp 62481 2016-07-22 18:30:21Z vboxsync $ */
2/** @file
3 * NAT Network - poll(2) implementation for winsock.
4 */
5
6/*
7 * Copyright (C) 2013-2016 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17#define LOG_GROUP LOG_GROUP_NAT_SERVICE
18
19#include <iprt/asm.h>
20#include <iprt/assert.h>
21#include <iprt/cdefs.h>
22#include <iprt/err.h>
23#include <iprt/string.h>
24
25#include <VBox/err.h>
26#include <VBox/log.h>
27
28#include <Winsock2.h>
29#include <Windows.h>
30#include "winpoll.h"
31
32static HANDLE g_hNetworkEvent;
33
34int
35RTWinPoll(struct pollfd *pFds, unsigned int nfds, int timeout, int *pNready)
36{
37 AssertPtrReturn(pFds, VERR_INVALID_PARAMETER);
38
39 if (g_hNetworkEvent == WSA_INVALID_EVENT)
40 {
41 g_hNetworkEvent = WSACreateEvent();
42 AssertReturn(g_hNetworkEvent != WSA_INVALID_EVENT, VERR_INTERNAL_ERROR);
43 }
44
45 for (unsigned int i = 0; i < nfds; ++i)
46 {
47 long eventMask = 0;
48 short pollEvents = pFds[i].events;
49
50 /* clean revents */
51 pFds[i].revents = 0;
52
53 /* ignore invalid sockets */
54 if (pFds[i].fd == INVALID_SOCKET)
55 continue;
56
57 /**
58 * POLLIN Data other than high priority data may be read without blocking.
59 * This is equivalent to ( POLLRDNORM | POLLRDBAND ).
60 * POLLRDBAND Priority data may be read without blocking.
61 * POLLRDNORM Normal data may be read without blocking.
62 */
63 if (pollEvents & POLLIN)
64 eventMask |= FD_READ | FD_ACCEPT;
65
66 /**
67 * POLLOUT Normal data may be written without blocking. This is equivalent
68 * to POLLWRNORM.
69 * POLLWRNORM Normal data may be written without blocking.
70 */
71 if (pollEvents & POLLOUT)
72 eventMask |= FD_WRITE | FD_CONNECT;
73
74 /**
75 * This is "moral" equivalent to POLLHUP.
76 */
77 eventMask |= FD_CLOSE;
78 WSAEventSelect(pFds[i].fd, g_hNetworkEvent, eventMask);
79 }
80
81 DWORD index = WSAWaitForMultipleEvents(1,
82 &g_hNetworkEvent,
83 FALSE,
84 timeout == RT_INDEFINITE_WAIT ? WSA_INFINITE : timeout,
85 FALSE);
86 if (index != WSA_WAIT_EVENT_0)
87 {
88 if (index == WSA_WAIT_TIMEOUT)
89 return VERR_TIMEOUT;
90 }
91
92 int nready = 0;
93 for (unsigned int i = 0; i < nfds; ++i)
94 {
95 short revents = 0;
96 WSANETWORKEVENTS NetworkEvents;
97 int err;
98
99 if (pFds[i].fd == INVALID_SOCKET)
100 continue;
101
102 RT_ZERO(NetworkEvents);
103
104 err = WSAEnumNetworkEvents(pFds[i].fd,
105 g_hNetworkEvent,
106 &NetworkEvents);
107
108 if (err == SOCKET_ERROR)
109 {
110 if (WSAGetLastError() == WSAENOTSOCK)
111 {
112 pFds[i].revents = POLLNVAL;
113 ++nready;
114 }
115 continue;
116 }
117
118 /* deassociate socket with event */
119 WSAEventSelect(pFds[i].fd, g_hNetworkEvent, 0);
120
121#define WSA_TO_POLL(_wsaev, _pollev) \
122 do { \
123 if (NetworkEvents.lNetworkEvents & (_wsaev)) { \
124 revents |= (_pollev); \
125 if (NetworkEvents.iErrorCode[_wsaev##_BIT] != 0) { \
126 Log2(("sock %d: %s: %R[sockerr]\n", \
127 pFds[i].fd, #_wsaev, \
128 NetworkEvents.iErrorCode[_wsaev##_BIT])); \
129 revents |= POLLERR; \
130 } \
131 } \
132 } while (0)
133
134 WSA_TO_POLL(FD_READ, POLLIN);
135 WSA_TO_POLL(FD_ACCEPT, POLLIN);
136 WSA_TO_POLL(FD_WRITE, POLLOUT);
137 WSA_TO_POLL(FD_CONNECT, POLLOUT);
138 WSA_TO_POLL(FD_CLOSE, POLLHUP | (pFds[i].events & POLLIN));
139
140 Assert((revents & ~(pFds[i].events | POLLHUP | POLLERR)) == 0);
141
142 if (revents != 0)
143 {
144 pFds[i].revents = revents;
145 ++nready;
146 }
147 }
148 WSAResetEvent(g_hNetworkEvent);
149
150 if (pNready)
151 *pNready = nready;
152
153 return VINF_SUCCESS;
154}
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