Files
AnyPS5/core/libs/tests/GuestHttp2.cpp
T
BunnyFlandClaude Opus 5.5 96603d9851 feat(libSceHttp2): bind cookie boxes to templates and requests
sceHttp2SetCookieBox and sceHttp2GetCookieBox follow an emulator run of
the firmware 13.42 module: templates and requests take a live box or 0,
other ids and unknown boxes return the invalid-id error, a new request
copies its template's box, and the getter checks a null output first.

A request with a bound box sends the box's matching cookies and stores
every Set-Cookie of the response in the box.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-27 15:59:15 +01:00

117 lines
6.0 KiB
C++

#include "prx/libkernel/include/Api.hpp"
#include "prx/libSceHttp2/include/Http2.hpp"
#include "SceTypes.hpp"
#include <cstdint>
#include <cstdlib>
#include <stdexcept>
#include <initializer_list>
static void Require(bool value) { if (!value) std::abort(); }
static constexpr int InvalidId = static_cast<int>(0x817B1100);
static constexpr int NotFound = static_cast<int>(0x817B1025);
static constexpr int NullPointer = static_cast<int>(0x817B1225);
template <typename TCall>
static bool Throws(TCall call) {
try { call(); } catch (const std::exception&) { return true; }
return false;
}
int main() {
Require(sceHttp2CreateCookieBox(0xffff) == static_cast<int>(0x817b121du));
const int box = sceHttp2CreateCookieBox(0x10000);
const int context = sceHttp2Init(1, 1, 0x10000, 4);
const int tmpl = sceHttp2CreateTemplate(context, "agent", 3, 0);
const int proxyTemplate = sceHttp2CreateTemplate(context, "agent", 3, 1);
Require(proxyTemplate > 0 && sceHttp2DeleteTemplate(proxyTemplate) == 0);
Require(Throws([&] { sceHttp2CreateTemplate(context, "agent", 3, 2); }));
Require(Throws([&] { sceHttp2CreateTemplate(context, "agent", 3, -1); }));
const int request = sceHttp2CreateRequestWithURL(tmpl, "GET", "https://localhost/", 0);
Require(box > 0 && context > 0 && tmpl > 0 && request > 0);
Require(sceHttp2SetCookieBox(tmpl, 0) == 0);
int bound = -7;
Require(sceHttp2GetCookieBox(tmpl, &bound) == NotFound && bound == 0);
Require(sceHttp2GetCookieBox(tmpl, nullptr) == NullPointer && sceHttp2GetCookieBox(context, nullptr) == NullPointer);
Require(sceHttp2SetCookieBox(tmpl, box) == 0);
bound = -7;
Require(sceHttp2GetCookieBox(tmpl, &bound) == 0 && bound == box);
bound = -7;
Require(sceHttp2GetCookieBox(request, &bound) == NotFound && bound == 0);
const int copied = sceHttp2CreateRequestWithURL(tmpl, "GET", "https://localhost/", 0);
bound = -7;
Require(sceHttp2GetCookieBox(copied, &bound) == 0 && bound == box);
Require(sceHttp2SetCookieBox(tmpl, 0) == 0);
bound = -7;
Require(sceHttp2GetCookieBox(tmpl, &bound) == NotFound && bound == 0);
bound = -7;
Require(sceHttp2GetCookieBox(copied, &bound) == 0 && bound == box);
for (const int id : {context, 0, -1, 0x7fffffff}) {
Require(sceHttp2SetCookieBox(id, box) == InvalidId && sceHttp2SetCookieBox(id, 0) == InvalidId);
bound = -7;
Require(sceHttp2GetCookieBox(id, &bound) == InvalidId && bound == 0);
}
const int deletedBox = sceHttp2CreateCookieBox(0x10000);
Require(deletedBox > 0 && sceHttp2DeleteCookieBox(deletedBox) == 0);
for (const int value : {-1, 0x7fffffff, context, tmpl, deletedBox}) Require(sceHttp2SetCookieBox(request, value) == InvalidId);
const int heldBox = sceHttp2CreateCookieBox(0x10000);
Require(heldBox > 0 && sceHttp2SetCookieBox(copied, heldBox) == 0 && sceHttp2DeleteCookieBox(heldBox) == 0);
bound = -7;
Require(sceHttp2GetCookieBox(copied, &bound) == 0 && bound == heldBox);
Require(sceHttp2SetCookieBox(copied, 0) == 0 && sceHttp2DeleteRequest(copied) == 0);
Require(sceHttp2CookieFlush(box) == 0);
Require(sceHttp2SetResolveRetry(tmpl, 0) == 0);
Require(Throws([&] { sceHttp2SetResolveRetry(tmpl, 3); }));
Require(sceHttp2SetRequestNoContentLength(request) == 0);
Require(Throws([&] { sceHttp2AddRequestHeader(request, "bad:name", "value", 0); }));
Require(Throws([&] { sceHttp2AddRequestHeader(request, "x-header", "value\r\ninjected: yes", 0); }));
Require(Throws([&] { sceHttp2AddRequestHeader(request, "keep-alive", "timeout=5", 0); }));
Require(sceHttp2AddRequestHeader(request, "connection", "keep-alive", 0) == static_cast<int>(0x804311FE));
Require(Throws([] { sceHttp2WebSocketSetPingInterval(0, 1000000); }));
for (const int id : {tmpl, request}) {
Require(Throws([&] { sceHttp2SetMinSslVersion(id, 0); }));
Require(sceHttp2SslEnableOption(id, 0x3d) == 0);
Require(sceHttp2SslDisableOption(id, 0x20) == 0);
Require(Throws([&] { sceHttp2SetMinSslVersion(id, 99); }));
Require(Throws([&] { sceHttp2SslEnableOption(id, 0x80000000); }));
}
for (const int id : {context, box}) {
Require(Throws([&] { sceHttp2SslEnableOption(id, 0x3d); }));
Require(Throws([&] { sceHttp2SslDisableOption(id, 0x20); }));
}
Http2MemoryPoolStats stats{1, 2, 3, 4};
Require(Throws([&] { sceHttp2GetMemoryPoolStats(context, &stats); }));
Require(stats.pool_size == 1 && stats.current_inuse_size == 3);
KernelEqueue eq = 0;
Require(sceKernelCreateEqueue(&eq, "http2-unsupported-async") == 0);
Require(sceKernelAddUserEventEdge(eq, request) == 0);
Http2AsyncOption option{};
option.equeue = eq;
option.user_event_id = request;
Require(Throws([&] { sceHttp2SendRequestAsync(request, nullptr, 0, &option, nullptr); }));
Http2AsyncResult result{};
result.req_id = 123;
std::uint32_t timeout = 500;
Require(Throws([&] { sceHttp2WaitAsync(request, &result, &timeout, nullptr); }));
Require(result.req_id == 123 && timeout == 500);
KernelEvent event{};
int count = 123;
const KernelUseconds poll = 0;
Require(sceKernelWaitEqueue(eq, &event, 1, &count, &poll) != 0);
Require(sceKernelDeleteEqueue(eq) == 0);
const int sibling = sceHttp2CreateTemplate(context, "other", 2, 0);
const int child = sceHttp2CreateRequestWithURL(sibling, "GET", "https://localhost/", 0);
Require(Throws([&] { sceHttp2SendRequest(child, nullptr, 0); }));
Require(sceHttp2DeleteTemplate(tmpl) == 0);
Require(sceHttp2SslEnableOption(sibling, 0) == 0);
Require(sceHttp2DeleteRequest(request) == InvalidId);
Require(sceHttp2SendRequest(request, nullptr, 0) == InvalidId);
Require(sceHttp2Term(context) == 0);
Require(sceHttp2DeleteRequest(child) == InvalidId);
Require(sceHttp2DeleteTemplate(sibling) == InvalidId);
Require(sceHttp2SetMinSslVersion(context, 0) == InvalidId);
Require(sceHttp2DeleteCookieBox(box) == 0);
Require(sceHttp2DeleteCookieBox(box) == InvalidId);
Require(sceHttp2Term(context) == InvalidId);
}