/*
- include/types/fd.h
- File descriptors states.
-
- Copyright (C) 2000-2008 Willy Tarreau - w@1wt.eu
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation, version 2.1
- exclusively.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-*/
+ * include/types/fd.h
+ * File descriptors states.
+ *
+ * Copyright (C) 2000-2009 Willy Tarreau - w@1wt.eu
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, version 2.1
+ * exclusively.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
#ifndef _TYPES_FD_H
#define _TYPES_FD_H
unsigned short flags; /* various flags precising the exact status of this fd */
unsigned char state; /* the state of this fd */
unsigned char ev; /* event seen in return of poll() : FD_POLL_* */
- struct sockaddr *peeraddr; /* pointer to peer's network address, or NULL if unset */
- socklen_t peerlen; /* peer's address length, or 0 if unset */
- int local_port; /* optional local port */
+};
+
+/* less often used information */
+struct fdinfo {
struct port_range *port_range; /* optional port range to bind to */
+ int local_port; /* optional local port */
+ struct sockaddr *peeraddr; /* pointer to peer's network address, or NULL if unset */
+ socklen_t peerlen; /* peer's address length, or 0 if unset */
};
/*
extern struct poller pollers[MAX_POLLERS]; /* all registered pollers */
extern struct fdtab *fdtab; /* array of all the file descriptors */
+extern struct fdinfo *fdinfo; /* less-often used infos for file descriptors */
extern int maxfd; /* # of the highest fd + 1 */
extern int totalconn; /* total # of terminated sessions */
extern int actconn; /* # of active sessions */
/* note: in case of retry, we may have to release a previously
* allocated port, hence this loop's construct.
*/
- port_range_release_port(fdtab[fd].port_range, fdtab[fd].local_port);
- fdtab[fd].port_range = NULL;
+ port_range_release_port(fdinfo[fd].port_range, fdinfo[fd].local_port);
+ fdinfo[fd].port_range = NULL;
if (!bind_attempts)
break;
bind_attempts--;
- fdtab[fd].local_port = port_range_alloc_port(s->sport_range);
- if (!fdtab[fd].local_port)
+ fdinfo[fd].local_port = port_range_alloc_port(s->sport_range);
+ if (!fdinfo[fd].local_port)
break;
- fdtab[fd].port_range = s->sport_range;
- src.sin_port = htons(fdtab[fd].local_port);
+ fdinfo[fd].port_range = s->sport_range;
+ src.sin_port = htons(fdinfo[fd].local_port);
ret = tcpv4_bind_socket(fd, flags, &src, remote);
} while (ret != 0); /* binding NOK */
fdtab[fd].cb[DIR_RD].b = NULL;
fdtab[fd].cb[DIR_WR].f = &event_srv_chk_w;
fdtab[fd].cb[DIR_WR].b = NULL;
- fdtab[fd].peeraddr = (struct sockaddr *)&sa;
- fdtab[fd].peerlen = sizeof(sa);
+ fdinfo[fd].peeraddr = (struct sockaddr *)&sa;
+ fdinfo[fd].peerlen = sizeof(sa);
fdtab[fd].state = FD_STCONN; /* connection in progress */
fdtab[fd].flags = FD_FL_TCP | FD_FL_TCP_NODELAY;
EV_FD_SET(fd, DIR_WR); /* for connect status */
}
}
}
- port_range_release_port(fdtab[fd].port_range, fdtab[fd].local_port);
- fdtab[fd].port_range = NULL;
+ port_range_release_port(fdinfo[fd].port_range, fdinfo[fd].local_port);
+ fdinfo[fd].port_range = NULL;
close(fd); /* socket creation error */
}
fdtab[cfd].cb[DIR_RD].b = s->req;
fdtab[cfd].cb[DIR_WR].f = l->proto->write;
fdtab[cfd].cb[DIR_WR].b = s->rep;
- fdtab[cfd].peeraddr = (struct sockaddr *)&s->cli_addr;
- fdtab[cfd].peerlen = sizeof(s->cli_addr);
+ fdinfo[cfd].peeraddr = (struct sockaddr *)&s->cli_addr;
+ fdinfo[cfd].peerlen = sizeof(s->cli_addr);
if ((p->mode == PR_MODE_HTTP && (s->flags & SN_MONITOR)) ||
(p->mode == PR_MODE_HEALTH && (p->options & PR_O_HTTP_CHK))) {
#include <proto/port_range.h>
struct fdtab *fdtab = NULL; /* array of all the file descriptors */
+struct fdinfo *fdinfo = NULL; /* less-often used infos for file descriptors */
int maxfd; /* # of the highest fd + 1 */
int totalconn; /* total # of terminated sessions */
int actconn; /* # of active sessions */
void fd_delete(int fd)
{
EV_FD_CLO(fd);
- port_range_release_port(fdtab[fd].port_range, fdtab[fd].local_port);
- fdtab[fd].port_range = NULL;
+ port_range_release_port(fdinfo[fd].port_range, fdinfo[fd].local_port);
+ fdinfo[fd].port_range = NULL;
close(fd);
fdtab[fd].state = FD_STCLOSE;
if (global.nbproc < 1)
global.nbproc = 1;
+ fdinfo = (struct fdinfo *)calloc(1,
+ sizeof(struct fdinfo) * (global.maxsock));
fdtab = (struct fdtab *)calloc(1,
sizeof(struct fdtab) * (global.maxsock));
for (i = 0; i < global.maxsock; i++) {
/* note: in case of retry, we may have to release a previously
* allocated port, hence this loop's construct.
*/
- port_range_release_port(fdtab[fd].port_range, fdtab[fd].local_port);
- fdtab[fd].port_range = NULL;
+ port_range_release_port(fdinfo[fd].port_range, fdinfo[fd].local_port);
+ fdinfo[fd].port_range = NULL;
if (!attempts)
break;
attempts--;
- fdtab[fd].local_port = port_range_alloc_port(srv->sport_range);
- if (!fdtab[fd].local_port)
+ fdinfo[fd].local_port = port_range_alloc_port(srv->sport_range);
+ if (!fdinfo[fd].local_port)
break;
- fdtab[fd].port_range = srv->sport_range;
- src.sin_port = htons(fdtab[fd].local_port);
+ fdinfo[fd].port_range = srv->sport_range;
+ src.sin_port = htons(fdinfo[fd].local_port);
ret = tcpv4_bind_socket(fd, flags, &src, remote);
} while (ret != 0); /* binding NOK */
}
if (ret) {
- port_range_release_port(fdtab[fd].port_range, fdtab[fd].local_port);
- fdtab[fd].port_range = NULL;
+ port_range_release_port(fdinfo[fd].port_range, fdinfo[fd].local_port);
+ fdinfo[fd].port_range = NULL;
close(fd);
if (ret == 1) {
msg = "local address already in use";
qfprintf(stderr,"Cannot connect: %s.\n",msg);
- port_range_release_port(fdtab[fd].port_range, fdtab[fd].local_port);
- fdtab[fd].port_range = NULL;
+ port_range_release_port(fdinfo[fd].port_range, fdinfo[fd].local_port);
+ fdinfo[fd].port_range = NULL;
close(fd);
send_log(be, LOG_EMERG,
"Connect() failed for server %s/%s: %s.\n",
return SN_ERR_RESOURCE;
} else if (errno == ETIMEDOUT) {
//qfprintf(stderr,"Connect(): ETIMEDOUT");
- port_range_release_port(fdtab[fd].port_range, fdtab[fd].local_port);
- fdtab[fd].port_range = NULL;
+ port_range_release_port(fdinfo[fd].port_range, fdinfo[fd].local_port);
+ fdinfo[fd].port_range = NULL;
close(fd);
return SN_ERR_SRVTO;
} else {
// (errno == ECONNREFUSED || errno == ENETUNREACH || errno == EACCES || errno == EPERM)
//qfprintf(stderr,"Connect(): %d", errno);
- port_range_release_port(fdtab[fd].port_range, fdtab[fd].local_port);
- fdtab[fd].port_range = NULL;
+ port_range_release_port(fdinfo[fd].port_range, fdinfo[fd].local_port);
+ fdinfo[fd].port_range = NULL;
close(fd);
return SN_ERR_SRVCL;
}
fdtab[fd].cb[DIR_WR].f = &stream_sock_write;
fdtab[fd].cb[DIR_WR].b = si->ob;
- fdtab[fd].peeraddr = (struct sockaddr *)srv_addr;
- fdtab[fd].peerlen = sizeof(struct sockaddr_in);
+ fdinfo[fd].peeraddr = (struct sockaddr *)srv_addr;
+ fdinfo[fd].peerlen = sizeof(struct sockaddr_in);
fd_insert(fd);
EV_FD_SET(fd, DIR_WR); /* for connect status */
if (listener->options & LI_O_NOLINGER)
fdtab[fd].flags |= FD_FL_TCP_NOLING;
- fdtab[fd].peeraddr = NULL;
- fdtab[fd].peerlen = 0;
+ fdinfo[fd].peeraddr = NULL;
+ fdinfo[fd].peerlen = 0;
tcp_return:
if (msg && errlen)
strlcpy2(errmsg, msg, errlen);
fdtab[fd].cb[DIR_RD].b = fdtab[fd].cb[DIR_WR].b = NULL;
fdtab[fd].owner = listener; /* reference the listener instead of a task */
fdtab[fd].state = FD_STLISTEN;
- fdtab[fd].peeraddr = NULL;
- fdtab[fd].peerlen = 0;
+ fdinfo[fd].peeraddr = NULL;
+ fdinfo[fd].peerlen = 0;
return ERR_NONE;
}
fdtab[cfd].cb[DIR_RD].b = s->req;
fdtab[cfd].cb[DIR_WR].f = l->proto->write;
fdtab[cfd].cb[DIR_WR].b = s->rep;
- fdtab[cfd].peeraddr = (struct sockaddr *)&s->cli_addr;
- fdtab[cfd].peerlen = sizeof(s->cli_addr);
+ fdinfo[cfd].peeraddr = (struct sockaddr *)&s->cli_addr;
+ fdinfo[cfd].peerlen = sizeof(s->cli_addr);
EV_FD_SET(cfd, DIR_RD);
* - connecting (EALREADY, EINPROGRESS)
* - connected (EISCONN, 0)
*/
- if ((connect(fd, fdtab[fd].peeraddr, fdtab[fd].peerlen) == 0))
+ if ((connect(fd, fdinfo[fd].peeraddr, fdinfo[fd].peerlen) == 0))
errno = 0;
if (errno == EALREADY || errno == EINPROGRESS) {