#define FD_FL_TCP 0x0001 /* socket is TCP */
#define FD_FL_TCP_NODELAY 0x0002
#define FD_FL_TCP_CORK 0x0004
+#define FD_FL_TCP_NOLING 0x0008 /* lingering disabled */
/* info about one given fd */
struct fdtab {
fdtab[cfd].owner = &s->si[0];
fdtab[cfd].state = FD_STREADY;
fdtab[cfd].flags = FD_FL_TCP | FD_FL_TCP_NODELAY;
+ if (p->options & PR_O_TCP_NOLING)
+ fdtab[cfd].flags |= FD_FL_TCP_NOLING;
+
fdtab[cfd].cb[DIR_RD].f = l->proto->read;
fdtab[cfd].cb[DIR_RD].b = s->req;
fdtab[cfd].cb[DIR_WR].f = l->proto->write;
fdtab[fd].owner = listener; /* reference the listener instead of a task */
fdtab[fd].state = FD_STLISTEN;
fdtab[fd].flags = FD_FL_TCP;
+ if (listener->options & LI_O_NOLINGER)
+ fdtab[fd].flags |= FD_FL_TCP_NOLING;
+
fdtab[fd].peeraddr = NULL;
fdtab[fd].peerlen = 0;
tcp_return:
* buffer but we know we will close, so we try to merge the ongoing FIN
* with the last data segment.
*/
- if ((fdtab[si->fd].flags & (FD_FL_TCP|FD_FL_TCP_CORK)) == FD_FL_TCP) {
+ if ((fdtab[si->fd].flags & (FD_FL_TCP|FD_FL_TCP_NOLING|FD_FL_TCP_CORK)) == FD_FL_TCP) {
if (unlikely((b->send_max == b->l &&
(b->flags & (BF_SHUTW|BF_SHUTW_NOW|BF_HIJACK|BF_WRITE_ENA|BF_SHUTR)) ==
(BF_WRITE_ENA|BF_SHUTR)))) {
shutdown(si->fd, SHUT_WR);
return;
}
+
+ if (fdtab[si->fd].flags & FD_FL_TCP_NOLING) {
+ /* we have to shut before closing if we disable lingering */
+ EV_FD_CLR(si->fd, DIR_WR);
+ shutdown(si->fd, SHUT_WR);
+ }
/* fall through */
case SI_ST_CON:
/* we may have to close a pending connection, and mark the