static void ns_mgr_handle_connection(struct ns_connection *nc, int fd_flags, time_t now) { DBG(("%p fd=%d fd_flags=%d nc_flags=%lu rmbl=%d smbl=%d", nc, nc->sock, fd_flags, nc->flags, (int) nc->recv_mbuf.len, (int) nc->send_mbuf.len)); if (fd_flags != 0) nc->last_io_time = now; if (nc->flags & NSF_CONNECTING) { if (fd_flags != 0) { ns_read_from_socket(nc); } return; } if (nc->flags & NSF_LISTENING) { /* * We're not looping here, and accepting just one connection at * a time. The reason is that eCos does not respect non-blocking * flag on a listening socket and hangs in a loop. */ if (fd_flags & _NSF_FD_CAN_READ) accept_conn(nc); return; } if (fd_flags & _NSF_FD_CAN_READ) { if (nc->flags & NSF_UDP) { ns_handle_udp(nc); } else { ns_read_from_socket(nc); } if (nc->flags & NSF_CLOSE_IMMEDIATELY) return; } if ((fd_flags & _NSF_FD_CAN_WRITE) && !(nc->flags & NSF_DONT_SEND) && !(nc->flags & NSF_UDP)) { /* Writes to UDP sockets are not buffered. */ ns_write_to_socket(nc); } if (!(fd_flags & (_NSF_FD_CAN_READ | _NSF_FD_CAN_WRITE))) { ns_call(nc, NS_POLL, &now); } DBG(("%p after fd=%d nc_flags=%lu rmbl=%d smbl=%d", nc, nc->sock, nc->flags, (int) nc->recv_mbuf.len, (int) nc->send_mbuf.len)); }
/* * This function performs the actual IO, and must be called in a loop * (an event loop). Returns the current timestamp. */ time_t ns_mgr_poll(struct ns_mgr *mgr, int milli) { struct ns_connection *nc, *tmp; struct timeval tv; fd_set read_set, write_set, err_set; sock_t max_fd = INVALID_SOCKET; time_t current_time = time(NULL); FD_ZERO(&read_set); FD_ZERO(&write_set); FD_ZERO(&err_set); ns_add_to_set(mgr->ctl[1], &read_set, &max_fd); for (nc = mgr->active_connections; nc != NULL; nc = tmp) { tmp = nc->next; if (!(nc->flags & (NSF_LISTENING | NSF_CONNECTING))) { ns_call(nc, NS_POLL, ¤t_time); } /* * NS_POLL handler could have signaled us to close the connection * by setting NSF_CLOSE_IMMEDIATELY flag. In this case, we don't want to * trigger any other events on that connection, but close it right away. */ if (nc->flags & NSF_CLOSE_IMMEDIATELY) { /* NOTE(lsm): this call removes nc from the mgr->active_connections */ ns_close_conn(nc); continue; } if (!(nc->flags & NSF_WANT_WRITE)) { /*DBG(("%p read_set", nc)); */ ns_add_to_set(nc->sock, &read_set, &max_fd); } if (((nc->flags & NSF_CONNECTING) && !(nc->flags & NSF_WANT_READ)) || (nc->send_iobuf.len > 0 && !(nc->flags & NSF_CONNECTING) && !(nc->flags & NSF_BUFFER_BUT_DONT_SEND))) { /*DBG(("%p write_set", nc)); */ ns_add_to_set(nc->sock, &write_set, &max_fd); ns_add_to_set(nc->sock, &err_set, &max_fd); } } tv.tv_sec = milli / 1000; tv.tv_usec = (milli % 1000) * 1000; if (select((int) max_fd + 1, &read_set, &write_set, &err_set, &tv) > 0) { /* select() might have been waiting for a long time, reset current_time * now to prevent last_io_time being set to the past. */ current_time = time(NULL); /* Read wakeup messages */ if (mgr->ctl[1] != INVALID_SOCKET && FD_ISSET(mgr->ctl[1], &read_set)) { struct ctl_msg ctl_msg; int len = (int) recv(mgr->ctl[1], (char *) &ctl_msg, sizeof(ctl_msg), 0); send(mgr->ctl[1], ctl_msg.message, 1, 0); if (len >= (int) sizeof(ctl_msg.callback) && ctl_msg.callback != NULL) { struct ns_connection *c; for (c = ns_next(mgr, NULL); c != NULL; c = ns_next(mgr, c)) { ctl_msg.callback(c, NS_POLL, ctl_msg.message); } } } for (nc = mgr->active_connections; nc != NULL; nc = tmp) { tmp = nc->next; /* Windows reports failed connect() requests in err_set */ if (FD_ISSET(nc->sock, &err_set) && (nc->flags & NSF_CONNECTING)) { nc->last_io_time = current_time; ns_read_from_socket(nc); } if (FD_ISSET(nc->sock, &read_set)) { nc->last_io_time = current_time; if (nc->flags & NSF_LISTENING) { if (nc->flags & NSF_UDP) { ns_handle_udp(nc); } else { /* We're not looping here, and accepting just one connection at * a time. The reason is that eCos does not respect non-blocking * flag on a listening socket and hangs in a loop. */ accept_conn(nc); } } else { ns_read_from_socket(nc); } } if (FD_ISSET(nc->sock, &write_set)) { nc->last_io_time = current_time; if (nc->flags & NSF_CONNECTING) { ns_read_from_socket(nc); } else if (!(nc->flags & NSF_BUFFER_BUT_DONT_SEND) && !(nc->flags & NSF_CLOSE_IMMEDIATELY)) { ns_write_to_socket(nc); } } } } for (nc = mgr->active_connections; nc != NULL; nc = tmp) { tmp = nc->next; if ((nc->flags & NSF_CLOSE_IMMEDIATELY) || (nc->send_iobuf.len == 0 && (nc->flags & NSF_FINISHED_SENDING_DATA))) { ns_close_conn(nc); } } return current_time; }