diff --git a/include/haproxy/protocol-t.h b/include/haproxy/protocol-t.h index cd642b46e..ce92765ea 100644 --- a/include/haproxy/protocol-t.h +++ b/include/haproxy/protocol-t.h @@ -100,6 +100,8 @@ struct protocol { void (*ctrl_close)(struct connection *); /* completes release of the connection */ int (*connect)(struct connection *, int flags); /* connect function if any, see below for flags values */ int (*drain)(struct connection *); /* drain pending data; 0=failed, >0=success */ + int (*check_events)(struct connection *conn, int event_type); /* subscribe to socket events */ + void (*ignore_events)(struct connection *conn, int event_type); /* unsubscribe from socket events */ /* functions acting on the receiver */ int (*rx_suspend)(struct receiver *rx); /* temporarily suspend this receiver for a soft restart */ diff --git a/include/haproxy/sock.h b/include/haproxy/sock.h index 20f4dee08..1a5b68c5a 100644 --- a/include/haproxy/sock.h +++ b/include/haproxy/sock.h @@ -48,6 +48,8 @@ void sock_conn_ctrl_close(struct connection *conn); void sock_conn_iocb(int fd); int sock_conn_check(struct connection *conn); int sock_drain(struct connection *conn); +int sock_check_events(struct connection *conn, int event_type); +void sock_ignore_events(struct connection *conn, int event_type); #endif /* _HAPROXY_SOCK_H */ diff --git a/src/proto_sockpair.c b/src/proto_sockpair.c index 9c16b2bcf..ca4fc6d8b 100644 --- a/src/proto_sockpair.c +++ b/src/proto_sockpair.c @@ -78,6 +78,8 @@ struct protocol proto_sockpair = { .ctrl_close = sock_conn_ctrl_close, .connect = sockpair_connect_server, .drain = sock_drain, + .check_events = sock_check_events, + .ignore_events = sock_ignore_events, /* binding layer */ /* Note: suspend/resume not supported */ diff --git a/src/proto_tcp.c b/src/proto_tcp.c index dcc524ddb..485603d57 100644 --- a/src/proto_tcp.c +++ b/src/proto_tcp.c @@ -68,6 +68,8 @@ struct protocol proto_tcpv4 = { .ctrl_close = sock_conn_ctrl_close, .connect = tcp_connect_server, .drain = sock_drain, + .check_events = sock_check_events, + .ignore_events = sock_ignore_events, /* binding layer */ .rx_suspend = tcp_suspend_receiver, @@ -108,6 +110,8 @@ struct protocol proto_tcpv6 = { .ctrl_close = sock_conn_ctrl_close, .connect = tcp_connect_server, .drain = sock_drain, + .check_events = sock_check_events, + .ignore_events = sock_ignore_events, /* binding layer */ .rx_suspend = tcp_suspend_receiver, diff --git a/src/proto_uxst.c b/src/proto_uxst.c index 9b1fc38d5..f33099e70 100644 --- a/src/proto_uxst.c +++ b/src/proto_uxst.c @@ -64,6 +64,8 @@ struct protocol proto_uxst = { .ctrl_close = sock_conn_ctrl_close, .connect = uxst_connect_server, .drain = sock_drain, + .check_events = sock_check_events, + .ignore_events = sock_ignore_events, /* binding layer */ .rx_suspend = uxst_suspend_receiver, diff --git a/src/sock.c b/src/sock.c index cd1e3ffa6..20ebdd0e4 100644 --- a/src/sock.c +++ b/src/sock.c @@ -872,6 +872,45 @@ int sock_drain(struct connection *conn) return 1; } +/* Checks the connection's FD for readiness of events , which may + * only be a combination of SUB_RETRY_RECV and SUB_RETRY_SEND. Those which are + * ready are returned. The ones that are not ready are enabled. The caller is + * expected to do what is needed to handle ready events and to deal with + * subsequent wakeups caused by the requested events' readiness. + */ +int sock_check_events(struct connection *conn, int event_type) +{ + int ret = 0; + + if (event_type & SUB_RETRY_RECV) { + if (fd_recv_ready(conn->handle.fd)) + ret |= SUB_RETRY_RECV; + else + fd_want_recv(conn->handle.fd); + } + + if (event_type & SUB_RETRY_SEND) { + if (fd_send_ready(conn->handle.fd)) + ret |= SUB_RETRY_SEND; + else + fd_want_send(conn->handle.fd); + } + + return ret; +} + +/* Ignore readiness events from connection's FD for events of types + * which may only be a combination of SUB_RETRY_RECV and SUB_RETRY_SEND. + */ +void sock_ignore_events(struct connection *conn, int event_type) +{ + if (event_type & SUB_RETRY_RECV) + fd_stop_recv(conn->handle.fd); + + if (event_type & SUB_RETRY_SEND) + fd_stop_send(conn->handle.fd); +} + /* * Local variables: * c-indent-level: 8