int tcp_bind_socket(int fd, int flags, struct sockaddr_storage *local, struct sockaddr_storage *remote);
void tcpv4_add_listener(struct listener *listener);
void tcpv6_add_listener(struct listener *listener);
+int tcp_pause_listener(struct listener *l);
int tcp_connect_server(struct connection *conn, int data, int delack);
int tcp_connect_probe(struct connection *conn);
int tcp_get_src(int fd, struct sockaddr *sa, socklen_t salen, int dir);
int (*get_src)(int fd, struct sockaddr *, socklen_t, int dir); /* syscall used to retrieve src addr */
int (*get_dst)(int fd, struct sockaddr *, socklen_t, int dir); /* syscall used to retrieve dst addr */
int (*drain)(int fd); /* indicates whether we can safely close the fd */
+ int (*pause)(struct listener *l); /* temporarily pause this listener for a soft restart */
struct list listeners; /* list of listeners using this protocol */
int nb_listeners; /* number of listeners */
if (l->state <= LI_PAUSED)
return 1;
- if (l->proto->sock_prot == IPPROTO_TCP) {
- if (shutdown(l->fd, SHUT_WR) != 0)
- return 0; /* Solaris dies here */
-
- if (listen(l->fd, l->backlog ? l->backlog : l->maxconn) != 0)
- return 0; /* OpenBSD dies here */
+ if (l->proto->pause) {
+ /* Returns < 0 in case of failure, 0 if the listener
+ * was totally stopped, or > 0 if correctly paused.
+ */
+ int ret = l->proto->pause(l);
- if (shutdown(l->fd, SHUT_RD) != 0)
- return 0; /* should always be OK */
+ if (ret < 0)
+ return 0;
+ else if (ret == 0)
+ return 1;
}
if (l->state == LI_LIMITED)
.get_src = tcp_get_src,
.get_dst = tcp_get_dst,
.drain = tcp_drain,
+ .pause = tcp_pause_listener,
.listeners = LIST_HEAD_INIT(proto_tcpv4.listeners),
.nb_listeners = 0,
};
.get_src = tcp_get_src,
.get_dst = tcp_get_dst,
.drain = tcp_drain,
+ .pause = tcp_pause_listener,
.listeners = LIST_HEAD_INIT(proto_tcpv6.listeners),
.nb_listeners = 0,
};
proto_tcpv6.nb_listeners++;
}
+/* Pause a listener. Returns < 0 in case of failure, 0 if the listener
+ * was totally stopped, or > 0 if correctly paused.
+ */
+int tcp_pause_listener(struct listener *l)
+{
+ if (shutdown(l->fd, SHUT_WR) != 0)
+ return -1; /* Solaris dies here */
+
+ if (listen(l->fd, l->backlog ? l->backlog : l->maxconn) != 0)
+ return -1; /* OpenBSD dies here */
+
+ if (shutdown(l->fd, SHUT_RD) != 0)
+ return -1; /* should always be OK */
+ return 1;
+}
+
/* This function performs the TCP request analysis on the current request. It
* returns 1 if the processing can continue on next analysers, or zero if it
* needs more data, encounters an error, or wants to immediately abort the