- struct timeval timeout;
- int nfds;
- int tmp_time;
-
- /* fail safe */
- global_readfds = NULL;
- global_writefds = NULL;
- global_xfds = NULL;
-
- nfds = *pnfds;
- /*
- * First, TCP sockets
- */
- do_slowtimo = 0;
- if (link_up) {
- /*
- * *_slowtimo needs calling if there are IP fragments
- * in the fragment queue, or there are TCP connections active
- */
- do_slowtimo = ((tcb.so_next != &tcb) ||
- (&ipq.ip_link != ipq.ip_link.next));
-
- for (so = tcb.so_next; so != &tcb; so = so_next) {
- so_next = so->so_next;
-
- /*
- * See if we need a tcp_fasttimo
- */
- if (time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK)
- time_fasttimo = curtime; /* Flag when we want a fasttimo */
-
- /*
- * NOFDREF can include still connecting to local-host,
- * newly socreated() sockets etc. Don't want to select these.
- */
- if (so->so_state & SS_NOFDREF || so->s == -1)
- continue;
-
- /*
- * Set for reading sockets which are accepting
- */
- if (so->so_state & SS_FACCEPTCONN) {
- FD_SET(so->s, readfds);
- UPD_NFDS(so->s);
- continue;
- }
-
- /*
- * Set for writing sockets which are connecting
- */
- if (so->so_state & SS_ISFCONNECTING) {
- FD_SET(so->s, writefds);
- UPD_NFDS(so->s);
- continue;
- }
-
- /*
- * Set for writing if we are connected, can send more, and
- * we have something to send
- */
- if (CONN_CANFSEND(so) && so->so_rcv.sb_cc) {
- FD_SET(so->s, writefds);
- UPD_NFDS(so->s);
- }
-
- /*
- * Set for reading (and urgent data) if we are connected, can
- * receive more, and we have room for it XXX /2 ?
- */
- 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);
- }
- }
-
- /*
- * UDP sockets
- */
- for (so = udb.so_next; so != &udb; so = so_next) {
- so_next = so->so_next;
-
- /*
- * See if it's timed out
- */
- if (so->so_expire) {
- if (so->so_expire <= curtime) {
- udp_detach(so);
- continue;
- } else
- do_slowtimo = 1; /* Let socket expire */
- }
-
- /*
- * When UDP packets are received from over the
- * link, they're sendto()'d straight away, so
- * no need for setting for writing
- * Limit the number of packets queued by this session
- * to 4. Note that even though we try and limit this
- * to 4 packets, the session could have more queued
- * if the packets needed to be fragmented
- * (XXX <= 4 ?)
- */
- if ((so->so_state & SS_ISFCONNECTED) && so->so_queued <= 4) {
- FD_SET(so->s, readfds);
- UPD_NFDS(so->s);
- }
- }
- }
-
- /*
- * Setup timeout to use minimum CPU usage, especially when idle
- */
-
- /*
- * First, see the timeout needed by *timo
- */
- timeout.tv_sec = 0;
- timeout.tv_usec = -1;
- /*
- * If a slowtimo is needed, set timeout to 500ms from the last
- * slow timeout. If a fast timeout is needed, set timeout within
- * 200ms of when it was requested.
- */
- if (do_slowtimo) {
- /* XXX + 10000 because some select()'s aren't that accurate */
- timeout.tv_usec = ((500 - (curtime - last_slowtimo)) * 1000) + 10000;
- if (timeout.tv_usec < 0)
- timeout.tv_usec = 0;
- else if (timeout.tv_usec > 510000)
- timeout.tv_usec = 510000;
-
- /* Can only fasttimo if we also slowtimo */
- if (time_fasttimo) {
- tmp_time = (200 - (curtime - time_fasttimo)) * 1000;
- if (tmp_time < 0)
- tmp_time = 0;
-
- /* Choose the smallest of the 2 */
- if (tmp_time < timeout.tv_usec)
- timeout.tv_usec = (u_int)tmp_time;
- }
- }
- *pnfds = nfds;
+
+ if (QTAILQ_EMPTY(&slirp_instances)) {
+ return;
+ }
+
+ /*
+ * First, TCP sockets
+ */
+ do_slowtimo = 0;
+
+ QTAILQ_FOREACH(slirp, &slirp_instances, entry) {
+ /*
+ * *_slowtimo needs calling if there are IP fragments
+ * in the fragment queue, or there are TCP connections active
+ */
+ do_slowtimo |= ((slirp->tcb.so_next != &slirp->tcb) ||
+ (&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
+ */
+ if (time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK) {
+ time_fasttimo = curtime; /* Flag when we want a fasttimo */
+ }
+
+ /*
+ * NOFDREF can include still connecting to local-host,
+ * newly socreated() sockets etc. Don't want to select these.
+ */
+ if (so->so_state & SS_NOFDREF || so->s == -1) {
+ continue;
+ }
+
+ /*
+ * Set for reading sockets which are accepting
+ */
+ if (so->so_state & SS_FACCEPTCONN) {
+ 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;
+ }
+
+ /*
+ * Set for writing sockets which are connecting
+ */
+ if (so->so_state & SS_ISFCONNECTING) {
+ GPollFD pfd = {
+ .fd = so->s,
+ .events = G_IO_OUT | G_IO_ERR,
+ };
+ so->pollfds_idx = pollfds->len;
+ g_array_append_val(pollfds, pfd);
+ continue;
+ }
+
+ /*
+ * Set for writing if we are connected, can send more, and
+ * we have something to send
+ */
+ if (CONN_CANFSEND(so) && so->so_rcv.sb_cc) {
+ events |= G_IO_OUT | G_IO_ERR;
+ }
+
+ /*
+ * Set for reading (and urgent data) if we are connected, can
+ * receive more, and we have room for it XXX /2 ?
+ */
+ if (CONN_CANFRCV(so) &&
+ (so->so_snd.sb_cc < (so->so_snd.sb_datalen/2))) {
+ 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);
+ }
+ }
+
+ /*
+ * UDP sockets
+ */
+ 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
+ */
+ if (so->so_expire) {
+ if (so->so_expire <= curtime) {
+ udp_detach(so);
+ continue;
+ } else {
+ do_slowtimo = 1; /* Let socket expire */
+ }
+ }
+
+ /*
+ * When UDP packets are received from over the
+ * link, they're sendto()'d straight away, so
+ * no need for setting for writing
+ * Limit the number of packets queued by this session
+ * to 4. Note that even though we try and limit this
+ * to 4 packets, the session could have more queued
+ * if the packets needed to be fragmented
+ * (XXX <= 4 ?)
+ */
+ if ((so->so_state & SS_ISFCONNECTED) && so->so_queued <= 4) {
+ 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);
+ }
+ }
+
+ /*
+ * ICMP sockets
+ */
+ 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
+ */
+ if (so->so_expire) {
+ if (so->so_expire <= curtime) {
+ icmp_detach(so);
+ continue;
+ } else {
+ do_slowtimo = 1; /* Let socket expire */
+ }
+ }
+
+ if (so->so_state & SS_ISFCONNECTED) {
+ 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);
+ }
+ }
+ }