#include <haproxy/sample-t.h>
int tcp_bind_socket(int fd, int flags, struct sockaddr_storage *local, struct sockaddr_storage *remote);
-int tcp_pause_listener(struct listener *l);
int tcp_connect_server(struct connection *conn, int flags);
int tcp_is_foreign(int fd, sa_family_t family);
#define _PROTO_PROTO_UDP_H
int udp_bind_socket(int fd, int flags, struct sockaddr_storage *local, struct sockaddr_storage *remote);
-int udp_pause_listener(struct listener *l);
#endif /* _PROTO_PROTO_UDP_H */
/* This structure contains all information needed to easily handle a protocol.
* Its primary goal is to ease listeners maintenance. Specifically, the
- * bind() primitive must be used before any fork().
+ * bind() primitive must be used before any fork(). rx_* may be null if the
+ * protocol doesn't provide direct access to the receiver.
*/
struct protocol {
char name[PROTO_NAME_LEN]; /* protocol name, zero-terminated */
int sock_domain; /* socket domain, as passed to socket() */
int sock_type; /* socket type, as passed to socket() */
int sock_prot; /* socket protocol, as passed to socket() */
- void (*accept)(int fd); /* generic accept function */
+
+ /* functions acting on the listener */
+ void (*add)(struct listener *l, int port); /* add a listener for this protocol and port */
int (*listen)(struct listener *l, char *errmsg, int errlen); /* start a listener */
+
+ /* functions acting on the receiver */
+ int (*rx_suspend)(struct receiver *rx); /* temporarily suspend this receiver for a soft restart */
+
+ /* functions acting on connections */
+ void (*accept)(int fd); /* generic accept function */
int (*connect)(struct connection *, int flags); /* connect function if any, see below for flags values */
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 */
- void (*add)(struct listener *l, int port); /* add a listener for this protocol and port */
struct list receivers; /* list of receivers using this protocol (under proto_lock) */
int nb_receivers; /* number of receivers (under proto_lock) */
if (l->state <= LI_PAUSED)
goto end;
- if (l->rx.proto->pause) {
+ if (l->rx.proto->rx_suspend) {
/* Returns < 0 in case of failure, 0 if the listener
* was totally stopped, or > 0 if correctly paused.
*/
- ret = l->rx.proto->pause(l);
+ ret = l->rx.proto->rx_suspend(&l->rx);
if (ret < 0) {
ret = 0;
.sock_domain = AF_CUST_SOCKPAIR,
.sock_type = SOCK_STREAM,
.sock_prot = 0,
+ .add = sockpair_add_listener,
+ .listen = sockpair_bind_listener,
.accept = &listener_accept,
.connect = &sockpair_connect_server,
- .listen = sockpair_bind_listener,
- .pause = NULL,
- .add = sockpair_add_listener,
.receivers = LIST_HEAD_INIT(proto_sockpair.receivers),
.nb_receivers = 0,
};
static int tcp_bind_listener(struct listener *listener, char *errmsg, int errlen);
+static int tcp_suspend_receiver(struct receiver *rx);
static void tcpv4_add_listener(struct listener *listener, int port);
static void tcpv6_add_listener(struct listener *listener, int port);
.sock_domain = AF_INET,
.sock_type = SOCK_STREAM,
.sock_prot = IPPROTO_TCP,
+ .add = tcpv4_add_listener,
+ .listen = tcp_bind_listener,
+ .rx_suspend = tcp_suspend_receiver,
.accept = &listener_accept,
.connect = tcp_connect_server,
- .listen = tcp_bind_listener,
- .pause = tcp_pause_listener,
- .add = tcpv4_add_listener,
.receivers = LIST_HEAD_INIT(proto_tcpv4.receivers),
.nb_receivers = 0,
};
.sock_domain = AF_INET6,
.sock_type = SOCK_STREAM,
.sock_prot = IPPROTO_TCP,
+ .add = tcpv6_add_listener,
+ .listen = tcp_bind_listener,
+ .rx_suspend = tcp_suspend_receiver,
.accept = &listener_accept,
.connect = tcp_connect_server,
- .listen = tcp_bind_listener,
- .pause = tcp_pause_listener,
- .add = tcpv6_add_listener,
.receivers = LIST_HEAD_INIT(proto_tcpv6.receivers),
.nb_receivers = 0,
};
proto_tcpv6.nb_receivers++;
}
-/* Pause a listener. Returns < 0 in case of failure, 0 if the listener
- * was totally stopped, or > 0 if correctly paused.
+/* Suspend a receiver. Returns < 0 in case of failure, 0 if the receiver
+ * was totally stopped, or > 0 if correctly suspended.
*/
-int tcp_pause_listener(struct listener *l)
+static int tcp_suspend_receiver(struct receiver *rx)
{
+ struct listener *l = LIST_ELEM(rx, struct listener *, rx);
socklen_t opt_val, opt_len;
- if (shutdown(l->rx.fd, SHUT_WR) != 0)
+ if (shutdown(rx->fd, SHUT_WR) != 0)
goto check_already_done; /* usually Solaris fails here */
- if (listen(l->rx.fd, listener_backlog(l)) != 0)
+ if (listen(rx->fd, listener_backlog(l)) != 0)
goto check_already_done; /* Usually OpenBSD fails here */
- if (shutdown(l->rx.fd, SHUT_RD) != 0)
+ if (shutdown(rx->fd, SHUT_RD) != 0)
goto check_already_done; /* show always be OK */
- fd_stop_recv(l->rx.fd);
+ fd_stop_recv(rx->fd);
return 1;
check_already_done:
*/
opt_val = 0;
opt_len = sizeof(opt_val);
- if (getsockopt(l->rx.fd, SOL_SOCKET, SO_ACCEPTCONN, &opt_val, &opt_len) == -1) {
- fd_stop_recv(l->rx.fd);
+ if (getsockopt(rx->fd, SOL_SOCKET, SO_ACCEPTCONN, &opt_val, &opt_len) == -1) {
+ fd_stop_recv(rx->fd);
return 0; /* the socket is really unrecoverable */
}
if (!opt_val) {
- fd_stop_recv(l->rx.fd);
+ fd_stop_recv(rx->fd);
return 1; /* already paused by another process */
}
#include <haproxy/task.h>
static int udp_bind_listener(struct listener *listener, char *errmsg, int errlen);
+static int udp_suspend_receiver(struct receiver *rx);
static void udp4_add_listener(struct listener *listener, int port);
static void udp6_add_listener(struct listener *listener, int port);
.sock_domain = AF_INET,
.sock_type = SOCK_DGRAM,
.sock_prot = IPPROTO_UDP,
- .accept = NULL,
- .connect = NULL,
- .listen = udp_bind_listener,
- .pause = udp_pause_listener,
.add = udp4_add_listener,
+ .listen = udp_bind_listener,
+ .rx_suspend = udp_suspend_receiver,
.receivers = LIST_HEAD_INIT(proto_udp4.receivers),
.nb_receivers = 0,
};
.sock_domain = AF_INET6,
.sock_type = SOCK_DGRAM,
.sock_prot = IPPROTO_UDP,
- .accept = NULL,
- .connect = NULL,
- .listen = udp_bind_listener,
- .pause = udp_pause_listener,
.add = udp6_add_listener,
+ .listen = udp_bind_listener,
+ .rx_suspend = udp_suspend_receiver,
.receivers = LIST_HEAD_INIT(proto_udp6.receivers),
.nb_receivers = 0,
};
proto_udp6.nb_receivers++;
}
-/* Pause a listener. Returns < 0 in case of failure, 0 if the listener
- * was totally stopped, or > 0 if correctly paused.
+/* Suspend a receiver. Returns < 0 in case of failure, 0 if the receiver
+ * was totally stopped, or > 0 if correctly suspended.
*/
-int udp_pause_listener(struct listener *l)
+static int udp_suspend_receiver(struct receiver *rx)
{
- /* we don't support pausing on UDP */
+ /* we don't support suspend on UDP */
return -1;
}
static int uxst_bind_listener(struct listener *listener, char *errmsg, int errlen);
static int uxst_connect_server(struct connection *conn, int flags);
static void uxst_add_listener(struct listener *listener, int port);
-static int uxst_pause_listener(struct listener *l);
+static int uxst_suspend_receiver(struct receiver *rx);
/* Note: must not be declared <const> as its list will be overwritten */
static struct protocol proto_unix = {
.sock_domain = PF_UNIX,
.sock_type = SOCK_STREAM,
.sock_prot = 0,
+ .add = uxst_add_listener,
+ .listen = uxst_bind_listener,
+ .rx_suspend = uxst_suspend_receiver,
.accept = &listener_accept,
.connect = &uxst_connect_server,
- .listen = uxst_bind_listener,
- .pause = uxst_pause_listener,
- .add = uxst_add_listener,
.receivers = LIST_HEAD_INIT(proto_unix.receivers),
.nb_receivers = 0,
};
proto_unix.nb_receivers++;
}
-/* Pause a listener. Returns < 0 in case of failure, 0 if the listener
- * was totally stopped, or > 0 if correctly paused. Nothing is done for
+/* Suspend a receiver. Returns < 0 in case of failure, 0 if the receiver
+ * was totally stopped, or > 0 if correctly suspended. Nothing is done for
* plain unix sockets since currently it's the new process which handles
* the renaming. Abstract sockets are completely unbound and closed so
* there's no need to stop the poller.
*/
-static int uxst_pause_listener(struct listener *l)
+static int uxst_suspend_receiver(struct receiver *rx)
{
- if (((struct sockaddr_un *)&l->rx.addr)->sun_path[0])
+ struct listener *l = LIST_ELEM(rx, struct listener *, rx);
+
+ if (((struct sockaddr_un *)&rx->addr)->sun_path[0])
return 1;
/* Listener's lock already held. Call lockless version of