size_t slirp_socket_can_recv(int addr_low_byte, int guest_port) { struct iovec iov[2]; struct socket *so; if (!link_up) return 0; so = slirp_find_ctl_socket(addr_low_byte, guest_port); if (!so || so->so_state & SS_NOFDREF) return 0; if (!CONN_CANFRCV(so) || so->so_snd.sb_cc >= (so->so_snd.sb_datalen/2)) return 0; return sopreprbuf(so, iov, NULL); }
int slirp_select_fill(int *pnfds, fd_set *readfds, fd_set *writefds, fd_set *xfds) { struct socket *so, *so_next; int nfds; int timeout, 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) || ((struct ipasfrag *)&ipq != (struct ipasfrag *)ipq.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 */ timeout = -1; /* * If a slowtimo is needed, set timeout to 5ms from the last * slow timeout. If a fast timeout is needed, set timeout within * 2ms of when it was requested. */ # define SLOW_TIMO 5 # define FAST_TIMO 2 if (do_slowtimo) { timeout = (SLOW_TIMO - (curtime - last_slowtimo)) * 1000; if (timeout < 0) timeout = 0; else if (timeout > (SLOW_TIMO * 1000)) timeout = SLOW_TIMO * 1000; /* Can only fasttimo if we also slowtimo */ if (time_fasttimo) { tmp_time = (FAST_TIMO - (curtime - time_fasttimo)) * 1000; if (tmp_time < 0) tmp_time = 0; /* Choose the smallest of the 2 */ if (tmp_time < timeout) timeout = tmp_time; } } *pnfds = nfds; /* * Adjust the timeout to make the minimum timeout * 2ms (XXX?) to lessen the CPU load */ if (timeout < (FAST_TIMO * 1000)) timeout = FAST_TIMO * 1000; return timeout; }
void slirp_select_fill(int *pnfds, fd_set *readfds, fd_set *writefds, fd_set *xfds) { struct socket *so, *so_next; struct timeval timeout; int nfds; int tmp_time; global_readfds = NULL; global_writefds = NULL; global_xfds = NULL; nfds = *pnfds; do_slowtimo = 0; if (link_up) { 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; if (time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK) time_fasttimo = curtime; if (so->so_state & SS_NOFDREF || so->s == -1) continue; if ((so->so_state & SS_PROXIFIED) != 0) continue; if (so->so_state & SS_FACCEPTCONN) { FD_SET(so->s, readfds); UPD_NFDS(so->s); continue; } if (so->so_state & SS_ISFCONNECTING) { FD_SET(so->s, writefds); UPD_NFDS(so->s); continue; } if (CONN_CANFSEND(so) && so->so_rcv.sb_cc) { FD_SET(so->s, writefds); UPD_NFDS(so->s); } 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); } } for (so = udb.so_next; so != &udb; so = so_next) { so_next = so->so_next; if ((so->so_state & SS_PROXIFIED) != 0) continue; if (so->so_expire) { if (so->so_expire <= curtime) { udp_detach(so); continue; } else do_slowtimo = 1; } if ((so->so_state & SS_ISFCONNECTED) && so->so_queued <= 4) { FD_SET(so->s, readfds); UPD_NFDS(so->s); } } } timeout.tv_sec = 0; timeout.tv_usec = -1; if (do_slowtimo) { 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; if (time_fasttimo) { tmp_time = (200 - (curtime - time_fasttimo)) * 1000; if (tmp_time < 0) tmp_time = 0; if (tmp_time < timeout.tv_usec) timeout.tv_usec = (u_int)tmp_time; } } proxy_manager_select_fill(&nfds, readfds, writefds, xfds); *pnfds = nfds; }
void slirp_select_fill(int *pnfds, fd_set *readfds, fd_set *writefds, fd_set *xfds) { struct socket *so, *so_next; 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; /* * don't register proxified socked connections here */ if ((so->so_state & SS_PROXIFIED) != 0) 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; if ((so->so_state & SS_PROXIFIED) != 0) continue; /* * 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; } } /* * now, the proxified sockets */ proxy_manager_select_fill(&nfds, readfds, writefds, xfds); *pnfds = nfds; }