Changeset 51674 in vbox
- Timestamp:
- Jun 19, 2014 9:01:20 PM (10 years ago)
- File:
-
- 1 edited
-
trunk/src/VBox/NetworkServices/NAT/pxtcp.c (modified) (11 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/NetworkServices/NAT/pxtcp.c
r51608 r51674 43 43 #include "lwip/icmp6.h" 44 44 45 /* NetBSD doesn't report POLLHUP for TCP sockets */ 46 #ifdef __NetBSD__ 47 # define HAVE_TCP_POLLHUP 0 45 /* 46 * Different OSes have different quirks in reporting POLLHUP for TCP 47 * sockets. 48 * 49 * Using shutdown(2) "how" values here would be more readable, but 50 * since SHUT_RD is 0, we can't use 0 for "none", unfortunately. 51 */ 52 #if defined(RT_OS_NETBSD) 53 # define HAVE_TCP_POLLHUP 0 /* not reported */ 54 #elif defined(RT_OS_DARWIN) 55 # define HAVE_TCP_POLLHUP POLLIN /* reported when remote closes */ 48 56 #else 49 # define HAVE_TCP_POLLHUP 157 # define HAVE_TCP_POLLHUP (POLLIN|POLLOUT) /* reported when both directions are closed */ 50 58 #endif 51 59 … … 172 180 * inbuf::buf. We defer delete until all data are acked to 173 181 * pxtcp_pcb_sent(). 174 *175 * It's also implied by inbound_pull. It probably means that176 * "deferred" is not a very fortunate name.177 182 */ 178 183 int deferred_delete; … … 213 218 static int pxtcp_pmgr_chan_pollout(struct pollmgr_handler *, SOCKET, int); 214 219 static int pxtcp_pmgr_chan_pollin(struct pollmgr_handler *, SOCKET, int); 215 #if ! HAVE_TCP_POLLHUP220 #if !(HAVE_TCP_POLLHUP & POLLOUT) 216 221 static int pxtcp_pmgr_chan_del(struct pollmgr_handler *, SOCKET, int); 217 222 #endif … … 273 278 static struct pollmgr_handler pxtcp_pmgr_chan_pollout_hdl; 274 279 static struct pollmgr_handler pxtcp_pmgr_chan_pollin_hdl; 275 #if ! HAVE_TCP_POLLHUP280 #if !(HAVE_TCP_POLLHUP & POLLOUT) 276 281 static struct pollmgr_handler pxtcp_pmgr_chan_del_hdl; 277 282 #endif … … 299 304 CHANNEL(POLLMGR_CHAN_PXTCP_POLLIN, pxtcp_pmgr_chan_pollin); 300 305 CHANNEL(POLLMGR_CHAN_PXTCP_POLLOUT, pxtcp_pmgr_chan_pollout); 301 #if ! HAVE_TCP_POLLHUP306 #if !(HAVE_TCP_POLLHUP & POLLOUT) 302 307 CHANNEL(POLLMGR_CHAN_PXTCP_DEL, pxtcp_pmgr_chan_del); 303 308 #endif … … 487 492 488 493 489 #if ! HAVE_TCP_POLLHUP494 #if !(HAVE_TCP_POLLHUP & POLLOUT) 490 495 /** 491 496 * POLLMGR_CHAN_PXTCP_DEL handler. … … 518 523 return POLLIN; 519 524 } 520 #endif /* ! HAVE_TCP_POLLHUP*/525 #endif /* !(HAVE_TCP_POLLHUP & POLLOUT) */ 521 526 522 527 … … 1373 1378 1374 1379 1375 /* 1376 * NB: set the flag first, since shutdown() will trigger POLLHUP 1377 * if inbound is already closed, and poll manager asserts 1378 * outbound_close_done (may be it should not?). 1379 */ 1380 /* set the flag first, since shutdown() may trigger POLLHUP */ 1380 1381 pxtcp->outbound_close_done = 1; 1381 1382 shutdown(pxtcp->sock, SHUT_WR); /* half-close the socket */ 1382 1383 1383 #if ! HAVE_TCP_POLLHUP1384 /* 1385 * On NetBSD POLLHUP is not reported for TCP sockets, so we need1386 * to nudge poll manager manually.1384 #if !(HAVE_TCP_POLLHUP & POLLOUT) 1385 /* 1386 * We need to nudge poll manager manually, since OS will not 1387 * report POLLHUP. 1387 1388 */ 1388 1389 if (pxtcp->inbound_close) { … … 1682 1683 #else 1683 1684 if (revents & POLLHUP) { 1685 #if HAVE_TCP_POLLHUP == POLLIN 1684 1686 /* 1685 * Linux and Darwin seems to report POLLHUP when both 1686 * directions are shut down. And they do report POLLHUP even 1687 * when there's unread data (which they aslo report as POLLIN 1688 * along with that POLLHUP). 1689 * 1690 * FreeBSD (from source inspection) seems to follow Linux, 1691 * reporting POLLHUP when both directions are shut down, but 1692 * POLLHUP is always accompanied with POLLIN. 1693 * 1694 * NetBSD never reports POLLHUP for sockets. 1695 * 1696 * --- 1697 * 1698 * If external half-closes first, we don't get POLLHUP, we 1699 * recv 0 bytes from the socket as EOF indicator, stop polling 1700 * for POLLIN and poll with events == 0 (with occasional 1701 * one-shot POLLOUT). When guest eventually closes, we get 1702 * POLLHUP. 1703 * 1704 * If guest half-closes first things are more tricky. As soon 1705 * as host sees the FIN from external it will spam POLLHUP, 1706 * even when there's unread data. The problem is that we 1707 * might have stopped polling for POLLIN because the ring 1708 * buffer is full or we were polling POLLIN but can't read all 1709 * of the data becuase buffer doesn't have enough space. 1710 * Either way, there's unread data but we can't keep polling 1711 * the socket. 1687 * Remote closed inbound. 1712 1688 */ 1713 DPRINTF(("sock %d: HUP\n", fd));1714 LWIP_ASSERT1(pxtcp->outbound_close_done);1715 1716 if (pxtcp->inbound_close) {1717 /* there's no unread data, we are done */1718 return pxtcp_schedule_delete(pxtcp);1719 }1720 else{1721 /* DPRINTF */ {1722 #ifndef RT_OS_WINDOWS 1723 int unread;1724 #else 1725 u_long unread;1689 if (!pxtcp->outbound_close_done) { 1690 /* 1691 * We might still need to poll for POLLOUT, but we can not 1692 * poll for POLLIN anymore (even if not all data are read) 1693 * because we will be spammed by POLLHUP. 1694 */ 1695 pxtcp->events &= ~POLLIN; 1696 if (!pxtcp->inbound_close) { 1697 /* the rest of the input has to be pulled */ 1698 proxy_lwip_post(&pxtcp->msg_inpull); 1699 } 1700 } 1701 else 1726 1702 #endif 1727 status = ioctlsocket(fd, FIONREAD, &unread); 1728 if (status == SOCKET_ERROR) { 1729 DPRINTF2(("sock %d: FIONREAD: %R[sockerr]\n", 1730 fd, SOCKERRNO())); 1731 } 1732 else { 1733 DPRINTF2(("sock %d: %d UNREAD bytes\n", fd, unread)); 1734 } 1703 /* 1704 * Both directions are closed. 1705 */ 1706 { 1707 DPRINTF(("sock %d: HUP\n", fd)); 1708 LWIP_ASSERT1(pxtcp->outbound_close_done); 1709 1710 if (pxtcp->inbound_close) { 1711 /* there's no unread data, we are done */ 1712 return pxtcp_schedule_delete(pxtcp); 1735 1713 } 1736 1737 /* 1738 * We cannot just set a flag here and let pxtcp_pcb_sent() 1739 * notice and start pulling, because if we are preempted 1740 * before setting the flag and all data in inbuf is ACKed 1741 * there will be no more calls to pxtcp_pcb_sent() to 1742 * notice the flag. 1743 * 1744 * We cannot set a flag and then send a message to make 1745 * sure it noticed, because if it has and it has read all 1746 * data while the message is in transit it will delete 1747 * pxtcp. 1748 * 1749 * In a sense this message is like msg_delete (except we 1750 * ask to pull some data first). 1751 */ 1752 proxy_lwip_post(&pxtcp->msg_inpull); 1753 pxtcp->pmhdl.slot = -1; 1754 return -1; 1755 } 1756 /* NOTREACHED */ 1757 } /* POLLHUP */ 1714 else { 1715 /* pull the rest of the input first (deferred_delete) */ 1716 pxtcp->pmhdl.slot = -1; 1717 proxy_lwip_post(&pxtcp->msg_inpull); 1718 return -1; 1719 } 1720 /* NOTREACHED */ 1721 } 1722 1723 } 1758 1724 #endif /* HAVE_TCP_POLLHUP */ 1759 1725 … … 2227 2193 if (/* __predict_false */ len == 0) { 2228 2194 /* we are notified to start pulling */ 2229 LWIP_ASSERT1(pxtcp->outbound_close_done);2230 2195 LWIP_ASSERT1(!pxtcp->inbound_close); 2231 2196 LWIP_ASSERT1(pxtcp->inbound_pull); … … 2343 2308 } 2344 2309 2345 DPRINTF(("%s: pxtcp %p: pcb %p\n",2346 __func__, (void *)pxtcp, (void *)pxtcp->pcb));2347 2310 pxtcp->inbound_pull = 1; 2348 pxtcp->deferred_delete = 1; 2311 if (pxtcp->outbound_close_done) { 2312 DPRINTF(("%s: pxtcp %p: pcb %p (deferred delete)\n", 2313 __func__, (void *)pxtcp, (void *)pxtcp->pcb)); 2314 pxtcp->deferred_delete = 1; 2315 } 2316 else { 2317 DPRINTF(("%s: pxtcp %p: pcb %p\n", 2318 __func__, (void *)pxtcp, (void *)pxtcp->pcb)); 2319 } 2320 2349 2321 pxtcp_pcb_sent(pxtcp, pxtcp->pcb, 0); 2350 2322 }
Note:
See TracChangeset
for help on using the changeset viewer.

