void tcp_tick() { /* guard against re-entry */ if (in_tcptick) return; in_tcptick++; LOCK_NET_RESOURCE(NET_RESID); if (cticks >= nextslow) /* time to do it again */ { tcp_slowtimo(); /* call routine in BSD tcp_timr.c */ #ifdef CSUM_DEMO nextslow = cticks + (TPS/5); /* another 200 ms */ #else nextslow = cticks + (TPS/2); /* another 500 ms */ #endif } #ifdef DO_DELAY_ACKS tcp_fasttimo(); #endif /* DO_DELAY_ACKS */ UNLOCK_NET_RESOURCE(NET_RESID); in_tcptick--; }
void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds) { struct socket *so, *so_next; int ret; global_readfds = readfds; global_writefds = writefds; global_xfds = xfds; /* Update time */ updtime(); /* * See if anything has timed out */ if (link_up) { if (time_fasttimo && ((curtime - time_fasttimo) >= FAST_TIMO)) { tcp_fasttimo(); time_fasttimo = 0; } if (do_slowtimo && ((curtime - last_slowtimo) >= SLOW_TIMO)) { ip_slowtimo(); tcp_slowtimo(); last_slowtimo = curtime; } } /* * Check sockets */ if (link_up) { /* * Check TCP sockets */ for (so = tcb.so_next; so != &tcb; so = so_next) { so_next = so->so_next; /* * FD_ISSET is meaningless on these sockets * (and they can crash the program) */ if (so->so_state & SS_NOFDREF || so->s == -1) continue; /* * Check for URG data * This will soread as well, so no need to * test for readfds below if this succeeds */ if (FD_ISSET(so->s, xfds)) sorecvoob(so); /* * Check sockets for reading */ else if (FD_ISSET(so->s, readfds)) { /* * Check for incoming connections */ if (so->so_state & SS_FACCEPTCONN) { tcp_connect(so); continue; } /* else */ ret = soread(so); /* Output it if we read something */ if (ret > 0) tcp_output(sototcpcb(so)); } /* * Check sockets for writing */ if (FD_ISSET(so->s, writefds)) { /* * Check for non-blocking, still-connecting sockets */ if (so->so_state & SS_ISFCONNECTING) { /* Connected */ so->so_state &= ~SS_ISFCONNECTING; ret = send(so->s, &ret, 0, 0); if (ret < 0) { /* XXXXX Must fix, zero bytes is a NOP */ if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS || errno == ENOTCONN) continue; /* else failed */ so->so_state = SS_NOFDREF; } /* else so->so_state &= ~SS_ISFCONNECTING; */ /* * Continue tcp_input */ tcp_input((struct mbuf *)NULL, sizeof(struct ip), so); /* continue; */ } else ret = sowrite(so); /* * XXXXX If we wrote something (a lot), there * could be a need for a window update. * In the worst case, the remote will send * a window probe to get things going again */ } /* * Probe a still-connecting, non-blocking socket * to check if it's still alive */ #ifdef PROBE_CONN if (so->so_state & SS_ISFCONNECTING) { ret = recv(so->s, (char *)&ret, 0,0); if (ret < 0) { /* XXX */ if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS || errno == ENOTCONN) continue; /* Still connecting, continue */ /* else failed */ so->so_state = SS_NOFDREF; /* tcp_input will take care of it */ } else { ret = send(so->s, &ret, 0,0); if (ret < 0) { /* XXX */ if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS || errno == ENOTCONN) continue; /* else failed */ so->so_state = SS_NOFDREF; } else so->so_state &= ~SS_ISFCONNECTING; } tcp_input((struct mbuf *)NULL, sizeof(struct ip),so); } /* SS_ISFCONNECTING */ #endif } /* * Now UDP sockets. * Incoming packets are sent straight away, they're not buffered. * Incoming UDP data isn't buffered either. */ for (so = udb.so_next; so != &udb; so = so_next) { so_next = so->so_next; if (so->s != -1 && FD_ISSET(so->s, readfds)) { sorecvfrom(so); } } } /* * See if we can start outputting */ if (if_queued && link_up) if_start(); /* 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; }
void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds) { struct socket *so, *so_next; int ret; global_readfds = readfds; global_writefds = writefds; global_xfds = xfds; updtime(); if (link_up) { if (time_fasttimo && ((curtime - time_fasttimo) >= 2)) { tcp_fasttimo(); time_fasttimo = 0; } if (do_slowtimo && ((curtime - last_slowtimo) >= 499)) { ip_slowtimo(); tcp_slowtimo(); last_slowtimo = curtime; } } if (link_up) { for (so = tcb.so_next; so != &tcb; so = so_next) { so_next = so->so_next; if (so->so_state & SS_NOFDREF || so->s == -1) continue; if ((so->so_state & SS_PROXIFIED) != 0) continue; if (FD_ISSET(so->s, xfds)) sorecvoob(so); else if (FD_ISSET(so->s, readfds)) { if (so->so_state & SS_FACCEPTCONN) { tcp_connect(so); continue; } ret = soread(so); if (ret > 0) tcp_output(sototcpcb(so)); } if (FD_ISSET(so->s, writefds)) { if (so->so_state & SS_ISFCONNECTING) { so->so_state &= ~SS_ISFCONNECTING; ret = socket_send(so->s, (const void *)&ret, 0); if (ret < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS || errno == ENOTCONN) continue; so->so_state = SS_NOFDREF; } tcp_input((struct mbuf *)NULL, sizeof(struct ip), so); } else ret = sowrite(so); } #ifdef PROBE_CONN if (so->so_state & SS_ISFCONNECTING) { ret = socket_recv(so->s, (char *)&ret, 0); if (ret < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS || errno == ENOTCONN) continue; so->so_state = SS_NOFDREF; } else { ret = socket_send(so->s, &ret, 0); if (ret < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS || errno == ENOTCONN) continue; so->so_state = SS_NOFDREF; } else so->so_state &= ~SS_ISFCONNECTING; } tcp_input((struct mbuf *)NULL, sizeof(struct ip),so); } #endif } 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->s != -1 && FD_ISSET(so->s, readfds)) { sorecvfrom(so); } } } proxy_manager_poll(readfds, writefds, xfds); if (if_queued && link_up) if_start(); global_readfds = NULL; global_writefds = NULL; global_xfds = NULL; }