62 lines
2.2 KiB
C++
62 lines
2.2 KiB
C++
|
|
//SPDX-License-Identifier: LGPL-3.0-only
|
||
|
|
//SPDX-FileCopyrightText: Copyright (C) 2026 Catcrafts®
|
||
|
|
|
||
|
|
// A build with --no-quic leaves out the QUIC, HTTP/3 and WebTransport
|
||
|
|
// partitions, and msquic with them, for consumers that only need TCP or
|
||
|
|
// HTTP/1.1: building msquic means cloning it with its submodules and running
|
||
|
|
// its CMake build. This test is only built that way. It checks that msquic is
|
||
|
|
// not in the process and that TCP and HTTP/1.1 still work.
|
||
|
|
|
||
|
|
#include <arpa/inet.h>
|
||
|
|
#include <netinet/in.h>
|
||
|
|
#include <sys/socket.h>
|
||
|
|
#include <unistd.h>
|
||
|
|
#include <cstdlib>
|
||
|
|
|
||
|
|
import Crafter.Network;
|
||
|
|
import std;
|
||
|
|
using namespace Crafter;
|
||
|
|
|
||
|
|
namespace {
|
||
|
|
|
||
|
|
int failures = 0;
|
||
|
|
|
||
|
|
void Check(bool ok, std::string_view what) {
|
||
|
|
std::println("{} {}", ok ? "PASS" : "FAIL", what);
|
||
|
|
if (!ok) ++failures;
|
||
|
|
}
|
||
|
|
|
||
|
|
} // namespace
|
||
|
|
|
||
|
|
int main() {
|
||
|
|
std::ifstream maps("/proc/self/maps");
|
||
|
|
const std::string mapped((std::istreambuf_iterator<char>(maps)), std::istreambuf_iterator<char>());
|
||
|
|
Check(!mapped.empty() && mapped.find("msquic") == std::string::npos, "libmsquic is not loaded");
|
||
|
|
|
||
|
|
const int listener = socket(AF_INET, SOCK_STREAM, 0);
|
||
|
|
sockaddr_in address {};
|
||
|
|
address.sin_family = AF_INET;
|
||
|
|
address.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||
|
|
bind(listener, reinterpret_cast<sockaddr*>(&address), sizeof(address));
|
||
|
|
listen(listener, 1);
|
||
|
|
socklen_t length = sizeof(address);
|
||
|
|
getsockname(listener, reinterpret_cast<sockaddr*>(&address), &length);
|
||
|
|
|
||
|
|
ClientTCP client("127.0.0.1", ntohs(address.sin_port));
|
||
|
|
const int peer = accept(listener, nullptr, nullptr);
|
||
|
|
client.Send("ping", 4);
|
||
|
|
char echoed[4] {};
|
||
|
|
recv(peer, echoed, sizeof(echoed), MSG_WAITALL);
|
||
|
|
Check(std::string_view(echoed, 4) == "ping", "a ClientTCP still connects and sends over loopback");
|
||
|
|
|
||
|
|
// HTTP/1.1 stays in this build.
|
||
|
|
HTTP1::MessageParser parser(HTTP1::MessageKind::Request);
|
||
|
|
const std::string_view wire = "GET / HTTP/1.1\r\nHost: h\r\n\r\n";
|
||
|
|
parser.Feed(wire.data(), wire.size());
|
||
|
|
Check(parser.Complete() && parser.TakeRequest().path == "/", "the HTTP/1.1 parser is still there");
|
||
|
|
|
||
|
|
close(peer);
|
||
|
|
close(listener);
|
||
|
|
std::println("{}", failures == 0 ? "all checks passed" : "check(s) failed");
|
||
|
|
return failures == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
|
||
|
|
}
|