VirtualBox

source: vbox/trunk/src/VBox/Devices/Network/RTWinPollLibslirp.cpp@ 106129

Last change on this file since 106129 was 106129, checked in by vboxsync, 2 months ago

Devices/Network: Fix windows slow packet throughput by kicking NAT thread more regularly. bugref:10268

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