aboutsummaryrefslogtreecommitdiff
path: root/slirp/slirp.c
diff options
context:
space:
mode:
Diffstat (limited to 'slirp/slirp.c')
-rw-r--r--slirp/slirp.c133
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)