summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilly Tarreau <w@1wt.eu>2020-09-25 19:40:31 +0200
committerWilly Tarreau <w@1wt.eu>2020-10-07 18:45:03 +0200
commit4597b6031268ca5940f272023ee4d1e61ff83cb6 (patch)
treeea3665b7396121d03eb01ffe21f6d4baa5250008
parent6b4780d029dfe1ab5709f9efd749df7a634740e1 (diff)
downloadhaproxy-4597b6031268ca5940f272023ee4d1e61ff83cb6.tar.gz
MINOR: protocol: implement an ->rx_resume() method
This one undoes ->rx_suspend(), it tries to restore an operational socket. It was only implemented for TCP since it's the only one we support right now.
-rw-r--r--include/haproxy/protocol-t.h6
-rw-r--r--src/proto_tcp.c20
2 files changed, 24 insertions, 2 deletions
diff --git a/include/haproxy/protocol-t.h b/include/haproxy/protocol-t.h
index 75da65b46..3d5ce82cd 100644
--- a/include/haproxy/protocol-t.h
+++ b/include/haproxy/protocol-t.h
@@ -74,8 +74,9 @@ struct proto_fam {
/* 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(). rx_* may be null if the
- * protocol doesn't provide direct access to the receiver.
+ * bind() primitive must be used before any fork(). rx_suspend()/rx_resume()
+ * return >0 on success, 0 if rx stopped, -1 on failure to proceed. 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 */
@@ -91,6 +92,7 @@ struct protocol {
/* functions acting on the receiver */
int (*rx_suspend)(struct receiver *rx); /* temporarily suspend this receiver for a soft restart */
+ int (*rx_resume)(struct receiver *rx); /* try to resume a temporarily suspended receiver */
/* functions acting on connections */
void (*accept)(int fd); /* generic accept function */
diff --git a/src/proto_tcp.c b/src/proto_tcp.c
index fdfb2899b..81eda1428 100644
--- a/src/proto_tcp.c
+++ b/src/proto_tcp.c
@@ -46,6 +46,7 @@
static int tcp_bind_listener(struct listener *listener, char *errmsg, int errlen);
static int tcp_suspend_receiver(struct receiver *rx);
+static int tcp_resume_receiver(struct receiver *rx);
static void tcpv4_add_listener(struct listener *listener, int port);
static void tcpv6_add_listener(struct listener *listener, int port);
@@ -60,6 +61,7 @@ static struct protocol proto_tcpv4 = {
.add = tcpv4_add_listener,
.listen = tcp_bind_listener,
.rx_suspend = tcp_suspend_receiver,
+ .rx_resume = tcp_resume_receiver,
.accept = &listener_accept,
.connect = tcp_connect_server,
.receivers = LIST_HEAD_INIT(proto_tcpv4.receivers),
@@ -79,6 +81,7 @@ static struct protocol proto_tcpv6 = {
.add = tcpv6_add_listener,
.listen = tcp_bind_listener,
.rx_suspend = tcp_suspend_receiver,
+ .rx_resume = tcp_resume_receiver,
.accept = &listener_accept,
.connect = tcp_connect_server,
.receivers = LIST_HEAD_INIT(proto_tcpv6.receivers),
@@ -746,6 +749,23 @@ static int tcp_suspend_receiver(struct receiver *rx)
return 1;
}
+/* Resume a receiver. Returns < 0 in case of failure, 0 if the receiver
+ * was totally stopped, or > 0 if correctly suspended.
+ */
+static int tcp_resume_receiver(struct receiver *rx)
+{
+ struct listener *l = LIST_ELEM(rx, struct listener *, rx);
+
+ if (rx->fd < 0)
+ return 0;
+
+ if (listen(rx->fd, listener_backlog(l)) == 0) {
+ fd_want_recv(l->rx.fd);
+ return 1;
+ }
+ return -1;
+}
+
/*
* Local variables: