diff options
-rw-r--r-- | libslirp.h | 6 | ||||
-rw-r--r-- | main.h | 1 | ||||
-rw-r--r-- | slirp.c | 133 | ||||
-rw-r--r-- | socket.c | 9 | ||||
-rw-r--r-- | socket.h | 2 |
5 files changed, 82 insertions, 69 deletions
@@ -17,11 +17,9 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork, void slirp_cleanup(Slirp *slirp); 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); -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); void slirp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len); @@ -31,7 +31,6 @@ extern int ctty_closed; extern char *slirp_tty; extern char *exec_shell; extern u_int curtime; -extern fd_set *global_readfds, *global_writefds, *global_xfds; extern struct in_addr loopback_addr; extern unsigned long loopback_mask; extern char *username; @@ -38,9 +38,6 @@ static const uint8_t special_ethaddr[ETH_ALEN] = { 0x52, 0x55, 0x00, 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; @@ -262,9 +259,6 @@ void slirp_cleanup(Slirp *slirp) (((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) { @@ -273,23 +267,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 */ @@ -304,8 +290,12 @@ void slirp_select_fill(int *pnfds, fd_set *readfds, fd_set *writefds, (&slirp->ipq.ip_link != slirp->ipq.ip_link.next)); 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 */ @@ -325,8 +315,12 @@ void slirp_select_fill(int *pnfds, fd_set *readfds, fd_set *writefds, * 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; } @@ -334,8 +328,12 @@ void slirp_select_fill(int *pnfds, fd_set *readfds, fd_set *writefds, * 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; } @@ -344,8 +342,7 @@ void slirp_select_fill(int *pnfds, fd_set *readfds, fd_set *writefds, * 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; } /* @@ -354,9 +351,16 @@ void slirp_select_fill(int *pnfds, fd_set *readfds, fd_set *writefds, */ 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); } } @@ -366,6 +370,8 @@ void slirp_select_fill(int *pnfds, fd_set *readfds, fd_set *writefds, for (so = slirp->udb.so_next; so != &slirp->udb; so = so_next) { so_next = so->so_next; + so->pollfds_idx = -1; + /* * See if it's timed out */ @@ -389,8 +395,12 @@ void slirp_select_fill(int *pnfds, fd_set *readfds, fd_set *writefds, * (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 +410,8 @@ void slirp_select_fill(int *pnfds, fd_set *readfds, fd_set *writefds, for (so = slirp->icmp.so_next; so != &slirp->icmp; so = so_next) { so_next = so->so_next; + so->pollfds_idx = -1; + /* * See if it's timed out */ @@ -413,17 +425,18 @@ void slirp_select_fill(int *pnfds, fd_set *readfds, fd_set *writefds, } 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 +446,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) { @@ -461,12 +470,16 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds, * Check TCP sockets */ 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; } @@ -474,15 +487,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 */ @@ -501,7 +514,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 */ @@ -585,9 +599,18 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds, * Incoming UDP data isn't buffered either. */ 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); } } @@ -596,9 +619,18 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds, * Check incoming ICMP relies. */ for (so = slirp->icmp.so_next; so != &slirp->icmp; 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))) { icmp_receive(so); } } @@ -606,15 +638,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) @@ -685,9 +685,6 @@ static void sofcantrcvmore(struct socket *so) { if ((so->so_state & SS_NOFDREF) == 0) { shutdown(so->s, 0); - if (global_writefds) { - FD_CLR(so->s, global_writefds); - } } so->so_state &= ~(SS_ISFCONNECTING); if (so->so_state & SS_FCANTSENDMORE) { @@ -702,12 +699,6 @@ static void sofcantsendmore(struct socket *so) { if ((so->so_state & SS_NOFDREF) == 0) { shutdown(so->s, 1); /* send FIN to fhost */ - if (global_readfds) { - FD_CLR(so->s, global_readfds); - } - if (global_xfds) { - FD_CLR(so->s, global_xfds); - } } so->so_state &= ~(SS_ISFCONNECTING); if (so->so_state & SS_FCANTRCVMORE) { @@ -20,6 +20,8 @@ struct socket { int s; /* The actual socket */ + int pollfds_idx; /* GPollFD GArray index */ + Slirp *slirp; /* managing slirp instance */ /* XXX union these with not-yet-used sbuf params */ |