summaryrefslogtreecommitdiffstats
path: root/src/shrpx_quic_listener.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/shrpx_quic_listener.cc')
-rw-r--r--src/shrpx_quic_listener.cc112
1 files changed, 112 insertions, 0 deletions
diff --git a/src/shrpx_quic_listener.cc b/src/shrpx_quic_listener.cc
new file mode 100644
index 0000000..d22045d
--- /dev/null
+++ b/src/shrpx_quic_listener.cc
@@ -0,0 +1,112 @@
+/*
+ * nghttp2 - HTTP/2 C Library
+ *
+ * Copyright (c) 2021 Tatsuhiro Tsujikawa
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "shrpx_quic_listener.h"
+#include "shrpx_worker.h"
+#include "shrpx_config.h"
+#include "shrpx_log.h"
+
+namespace shrpx {
+
+namespace {
+void readcb(struct ev_loop *loop, ev_io *w, int revent) {
+ auto l = static_cast<QUICListener *>(w->data);
+ l->on_read();
+}
+} // namespace
+
+QUICListener::QUICListener(const UpstreamAddr *faddr, Worker *worker)
+ : faddr_{faddr}, worker_{worker} {
+ ev_io_init(&rev_, readcb, faddr_->fd, EV_READ);
+ rev_.data = this;
+ ev_io_start(worker_->get_loop(), &rev_);
+}
+
+QUICListener::~QUICListener() {
+ ev_io_stop(worker_->get_loop(), &rev_);
+ close(faddr_->fd);
+}
+
+void QUICListener::on_read() {
+ sockaddr_union su;
+ std::array<uint8_t, 64_k> buf;
+ size_t pktcnt = 0;
+ iovec msg_iov{buf.data(), buf.size()};
+
+ msghdr msg{};
+ msg.msg_name = &su;
+ msg.msg_iov = &msg_iov;
+ msg.msg_iovlen = 1;
+
+ uint8_t
+ msg_ctrl[CMSG_SPACE(sizeof(uint8_t)) + CMSG_SPACE(sizeof(in6_pktinfo))];
+ msg.msg_control = msg_ctrl;
+
+ auto quic_conn_handler = worker_->get_quic_connection_handler();
+
+ for (; pktcnt < 10;) {
+ msg.msg_namelen = sizeof(su);
+ msg.msg_controllen = sizeof(msg_ctrl);
+
+ auto nread = recvmsg(faddr_->fd, &msg, 0);
+ if (nread == -1) {
+ return;
+ }
+
+ ++pktcnt;
+
+ Address local_addr{};
+ if (util::msghdr_get_local_addr(local_addr, &msg, su.storage.ss_family) !=
+ 0) {
+ continue;
+ }
+
+ util::set_port(local_addr, faddr_->port);
+
+ ngtcp2_pkt_info pi{
+ .ecn = util::msghdr_get_ecn(&msg, su.storage.ss_family),
+ };
+
+ if (LOG_ENABLED(INFO)) {
+ LOG(INFO) << "QUIC received packet: local="
+ << util::to_numeric_addr(&local_addr)
+ << " remote=" << util::to_numeric_addr(&su.sa, msg.msg_namelen)
+ << " ecn=" << log::hex << pi.ecn << log::dec << " " << nread
+ << " bytes";
+ }
+
+ if (nread == 0) {
+ continue;
+ }
+
+ Address remote_addr;
+ remote_addr.su = su;
+ remote_addr.len = msg.msg_namelen;
+
+ quic_conn_handler->handle_packet(faddr_, remote_addr, local_addr, pi,
+ buf.data(), nread);
+ }
+}
+
+} // namespace shrpx