nghttpx: Add QUICConnectionHandler and HTTP3Upstream skeleton
This commit is contained in:
parent
8b2746abf1
commit
aeb0b0728d
|
@ -155,6 +155,8 @@ NGHTTPX_SRCS = \
|
|||
shrpx_dns_tracker.cc shrpx_dns_tracker.h \
|
||||
shrpx_quic.cc shrpx_quic.h \
|
||||
shrpx_quic_listener.cc shrpx_quic_listener.h \
|
||||
shrpx_quic_connection_handler.cc shrpx_quic_connection_handler.h \
|
||||
shrpx_http3_upstream.cc shrpx_http3_upstream.h \
|
||||
buffer.h memchunk.h template.h allocator.h \
|
||||
xsi_strerror.c xsi_strerror.h
|
||||
|
||||
|
|
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
* 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_http3_upstream.h"
|
||||
#include "shrpx_client_handler.h"
|
||||
#include "shrpx_downstream.h"
|
||||
#include "shrpx_downstream_connection.h"
|
||||
#include "shrpx_log.h"
|
||||
|
||||
namespace shrpx {
|
||||
|
||||
Http3Upstream::Http3Upstream(ClientHandler *handler) : handler_{handler} {}
|
||||
|
||||
Http3Upstream::~Http3Upstream() {}
|
||||
|
||||
int Http3Upstream::on_read() { return 0; }
|
||||
|
||||
int Http3Upstream::on_write() { return 0; }
|
||||
|
||||
int Http3Upstream::on_timeout(Downstream *downstream) { return 0; }
|
||||
|
||||
int Http3Upstream::on_downstream_abort_request(Downstream *downstream,
|
||||
unsigned int status_code) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Http3Upstream::on_downstream_abort_request_with_https_redirect(
|
||||
Downstream *downstream) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Http3Upstream::downstream_read(DownstreamConnection *dconn) { return 0; }
|
||||
|
||||
int Http3Upstream::downstream_write(DownstreamConnection *dconn) { return 0; }
|
||||
|
||||
int Http3Upstream::downstream_eof(DownstreamConnection *dconn) { return 0; }
|
||||
|
||||
int Http3Upstream::downstream_error(DownstreamConnection *dconn, int events) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ClientHandler *Http3Upstream::get_client_handler() const { return handler_; }
|
||||
|
||||
int Http3Upstream::on_downstream_header_complete(Downstream *downstream) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Http3Upstream::on_downstream_body(Downstream *downstream,
|
||||
const uint8_t *data, size_t len,
|
||||
bool flush) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Http3Upstream::on_downstream_body_complete(Downstream *downstream) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Http3Upstream::on_handler_delete() {}
|
||||
|
||||
int Http3Upstream::on_downstream_reset(Downstream *downstream, bool no_retry) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Http3Upstream::pause_read(IOCtrlReason reason) {}
|
||||
|
||||
int Http3Upstream::resume_read(IOCtrlReason reason, Downstream *downstream,
|
||||
size_t consumed) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Http3Upstream::send_reply(Downstream *downstream, const uint8_t *body,
|
||||
size_t bodylen) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Http3Upstream::initiate_push(Downstream *downstream, const StringRef &uri) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Http3Upstream::response_riovec(struct iovec *iov, int iovcnt) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Http3Upstream::response_drain(size_t n) {}
|
||||
|
||||
bool Http3Upstream::response_empty() const { return false; }
|
||||
|
||||
Downstream *
|
||||
Http3Upstream::on_downstream_push_promise(Downstream *downstream,
|
||||
int32_t promised_stream_id) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int Http3Upstream::on_downstream_push_promise_complete(
|
||||
Downstream *downstream, Downstream *promised_downstream) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Http3Upstream::push_enabled() const { return false; }
|
||||
|
||||
void Http3Upstream::cancel_premature_downstream(
|
||||
Downstream *promised_downstream) {}
|
||||
|
||||
int Http3Upstream::on_read(const UpstreamAddr *faddr,
|
||||
const Address &remote_addr,
|
||||
const Address &local_addr, const uint8_t *data,
|
||||
size_t datalen) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace shrpx
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef SHRPX_HTTP3_UPSTREAM_H
|
||||
#define SHRPX_HTTP3_UPSTREAM_H
|
||||
|
||||
#include "shrpx.h"
|
||||
#include "shrpx_upstream.h"
|
||||
#include "network.h"
|
||||
|
||||
using namespace nghttp2;
|
||||
|
||||
namespace shrpx {
|
||||
|
||||
struct UpstreamAddr;
|
||||
|
||||
class Http3Upstream : public Upstream {
|
||||
public:
|
||||
Http3Upstream(ClientHandler *handler);
|
||||
virtual ~Http3Upstream();
|
||||
|
||||
virtual int on_read();
|
||||
virtual int on_write();
|
||||
virtual int on_timeout(Downstream *downstream);
|
||||
virtual int on_downstream_abort_request(Downstream *downstream,
|
||||
unsigned int status_code);
|
||||
virtual int
|
||||
on_downstream_abort_request_with_https_redirect(Downstream *downstream);
|
||||
virtual int downstream_read(DownstreamConnection *dconn);
|
||||
virtual int downstream_write(DownstreamConnection *dconn);
|
||||
virtual int downstream_eof(DownstreamConnection *dconn);
|
||||
virtual int downstream_error(DownstreamConnection *dconn, int events);
|
||||
virtual ClientHandler *get_client_handler() const;
|
||||
|
||||
virtual int on_downstream_header_complete(Downstream *downstream);
|
||||
virtual int on_downstream_body(Downstream *downstream, const uint8_t *data,
|
||||
size_t len, bool flush);
|
||||
virtual int on_downstream_body_complete(Downstream *downstream);
|
||||
|
||||
virtual void on_handler_delete();
|
||||
virtual int on_downstream_reset(Downstream *downstream, bool no_retry);
|
||||
|
||||
virtual void pause_read(IOCtrlReason reason);
|
||||
virtual int resume_read(IOCtrlReason reason, Downstream *downstream,
|
||||
size_t consumed);
|
||||
virtual int send_reply(Downstream *downstream, const uint8_t *body,
|
||||
size_t bodylen);
|
||||
|
||||
virtual int initiate_push(Downstream *downstream, const StringRef &uri);
|
||||
|
||||
virtual int response_riovec(struct iovec *iov, int iovcnt) const;
|
||||
virtual void response_drain(size_t n);
|
||||
virtual bool response_empty() const;
|
||||
|
||||
virtual Downstream *on_downstream_push_promise(Downstream *downstream,
|
||||
int32_t promised_stream_id);
|
||||
virtual int
|
||||
on_downstream_push_promise_complete(Downstream *downstream,
|
||||
Downstream *promised_downstream);
|
||||
virtual bool push_enabled() const;
|
||||
virtual void cancel_premature_downstream(Downstream *promised_downstream);
|
||||
|
||||
int on_read(const UpstreamAddr *faddr, const Address &remote_addr,
|
||||
const Address &local_addr, const uint8_t *data, size_t datalen);
|
||||
|
||||
private:
|
||||
ClientHandler *handler_;
|
||||
};
|
||||
|
||||
} // namespace shrpx
|
||||
|
||||
#endif // SHRPX_HTTP3_UPSTREAM_H
|
|
@ -185,4 +185,11 @@ int create_quic_server_socket(UpstreamAddr &faddr) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int quic_send_packet(const UpstreamAddr *addr, const sockaddr *remote_sa,
|
||||
size_t remote_salen, const sockaddr *local_sa,
|
||||
size_t local_salen, const uint8_t *data, size_t datalen,
|
||||
size_t gso_size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace shrpx
|
||||
|
|
|
@ -27,12 +27,21 @@
|
|||
|
||||
#include "shrpx.h"
|
||||
|
||||
struct UpstreamAddr;
|
||||
#include <stdint.h>
|
||||
|
||||
namespace shrpx {
|
||||
|
||||
struct UpstreamAddr;
|
||||
|
||||
constexpr size_t SHRPX_QUIC_SCIDLEN = 20;
|
||||
|
||||
int create_quic_server_socket(UpstreamAddr &addr);
|
||||
|
||||
int quic_send_packet(const UpstreamAddr *addr, const sockaddr *remote_sa,
|
||||
size_t remote_salen, const sockaddr *local_sa,
|
||||
size_t local_salen, const uint8_t *data, size_t datalen,
|
||||
size_t gso_size);
|
||||
|
||||
} // namespace shrpx
|
||||
|
||||
#endif // SHRPX_QUIC_H
|
||||
|
|
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
* 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_connection_handler.h"
|
||||
|
||||
#include <ngtcp2/ngtcp2.h>
|
||||
|
||||
#include "shrpx_worker.h"
|
||||
#include "shrpx_client_handler.h"
|
||||
#include "shrpx_log.h"
|
||||
#include "shrpx_quic.h"
|
||||
#include "shrpx_http3_upstream.h"
|
||||
|
||||
namespace shrpx {
|
||||
|
||||
QUICConnectionHandler::QUICConnectionHandler(Worker *worker)
|
||||
: worker_{worker} {}
|
||||
|
||||
QUICConnectionHandler::~QUICConnectionHandler() {}
|
||||
|
||||
namespace {
|
||||
std::string make_cid_key(const uint8_t *dcid, size_t dcidlen) {
|
||||
return std::string{dcid, dcid + dcidlen};
|
||||
}
|
||||
} // namespace
|
||||
|
||||
int QUICConnectionHandler::handle_packet(const UpstreamAddr *faddr,
|
||||
const Address &remote_addr,
|
||||
const Address &local_addr,
|
||||
const uint8_t *data, size_t datalen) {
|
||||
int rv;
|
||||
uint32_t version;
|
||||
const uint8_t *dcid, *scid;
|
||||
size_t dcidlen, scidlen;
|
||||
|
||||
rv = ngtcp2_pkt_decode_version_cid(&version, &dcid, &dcidlen, &scid, &scidlen,
|
||||
data, datalen, SHRPX_QUIC_SCIDLEN);
|
||||
if (rv != 0) {
|
||||
if (rv == 1) {
|
||||
send_version_negotiation(faddr, version, scid, scidlen, dcid, dcidlen,
|
||||
remote_addr, local_addr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto dcid_key = make_cid_key(dcid, dcidlen);
|
||||
|
||||
auto it = connections_.find(dcid_key);
|
||||
if (it == std::end(connections_)) {
|
||||
// new connection
|
||||
|
||||
ngtcp2_pkt_hd hd;
|
||||
|
||||
switch (ngtcp2_accept(&hd, data, datalen)) {
|
||||
case 0:
|
||||
break;
|
||||
case NGTCP2_ERR_RETRY:
|
||||
// TODO Send retry
|
||||
return 0;
|
||||
case NGTCP2_ERR_VERSION_NEGOTIATION:
|
||||
send_version_negotiation(faddr, version, scid, scidlen, dcid, dcidlen,
|
||||
remote_addr, local_addr);
|
||||
return 0;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto h = (*it).second.get();
|
||||
auto upstream = static_cast<Http3Upstream *>(h->get_upstream());
|
||||
|
||||
// TODO Delete h on failure
|
||||
upstream->on_read(faddr, remote_addr, local_addr, data, datalen);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
namespace {
|
||||
uint32_t generate_reserved_version(const Address &addr, uint32_t version) {
|
||||
uint32_t h = 0x811C9DC5u;
|
||||
const uint8_t *p = reinterpret_cast<const uint8_t *>(&addr.su.sa);
|
||||
const uint8_t *ep = p + addr.len;
|
||||
|
||||
for (; p != ep; ++p) {
|
||||
h ^= *p;
|
||||
h *= 0x01000193u;
|
||||
}
|
||||
|
||||
version = htonl(version);
|
||||
p = (const uint8_t *)&version;
|
||||
ep = p + sizeof(version);
|
||||
|
||||
for (; p != ep; ++p) {
|
||||
h ^= *p;
|
||||
h *= 0x01000193u;
|
||||
}
|
||||
|
||||
h &= 0xf0f0f0f0u;
|
||||
h |= 0x0a0a0a0au;
|
||||
|
||||
return h;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
int QUICConnectionHandler::send_version_negotiation(
|
||||
const UpstreamAddr *faddr, uint32_t version, const uint8_t *dcid,
|
||||
size_t dcidlen, const uint8_t *scid, size_t scidlen,
|
||||
const Address &remote_addr, const Address &local_addr) {
|
||||
std::array<uint32_t, 2> sv;
|
||||
|
||||
sv[0] = generate_reserved_version(remote_addr, version);
|
||||
sv[1] = NGTCP2_PROTO_VER_V1;
|
||||
|
||||
std::array<uint8_t, 1280> buf;
|
||||
|
||||
uint8_t rand_byte;
|
||||
util::random_bytes(&rand_byte, &rand_byte + 1, worker_->get_randgen());
|
||||
|
||||
auto nwrite = ngtcp2_pkt_write_version_negotiation(
|
||||
buf.data(), buf.size(), rand_byte, dcid, dcidlen, scid, scidlen,
|
||||
sv.data(), sv.size());
|
||||
if (nwrite < 0) {
|
||||
LOG(ERROR) << "ngtcp2_pkt_write_version_negotiation: "
|
||||
<< ngtcp2_strerror(nwrite);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return quic_send_packet(faddr, &remote_addr.su.sa, remote_addr.len,
|
||||
&local_addr.su.sa, local_addr.len, buf.data(), nwrite,
|
||||
0);
|
||||
}
|
||||
|
||||
} // namespace shrpx
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef SHRPX_QUIC_CONNECTION_HANDLER_H
|
||||
#define SHRPX_QUIC_CONNECTION_HANDLER_H
|
||||
|
||||
#include "shrpx.h"
|
||||
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
|
||||
#include "network.h"
|
||||
|
||||
using namespace nghttp2;
|
||||
|
||||
namespace shrpx {
|
||||
|
||||
struct UpstreamAddr;
|
||||
class ClientHandler;
|
||||
class Worker;
|
||||
|
||||
class QUICConnectionHandler {
|
||||
public:
|
||||
QUICConnectionHandler(Worker *worker);
|
||||
~QUICConnectionHandler();
|
||||
int handle_packet(const UpstreamAddr *faddr, const Address &remote_addr,
|
||||
const Address &local_addr, const uint8_t *data,
|
||||
size_t datalen);
|
||||
int send_version_negotiation(const UpstreamAddr *faddr, uint32_t version,
|
||||
const uint8_t *dcid, size_t dcidlen,
|
||||
const uint8_t *scid, size_t scidlen,
|
||||
const Address &remote_addr,
|
||||
const Address &local_addr);
|
||||
|
||||
private:
|
||||
Worker *worker_;
|
||||
std::unordered_map<std::string, std::shared_ptr<ClientHandler>> connections_;
|
||||
};
|
||||
|
||||
} // namespace shrpx
|
||||
|
||||
#endif // SHRPX_QUIC_CONNECTION_HANDLER_H
|
Loading…
Reference in New Issue