diff options
Diffstat (limited to 'slirp/slirp.c')
-rw-r--r-- | slirp/slirp.c | 133 |
1 files changed, 79 insertions, 54 deletions
diff --git a/slirp/slirp.c b/slirp/slirp.c index 5d14e7f865..bd9b7cb644 100644 --- a/slirp/slirp.c +++ b/slirp/slirp.c @@ -39,9 +39,6 @@ static const uint8_t special_ethaddr[ETH_ALEN] = { static const uint8_t zero_ethaddr[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; -/* XXX: suppress those select globals */ -fd_set *global_readfds, *global_writefds, *global_xfds; - u_int curtime; static u_int time_fasttimo, last_slowtimo; static int do_slowtimo; @@ -261,7 +258,6 @@ void slirp_cleanup(Slirp *slirp) #define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED) #define CONN_CANFRCV(so) (((so)->so_state & (SS_FCANTRCVMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED) -#define UPD_NFDS(x) if (nfds < (x)) nfds = (x) void slirp_update_timeout(uint32_t *timeout) { @@ -270,23 +266,15 @@ void slirp_update_timeout(uint32_t *timeout) } } -void slirp_select_fill(int *pnfds, - fd_set *readfds, fd_set *writefds, fd_set *xfds) +void slirp_pollfds_fill(GArray *pollfds) { Slirp *slirp; struct socket *so, *so_next; - int nfds; if (QTAILQ_EMPTY(&slirp_instances)) { return; } - /* fail safe */ - global_readfds = NULL; - global_writefds = NULL; - global_xfds = NULL; - - nfds = *pnfds; /* * First, TCP sockets */ @@ -302,8 +290,12 @@ void slirp_select_fill(int *pnfds, for (so = slirp->tcb.so_next; so != &slirp->tcb; so = so_next) { + int events = 0; + so_next = so->so_next; + so->pollfds_idx = -1; + /* * See if we need a tcp_fasttimo */ @@ -323,8 +315,12 @@ void slirp_select_fill(int *pnfds, * Set for reading sockets which are accepting */ if (so->so_state & SS_FACCEPTCONN) { - FD_SET(so->s, readfds); - UPD_NFDS(so->s); + GPollFD pfd = { + .fd = so->s, + .events = G_IO_IN | G_IO_HUP | G_IO_ERR, + }; + so->pollfds_idx = pollfds->len; + g_array_append_val(pollfds, pfd); continue; } @@ -332,8 +328,12 @@ void slirp_select_fill(int *pnfds, * Set for writing sockets which are connecting */ if (so->so_state & SS_ISFCONNECTING) { - FD_SET(so->s, writefds); - UPD_NFDS(so->s); + GPollFD pfd = { + .fd = so->s, + .events = G_IO_OUT | G_IO_ERR, + }; + so->pollfds_idx = pollfds->len; + g_array_append_val(pollfds, pfd); continue; } @@ -342,8 +342,7 @@ void slirp_select_fill(int *pnfds, * we have something to send */ if (CONN_CANFSEND(so) && so->so_rcv.sb_cc) { - FD_SET(so->s, writefds); - UPD_NFDS(so->s); + events |= G_IO_OUT | G_IO_ERR; } /* @@ -352,9 +351,16 @@ void slirp_select_fill(int *pnfds, */ if (CONN_CANFRCV(so) && (so->so_snd.sb_cc < (so->so_snd.sb_datalen/2))) { - FD_SET(so->s, readfds); - FD_SET(so->s, xfds); - UPD_NFDS(so->s); + events |= G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_PRI; + } + + if (events) { + GPollFD pfd = { + .fd = so->s, + .events = events, + }; + so->pollfds_idx = pollfds->len; + g_array_append_val(pollfds, pfd); } } @@ -365,6 +371,8 @@ void slirp_select_fill(int *pnfds, so = so_next) { so_next = so->so_next; + so->pollfds_idx = -1; + /* * See if it's timed out */ @@ -388,8 +396,12 @@ void slirp_select_fill(int *pnfds, * (XXX <= 4 ?) */ if ((so->so_state & SS_ISFCONNECTED) && so->so_queued <= 4) { - FD_SET(so->s, readfds); - UPD_NFDS(so->s); + GPollFD pfd = { + .fd = so->s, + .events = G_IO_IN | G_IO_HUP | G_IO_ERR, + }; + so->pollfds_idx = pollfds->len; + g_array_append_val(pollfds, pfd); } } @@ -400,6 +412,8 @@ void slirp_select_fill(int *pnfds, so = so_next) { so_next = so->so_next; + so->pollfds_idx = -1; + /* * See if it's timed out */ @@ -413,17 +427,18 @@ void slirp_select_fill(int *pnfds, } if (so->so_state & SS_ISFCONNECTED) { - FD_SET(so->s, readfds); - UPD_NFDS(so->s); + GPollFD pfd = { + .fd = so->s, + .events = G_IO_IN | G_IO_HUP | G_IO_ERR, + }; + so->pollfds_idx = pollfds->len; + g_array_append_val(pollfds, pfd); } } } - - *pnfds = nfds; } -void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds, - int select_error) +void slirp_pollfds_poll(GArray *pollfds, int select_error) { Slirp *slirp; struct socket *so, *so_next; @@ -433,10 +448,6 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds, return; } - global_readfds = readfds; - global_writefds = writefds; - global_xfds = xfds; - curtime = qemu_get_clock_ms(rt_clock); QTAILQ_FOREACH(slirp, &slirp_instances, entry) { @@ -462,12 +473,16 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds, */ for (so = slirp->tcb.so_next; so != &slirp->tcb; so = so_next) { + int revents; + so_next = so->so_next; - /* - * FD_ISSET is meaningless on these sockets - * (and they can crash the program) - */ + revents = 0; + if (so->pollfds_idx != -1) { + revents = g_array_index(pollfds, GPollFD, + so->pollfds_idx).revents; + } + if (so->so_state & SS_NOFDREF || so->s == -1) { continue; } @@ -475,15 +490,15 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds, /* * Check for URG data * This will soread as well, so no need to - * test for readfds below if this succeeds + * test for G_IO_IN below if this succeeds */ - if (FD_ISSET(so->s, xfds)) { + if (revents & G_IO_PRI) { sorecvoob(so); } /* * Check sockets for reading */ - else if (FD_ISSET(so->s, readfds)) { + else if (revents & (G_IO_IN | G_IO_HUP | G_IO_ERR)) { /* * Check for incoming connections */ @@ -502,7 +517,8 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds, /* * Check sockets for writing */ - if (FD_ISSET(so->s, writefds)) { + if (!(so->so_state & SS_NOFDREF) && + (revents & (G_IO_OUT | G_IO_ERR))) { /* * Check for non-blocking, still-connecting sockets */ @@ -588,9 +604,18 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds, */ for (so = slirp->udb.so_next; so != &slirp->udb; so = so_next) { + int revents; + so_next = so->so_next; - if (so->s != -1 && FD_ISSET(so->s, readfds)) { + revents = 0; + if (so->pollfds_idx != -1) { + revents = g_array_index(pollfds, GPollFD, + so->pollfds_idx).revents; + } + + if (so->s != -1 && + (revents & (G_IO_IN | G_IO_HUP | G_IO_ERR))) { sorecvfrom(so); } } @@ -600,9 +625,18 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds, */ for (so = slirp->icmp.so_next; so != &slirp->icmp; so = so_next) { - so_next = so->so_next; + int revents; + + so_next = so->so_next; + + revents = 0; + if (so->pollfds_idx != -1) { + revents = g_array_index(pollfds, GPollFD, + so->pollfds_idx).revents; + } - if (so->s != -1 && FD_ISSET(so->s, readfds)) { + if (so->s != -1 && + (revents & (G_IO_IN | G_IO_HUP | G_IO_ERR))) { icmp_receive(so); } } @@ -610,15 +644,6 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds, if_start(slirp); } - - /* clear global file descriptor sets. - * these reside on the stack in vl.c - * so they're unusable if we're not in - * slirp_select_fill or slirp_select_poll. - */ - global_readfds = NULL; - global_writefds = NULL; - global_xfds = NULL; } static void arp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len) |