feat(tls): add a libssl TLS transport and an https:// HTTP/1.1 stack
HTTP/1.1 was plaintext-only, which left `https://` to either an HTTP/3
listener or a terminating proxy in front. Neither helps the callers this
stack exists for — curl scripts, CI tooling, old proxies — so wrap the
transport in libssl instead.
Two new partitions:
:Stream a ByteStream with per-call deadlines on both directions, plus
the plaintext socket implementation. The HTTP/1.1 client and
listener now hold a ByteStream& and never learn which
transport they have, which is what lets one code path serve
both schemes.
:TLS TLSContext/TLSStream over OpenSSL 3, with credentials for both
roles: chain and hostname verification on by default, private
trust anchors, client certificates, mutual TLS, ALPN, and an
in-process self-signed certificate for development.
Both descriptors go non-blocking and every read and write is driven by
poll() against a deadline. That is required for TLS — a blocking
descriptor cannot express a handshake timeout — and it means a plaintext
write can now time out too, instead of parking forever against a peer
that stopped reading.
ClientHTTP1 and ListenerHTTP1 gain credential-taking constructors; the
existing ones still speak http://. The listener handshakes on the
connection's own thread, so a peer that stalls mid-handshake costs one
thread rather than the accept loop, and a failed handshake is counted
rather than logged — on a public port it is ordinary traffic.
MessageParser gains SetDefaultScheme so origin-form targets report the
scheme the transport actually used; handlers shared with ListenerHTTP now
see the same "https" they would over HTTP/3.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
e1bb116b2d
commit
9c22cbe09e
11 changed files with 1299 additions and 99 deletions
21
project.cpp
21
project.cpp
|
|
@ -7,7 +7,7 @@ namespace fs = std::filesystem;
|
|||
using namespace Crafter;
|
||||
|
||||
extern "C" Configuration CrafterBuildProject(std::span<const std::string_view> args) {
|
||||
constexpr std::array<std::string_view, 13> networkInterfaces = {
|
||||
constexpr std::array<std::string_view, 15> networkInterfaces = {
|
||||
"interfaces/Crafter.Network",
|
||||
"interfaces/Crafter.Network-ClientTCP",
|
||||
"interfaces/Crafter.Network-ListenerTCP",
|
||||
|
|
@ -15,6 +15,8 @@ extern "C" Configuration CrafterBuildProject(std::span<const std::string_view> a
|
|||
"interfaces/Crafter.Network-ListenerHTTP",
|
||||
"interfaces/Crafter.Network-HTTP",
|
||||
"interfaces/Crafter.Network-HTTP1",
|
||||
"interfaces/Crafter.Network-Stream",
|
||||
"interfaces/Crafter.Network-TLS",
|
||||
"interfaces/Crafter.Network-ClientHTTP1",
|
||||
"interfaces/Crafter.Network-ListenerHTTP1",
|
||||
"interfaces/Crafter.Network-HTTP3",
|
||||
|
|
@ -72,11 +74,13 @@ extern "C" Configuration CrafterBuildProject(std::span<const std::string_view> a
|
|||
return cfg;
|
||||
}
|
||||
|
||||
constexpr std::array<std::string_view, 9> networkImplementations = {
|
||||
constexpr std::array<std::string_view, 11> networkImplementations = {
|
||||
"implementations/Crafter.Network-ClientTCP",
|
||||
"implementations/Crafter.Network-ListenerTCP",
|
||||
"implementations/Crafter.Network-ClientHTTP",
|
||||
"implementations/Crafter.Network-ListenerHTTP",
|
||||
"implementations/Crafter.Network-Stream",
|
||||
"implementations/Crafter.Network-TLS",
|
||||
"implementations/Crafter.Network-ClientHTTP1",
|
||||
"implementations/Crafter.Network-ListenerHTTP1",
|
||||
"implementations/Crafter.Network-ClientQUIC",
|
||||
|
|
@ -108,9 +112,18 @@ extern "C" Configuration CrafterBuildProject(std::span<const std::string_view> a
|
|||
// linker at the actual output location.
|
||||
msquic.libDirs = { "bin/Release" };
|
||||
msquic.libs = { "msquic" };
|
||||
std::array<fs::path, 13> ifaces;
|
||||
|
||||
// libssl/libcrypto — the TLS transport behind :TLS, i.e. https:// on the
|
||||
// HTTP/1.1 client and listener. A system package rather than a built
|
||||
// external: OpenSSL 3 is on every platform we target, and building it here
|
||||
// would mean shipping a second TLS stack alongside the one msquic already
|
||||
// links (quictls, which keeps its symbols to itself inside libmsquic.so).
|
||||
cfg.linkFlags.push_back("-lssl");
|
||||
cfg.linkFlags.push_back("-lcrypto");
|
||||
|
||||
std::array<fs::path, 15> ifaces;
|
||||
std::ranges::copy(networkInterfaces, ifaces.begin());
|
||||
std::array<fs::path, 9> impls;
|
||||
std::array<fs::path, 11> impls;
|
||||
std::ranges::copy(networkImplementations, impls.begin());
|
||||
cfg.GetInterfacesAndImplementations(ifaces, impls);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue