/* info about one given fd */
struct fdtab {
int (*iocb)(int fd); /* I/O handler, returns FD_WAIT_* */
- struct {
- int (*f)(int fd); /* read/write function */
- } cb[DIR_SIZE];
void *owner; /* the connection or listener associated with this fd, NULL if closed */
struct { /* used by pollers which support speculative polling */
unsigned char e; /* read and write events status. 4 bits, may be merged into flags' lower bits */
s->check_conn->flags = CO_FL_WAIT_L4_CONN; /* TCP connection pending */
fd_insert(fd);
fdtab[fd].owner = t;
- fdtab[fd].cb[DIR_RD].f = NULL;
- fdtab[fd].cb[DIR_WR].f = NULL;
fdtab[fd].iocb = &check_iocb;
fdtab[fd].flags = FD_FL_TCP | FD_FL_TCP_NODELAY;
EV_FD_SET(fd, DIR_WR); /* for connect status */
int e = epoll_events[count].events;
fd = epoll_events[count].data.fd;
+ if (!fdtab[fd].owner)
+ continue;
+
/* it looks complicated but gcc can optimize it away when constants
* have same values.
*/
((e & EPOLLERR) ? FD_POLL_ERR : 0) |
((e & EPOLLHUP) ? FD_POLL_HUP : 0);
- if ((fd_evts[FD2OFS(fd)] >> FD2BIT(fd)) & DIR2MSK(DIR_RD)) {
- if (!fdtab[fd].owner)
- continue;
- if (fdtab[fd].ev & (FD_POLL_IN|FD_POLL_HUP|FD_POLL_ERR))
- if (fdtab[fd].cb[DIR_RD].f)
- fdtab[fd].cb[DIR_RD].f(fd);
- }
-
- if ((fd_evts[FD2OFS(fd)] >> FD2BIT(fd)) & DIR2MSK(DIR_WR)) {
- if (!fdtab[fd].owner)
- continue;
- if (fdtab[fd].ev & (FD_POLL_OUT|FD_POLL_ERR|FD_POLL_HUP))
- if (fdtab[fd].cb[DIR_WR].f)
- fdtab[fd].cb[DIR_WR].f(fd);
- }
-
if (fdtab[fd].iocb && fdtab[fd].owner && fdtab[fd].ev)
fdtab[fd].iocb(fd);
}
for (count = 0; count < status; count++) {
fd = kev[count].ident;
+ if (!fdtab[fd].owner)
+ continue;
+
fdtab[fd].ev &= FD_POLL_STICKY;
if (kev[count].filter == EVFILT_READ) {
if (FD_ISSET(fd, fd_evts[DIR_RD])) {
- if (!fdtab[fd].owner)
- continue;
fdtab[fd].ev |= FD_POLL_IN;
- if (fdtab[fd].cb[DIR_RD].f)
- fdtab[fd].cb[DIR_RD].f(fd);
}
} else if (kev[count].filter == EVFILT_WRITE) {
if (FD_ISSET(fd, fd_evts[DIR_WR])) {
- if (!fdtab[fd].owner)
- continue;
fdtab[fd].ev |= FD_POLL_OUT;
- if (fdtab[fd].cb[DIR_WR].f)
- fdtab[fd].cb[DIR_WR].f(fd)
}
}
- if (fdtab[fd].iocb && fdtab[fd].owner && fdtab[fd].ev)
+ if (fdtab[fd].iocb && fdtab[fd].ev)
fdtab[fd].iocb(fd);
}
}
if (!(e & ( POLLOUT | POLLIN | POLLERR | POLLHUP )))
continue;
+ /* ok, we found one active fd */
+ status--;
+
+ if (!fdtab[fd].owner)
+ continue;
+
fdtab[fd].ev &= FD_POLL_STICKY;
fdtab[fd].ev |=
((e & POLLIN ) ? FD_POLL_IN : 0) |
((e & POLLERR) ? FD_POLL_ERR : 0) |
((e & POLLHUP) ? FD_POLL_HUP : 0);
- /* ok, we found one active fd */
- status--;
-
- if (FD_ISSET(fd, fd_evts[DIR_RD])) {
- if (!fdtab[fd].owner)
- continue;
- if (fdtab[fd].ev & (FD_POLL_IN|FD_POLL_HUP|FD_POLL_ERR))
- if (fdtab[fd].cb[DIR_RD].f)
- fdtab[fd].cb[DIR_RD].f(fd);
- }
-
- if (FD_ISSET(fd, fd_evts[DIR_WR])) {
- if (!fdtab[fd].owner)
- continue;
- if (fdtab[fd].ev & (FD_POLL_OUT|FD_POLL_ERR|FD_POLL_HUP))
- if (fdtab[fd].cb[DIR_WR].f)
- fdtab[fd].cb[DIR_WR].f(fd);
- }
-
if (fdtab[fd].iocb && fdtab[fd].owner && fdtab[fd].ev)
fdtab[fd].iocb(fd);
}
/* if we specify read first, the accepts and zero reads will be
* seen first. Moreover, system buffers will be flushed faster.
*/
+ if (!fdtab[fd].owner)
+ continue;
+
fdtab[fd].ev &= FD_POLL_STICKY;
- if (FD_ISSET(fd, tmp_evts[DIR_RD])) {
- if (!fdtab[fd].owner)
- continue;
+ if (FD_ISSET(fd, tmp_evts[DIR_RD]))
fdtab[fd].ev |= FD_POLL_IN;
- if (fdtab[fd].cb[DIR_RD].f)
- fdtab[fd].cb[DIR_RD].f(fd);
- }
- if (FD_ISSET(fd, tmp_evts[DIR_WR])) {
- if (!fdtab[fd].owner)
- continue;
+ if (FD_ISSET(fd, tmp_evts[DIR_WR]))
fdtab[fd].ev |= FD_POLL_OUT;
- if (fdtab[fd].cb[DIR_WR].f)
- fdtab[fd].cb[DIR_WR].f(fd);
- }
if (fdtab[fd].iocb && fdtab[fd].owner && fdtab[fd].ev)
fdtab[fd].iocb(fd);
int e = epoll_events[count].events;
fd = epoll_events[count].data.fd;
+ if (!fdtab[fd].owner)
+ continue;
+
/* it looks complicated but gcc can optimize it away when constants
* have same values.
*/
((e & EPOLLERR) ? FD_POLL_ERR : 0) |
((e & EPOLLHUP) ? FD_POLL_HUP : 0);
- if ((fdtab[fd].spec.e & FD_EV_MASK_R) == FD_EV_WAIT_R) {
- if (!fdtab[fd].owner)
- continue;
- if (fdtab[fd].ev & (FD_POLL_IN|FD_POLL_HUP|FD_POLL_ERR))
- if (fdtab[fd].cb[DIR_RD].f)
- fdtab[fd].cb[DIR_RD].f(fd);
- }
-
- if ((fdtab[fd].spec.e & FD_EV_MASK_W) == FD_EV_WAIT_W) {
- if (!fdtab[fd].owner)
- continue;
- if (fdtab[fd].ev & (FD_POLL_OUT|FD_POLL_ERR))
- if (fdtab[fd].cb[DIR_WR].f)
- fdtab[fd].cb[DIR_WR].f(fd);
- }
-
if (fdtab[fd].iocb && fdtab[fd].owner && fdtab[fd].ev)
fdtab[fd].iocb(fd);
}
*/
fdtab[fd].ev &= FD_POLL_STICKY;
- if ((eo & FD_EV_MASK_R) == FD_EV_SPEC_R) {
- /* The owner is interested in reading from this FD */
- /* Pretend there is something to read */
+ if ((eo & FD_EV_MASK_R) == FD_EV_SPEC_R)
fdtab[fd].ev |= FD_POLL_IN;
- if (fdtab[fd].cb[DIR_RD].f && !fdtab[fd].cb[DIR_RD].f(fd))
- fdtab[fd].spec.e ^= (FD_EV_WAIT_R ^ FD_EV_SPEC_R);
- }
- if ((eo & FD_EV_MASK_W) == FD_EV_SPEC_W) {
- /* The owner is interested in writing to this FD */
- /* Pretend there is something to write */
+ if ((eo & FD_EV_MASK_W) == FD_EV_SPEC_W)
fdtab[fd].ev |= FD_POLL_OUT;
- if (fdtab[fd].cb[DIR_WR].f && !fdtab[fd].cb[DIR_WR].f(fd))
- fdtab[fd].spec.e ^= (FD_EV_WAIT_W ^ FD_EV_SPEC_W);
- }
if (fdtab[fd].iocb && fdtab[fd].owner && fdtab[fd].ev) {
int wait = fdtab[fd].iocb(fd);
fdtab[fd].flags = FD_FL_TCP | FD_FL_TCP_NODELAY;
si->conn.flags = CO_FL_WAIT_L4_CONN; /* connection in progress */
- /* Prepare to send a few handshakes related to the on-wire protocol.
- * If we have nothing to send, we want to confirm that the TCP
- * connection is established before doing so, so we use our own write
- * callback then switch to the sock layer.
- */
- fdtab[fd].cb[DIR_RD].f = NULL;
- fdtab[fd].cb[DIR_WR].f = NULL;
-
+ /* Prepare to send a few handshakes related to the on-wire protocol. */
if (si->send_proxy_ofs)
si->conn.flags |= CO_FL_SI_SEND_PROXY;
*/
b->flags |= BF_WRITE_NULL;
- /* The FD is ready now, we can hand the handlers to the socket layer
- * and forward the event there to start working on the socket.
+ /* The FD is ready now, we'll mark the connection as complete and
+ * forward the event to the data layer which will update the stream
+ * interface flags.
*/
- fdtab[fd].cb[DIR_RD].f = NULL;
- fdtab[fd].cb[DIR_WR].f = NULL;
conn->flags &= ~CO_FL_WAIT_L4_CONN;
si->exp = TICK_ETERNITY;
return si_data(si)->write(fd);
fdtab[fd].owner = listener; /* reference the listener instead of a task */
fdtab[fd].flags = FD_FL_TCP | ((listener->options & LI_O_NOLINGER) ? FD_FL_TCP_NOLING : 0);
fdtab[fd].iocb = listener->proto->accept;
- fdtab[fd].cb[DIR_RD].f = NULL; /* never called */
- fdtab[fd].cb[DIR_WR].f = NULL; /* never called */
fd_insert(fd);
tcp_return:
/* the function for the accept() event */
fd_insert(fd);
fdtab[fd].iocb = listener->proto->accept;
- fdtab[fd].cb[DIR_RD].f = NULL; /* never called */
- fdtab[fd].cb[DIR_WR].f = NULL; /* never called */
fdtab[fd].owner = listener; /* reference the listener instead of a task */
return ERR_NONE;
err_rename:
fd_insert(cfd);
fdtab[cfd].owner = &s->si[0].conn;
fdtab[cfd].flags = 0;
- fdtab[cfd].cb[DIR_RD].f = NULL;
- fdtab[cfd].cb[DIR_WR].f = NULL;
fdtab[cfd].iocb = conn_fd_handler;
EV_FD_SET(cfd, DIR_RD);