From 70da889d57051134d2c9536bf5aa66637432e664 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20L=C3=A9caille?= Date: Fri, 6 Nov 2020 15:49:49 +0100 Subject: [PATCH] MINOR: quic: Redefine control layer callbacks which are QUIC specific. We add src/quic_sock.c QUIC specific socket management functions as callbacks for the control layer: ->accept_conn, ->default_iocb and ->rx_listening. accept_conn() will have to be defined. The default I/O handler only recvfrom() the datagrams received. Furthermore, ->rx_listening callback always returns 1 at this time but should returns 0 when reloading the processus. --- include/haproxy/quic_sock.h | 43 ++++++++++++++++++++++ src/proto_quic.c | 13 +++---- src/quic_sock.c | 72 +++++++++++++++++++++++++++++++++++++ 3 files changed, 122 insertions(+), 6 deletions(-) create mode 100644 include/haproxy/quic_sock.h create mode 100644 src/quic_sock.c diff --git a/include/haproxy/quic_sock.h b/include/haproxy/quic_sock.h new file mode 100644 index 000000000..78623e817 --- /dev/null +++ b/include/haproxy/quic_sock.h @@ -0,0 +1,43 @@ +/* + * include/haproxy/quic_sock.h + * This file contains declarations for QUIC sockets. + * + * Copyright 2020 Frédéric Lécaille + * + * 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 _HAPROXY_QUIC_SOCK_H +#define _HAPROXY_QUIC_SOCK_H + +#include +#include + +#include +#include +#include + +int quic_sock_accepting_conn(const struct receiver *rx); +struct connection *quic_sock_accept_conn(struct listener *l, int *status); +void quic_sock_fd_iocb(int fd); + +#endif /* _HAPROXY_QUIC_SOCK_H */ + +/* + * Local variables: + * c-indent-level: 8 + * c-basic-offset: 8 + * End: + */ diff --git a/src/proto_quic.c b/src/proto_quic.c index bde3e4859..751fc49aa 100644 --- a/src/proto_quic.c +++ b/src/proto_quic.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include @@ -63,7 +64,7 @@ struct protocol proto_quic4 = { .unbind = default_unbind_listener, .suspend = default_suspend_listener, .resume = default_resume_listener, - .accept_conn = sock_accept_conn, + .accept_conn = quic_sock_accept_conn, .connect = quic_connect_server, /* binding layer */ @@ -79,8 +80,8 @@ struct protocol proto_quic4 = { .rx_enable = sock_enable, .rx_disable = sock_disable, .rx_unbind = sock_unbind, - .rx_listening = sock_accepting_conn, - .default_iocb = sock_accept_iocb, + .rx_listening = quic_sock_accepting_conn, + .default_iocb = quic_sock_fd_iocb, .receivers = LIST_HEAD_INIT(proto_quic4.receivers), .nb_receivers = 0, }; @@ -100,7 +101,7 @@ struct protocol proto_quic6 = { .unbind = default_unbind_listener, .suspend = default_suspend_listener, .resume = default_resume_listener, - .accept_conn = sock_accept_conn, + .accept_conn = quic_sock_accept_conn, .connect = quic_connect_server, /* binding layer */ @@ -116,8 +117,8 @@ struct protocol proto_quic6 = { .rx_enable = sock_enable, .rx_disable = sock_disable, .rx_unbind = sock_unbind, - .rx_listening = sock_accepting_conn, - .default_iocb = sock_accept_iocb, + .rx_listening = quic_sock_accepting_conn, + .default_iocb = quic_sock_fd_iocb, .receivers = LIST_HEAD_INIT(proto_quic6.receivers), .nb_receivers = 0, }; diff --git a/src/quic_sock.c b/src/quic_sock.c new file mode 100644 index 000000000..374e97bf6 --- /dev/null +++ b/src/quic_sock.c @@ -0,0 +1,72 @@ +/* + * QUIC socket management. + * + * Copyright 2020 HAProxy Technologies, Frédéric Lécaille + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ + +#include + +#include +#include + +#include +#include + +/* Tests if the receiver supports accepting connections. Returns positive on + * success, 0 if not possible + */ +int quic_sock_accepting_conn(const struct receiver *rx) +{ + return 1; +} + +/* Accept an incoming connection from listener , and return it, as well as + * a CO_AC_* status code into if not null. Null is returned on error. + * must be a valid listener with a valid frontend. + */ +struct connection *quic_sock_accept_conn(struct listener *l, int *status) +{ + /* TO DO */ + return NULL; +} + +/* Function called on a read event from a listening socket. It tries + * to handle as many connections as possible. + */ +void quic_sock_fd_iocb(int fd) +{ + ssize_t ret; + struct buffer *buf; + struct listener *l = objt_listener(fdtab[fd].owner); + /* Source address */ + struct sockaddr_storage saddr = {0}; + socklen_t saddrlen; + + if (!l) + ABORT_NOW(); + + if (!(fdtab[fd].ev & FD_POLL_IN) || !fd_recv_ready(fd)) + return; + + buf = get_trash_chunk(); + saddrlen = sizeof saddr; + do { + ret = recvfrom(fd, buf->area, buf->size, 0, + (struct sockaddr *)&saddr, &saddrlen); + if (ret < 0) { + if (errno == EINTR) + continue; + if (errno == EAGAIN) + fd_cant_recv(fd); + return; + } + } while (0); + + buf->data = ret; +}