http part6 (#4460)

* added http* epolls

* changed info to debug

* one more info to debug

* helper function
This commit is contained in:
georgemoralis 2026-05-21 20:57:55 +03:00 committed by GitHub
parent 82beca2bbf
commit 00339cf010
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 356 additions and 42 deletions

View File

@ -3,8 +3,10 @@
#include <atomic>
#include <cctype>
#include <chrono>
#include <condition_variable>
#include <cstring>
#include <deque>
#include <memory>
#include <mutex>
#include <string>
@ -41,11 +43,21 @@ struct HttpSettings {
bool nonblock = false; // false = blocking (default), true = nonblock (EAGAIN)
};
struct Epoll {
int ctx_id = 0;
std::deque<OrbisHttpNBEvent> events;
std::condition_variable cv;
bool destroyed = false;
bool abort_requested = false;
};
struct HttpTemplate {
std::string user_agent;
int http_version;
int auto_proxy_conf;
HttpSettings settings;
int epoll_id = 0;
void* epoll_user_arg = nullptr;
};
struct HttpConnection {
@ -58,6 +70,8 @@ struct HttpConnection {
bool keep_alive = false; // Game-controlled keep-alive intent.
bool is_secure = false; // True if scheme == "https".
HttpSettings settings;
int epoll_id = 0;
void* epoll_user_arg = nullptr;
};
struct HttpResponse {
@ -82,6 +96,8 @@ struct HttpRequest {
HttpResponse res;
std::condition_variable cv; // waiters in blocking getters block on this
// notified when state leaves Sending.
int epoll_id = 0;
void* epoll_user_arg = nullptr;
};
struct HttpState {
@ -93,6 +109,7 @@ struct HttpState {
std::unordered_map<int, HttpTemplate> templates;
std::unordered_map<int, HttpConnection> connections;
std::unordered_map<int, std::shared_ptr<HttpRequest>> requests;
std::unordered_map<int, std::shared_ptr<Epoll>> epolls;
std::atomic<bool> shutting_down{false};
};
@ -119,6 +136,38 @@ static HttpSettings* ResolveSettings(int id, const char*& level) {
return nullptr;
}
static OrbisHttpEpollHandle EncodeEpollHandle(int id) {
return reinterpret_cast<OrbisHttpEpollHandle>(static_cast<intptr_t>(id));
}
static int DecodeEpollHandle(OrbisHttpEpollHandle eh) {
return static_cast<int>(reinterpret_cast<intptr_t>(eh));
}
// Resolve the (epoll_id*, epoll_user_arg*) pair on a template/connection/request
static bool ResolveEpollBinding(int id, int*& epoll_id_out, void**& user_arg_out,
const char*& level) {
if (auto it = g_state.templates.find(id); it != g_state.templates.end()) {
epoll_id_out = &it->second.epoll_id;
user_arg_out = &it->second.epoll_user_arg;
level = "template";
return true;
}
if (auto it = g_state.connections.find(id); it != g_state.connections.end()) {
epoll_id_out = &it->second.epoll_id;
user_arg_out = &it->second.epoll_user_arg;
level = "connection";
return true;
}
if (auto it = g_state.requests.find(id); it != g_state.requests.end()) {
epoll_id_out = &it->second->epoll_id;
user_arg_out = &it->second->epoll_user_arg;
level = "request";
return true;
}
return false;
}
// Populate a response object with the shape a transport-level failure produces:
// no status line, no headers, no body. Used by the no-internet path.
static void SynthesizeTransportFailureResponse(HttpResponse& res) {
@ -130,6 +179,40 @@ static void SynthesizeTransportFailureResponse(HttpResponse& res) {
res.all_headers_blob.clear();
}
// Map common HTTP status codes to strings for logs.
static std::string HttpStatusLabel(int sc) {
switch (sc) {
case 0:
return "0 (no status)";
case 200:
return "200 OK";
case 204:
return "204 No Content";
case 301:
return "301 Moved Permanently";
case 302:
return "302 Found";
case 304:
return "304 Not Modified";
case 400:
return "400 Bad Request";
case 401:
return "401 Unauthorized";
case 403:
return "403 Forbidden";
case 404:
return "404 Not Found";
case 500:
return "500 Internal Server Error";
case 502:
return "502 Bad Gateway";
case 503:
return "503 Service Unavailable";
default:
return std::to_string(sc);
}
}
static int WaitForResponseReady(HttpRequest& req, std::unique_lock<std::mutex>& lock) {
if (req.state == HttpRequestState::Aborted) {
return ORBIS_HTTP_ERROR_ABORTED;
@ -218,11 +301,6 @@ static bool ContainsCrLf(const char* s) {
// TODO/WIP/Stubbed functions
//***********************************
int PS4_SYSV_ABI sceHttpAbortWaitRequest(OrbisHttpEpollHandle eh) {
LOG_ERROR(Lib_Http, "(STUBBED) called eh={}", fmt::ptr(eh));
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttpAddCookie(int libhttpCtxId, const char* url, const char* cookie,
u64 cookieLength) {
LOG_ERROR(Lib_Http, "(STUBBED) called libhttpCtxId={}, url={}, cookie={}, cookieLength={}",
@ -321,6 +399,8 @@ int PS4_SYSV_ABI sceHttpCreateConnection(int tmplId, const char* serverName, con
conn.url = scheme_str + "://" + serverName + ":" + std::to_string(port);
if (auto tmpl_it = g_state.templates.find(tmplId); tmpl_it != g_state.templates.end()) {
conn.settings = tmpl_it->second.settings;
conn.epoll_id = tmpl_it->second.epoll_id;
conn.epoll_user_arg = tmpl_it->second.epoll_user_arg;
}
g_state.connections.emplace(conn_id, std::move(conn));
LOG_INFO(Lib_Http, "created connection connId={} url={}", conn_id,
@ -396,6 +476,8 @@ int PS4_SYSV_ABI sceHttpCreateConnectionWithURL(int tmplId, const char* url, boo
conn.is_secure = is_secure;
if (auto tmpl_it = g_state.templates.find(tmplId); tmpl_it != g_state.templates.end()) {
conn.settings = tmpl_it->second.settings;
conn.epoll_id = tmpl_it->second.epoll_id;
conn.epoll_user_arg = tmpl_it->second.epoll_user_arg;
}
g_state.connections.emplace(conn_id, std::move(conn));
LOG_INFO(Lib_Http, "created connection connId={} host={} port={} scheme={}", conn_id,
@ -403,11 +485,6 @@ int PS4_SYSV_ABI sceHttpCreateConnectionWithURL(int tmplId, const char* url, boo
return conn_id;
}
int PS4_SYSV_ABI sceHttpCreateEpoll(int libhttpCtxId, OrbisHttpEpollHandle* eh) {
LOG_ERROR(Lib_Http, "(STUBBED) called libhttpCtxId={}, eh={}", libhttpCtxId, fmt::ptr(eh));
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttpCreateRequest(int connId, int method, const char* path, u64 contentLength) {
LOG_INFO(Lib_Http, "called connId={}, method={}, path={}, contentLength={}", connId, method,
path ? path : "(null)", contentLength);
@ -473,6 +550,8 @@ int PS4_SYSV_ABI sceHttpCreateRequestWithURL(int connId, s32 method, const char*
req->url = url;
req->content_length = contentLength;
req->settings = conn_it->second.settings;
req->epoll_id = conn_it->second.epoll_id;
req->epoll_user_arg = conn_it->second.epoll_user_arg;
g_state.requests.emplace(req_id, std::move(req));
LOG_INFO(Lib_Http, "created request reqId={}", req_id);
return req_id;
@ -541,11 +620,6 @@ int PS4_SYSV_ABI sceHttpDbgShowStat() {
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttpDestroyEpoll(int libhttpCtxId, OrbisHttpEpollHandle eh) {
LOG_ERROR(Lib_Http, "(STUBBED) called libhttpCtxId={}, eh={}", libhttpCtxId, fmt::ptr(eh));
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttpGetAcceptEncodingGZIPEnabled(int id, int* isEnable) {
LOG_ERROR(Lib_Http, "(STUBBED) called id={}, isEnable={}", id, fmt::ptr(isEnable));
return ORBIS_OK;
@ -582,12 +656,6 @@ int PS4_SYSV_ABI sceHttpGetCookieStats(int libhttpCtxId, OrbisHttpCookieStats* s
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttpGetEpoll(int id, OrbisHttpEpollHandle* eh, void** userArg) {
LOG_ERROR(Lib_Http, "(STUBBED) called id={}, eh={}, userArg={}", id, fmt::ptr(eh),
fmt::ptr(userArg));
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttpGetEpollId() {
LOG_ERROR(Lib_Http, "(STUBBED) called");
return ORBIS_OK;
@ -660,7 +728,7 @@ int PS4_SYSV_ABI sceHttpSendRequest(int reqId, const void* postData, u64 size) {
LOG_ERROR(Lib_Http, "Request was aborted (reqId={})", reqId);
return ORBIS_HTTP_ERROR_ABORTED;
}
// Created -> Sending. Worker thread will move to Sent.
// Created to Sending. Worker thread will move to Sent.
req.state = HttpRequestState::Sending;
req_ptr = it->second;
}
@ -689,6 +757,24 @@ int PS4_SYSV_ABI sceHttpSendRequest(int reqId, const void* postData, u64 size) {
LOG_INFO(Lib_Http, "(TRANSPORT FAIL) reqId={} -> 0 (body 0 bytes, errno={:#x})", reqId,
static_cast<u32>(req_ptr->last_errno));
req_ptr->cv.notify_all();
// If this request is bound to an epoll, push a failure-shaped event so
// sceHttpWaitRequest callers see the completion (with errored bits).
if (req_ptr->epoll_id != 0) {
auto epoll_it = g_state.epolls.find(req_ptr->epoll_id);
if (epoll_it != g_state.epolls.end() && !epoll_it->second->destroyed) {
constexpr u32 FailureEventBits =
ORBIS_HTTP_NB_EVENT_RESOLVER_ERR | ORBIS_HTTP_NB_EVENT_HUP;
OrbisHttpNBEvent ev{};
ev.events = FailureEventBits;
ev.eventDetail = FailureEventBits;
ev.id = reqId;
ev.userArg = req_ptr->epoll_user_arg;
epoll_it->second->events.push_back(ev);
epoll_it->second->cv.notify_all();
LOG_DEBUG(Lib_Http, "pushed failure epoll event for reqId={} on epoll={}", reqId,
req_ptr->epoll_id);
}
}
}).detach();
return ORBIS_OK;
@ -765,12 +851,6 @@ int PS4_SYSV_ABI sceHttpSetDelayBuildRequestEnabled(int id, int isEnable) {
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttpSetEpoll(int id, OrbisHttpEpollHandle eh, void* userArg) {
LOG_ERROR(Lib_Http, "(STUBBED) called id={}, eh={}, userArg={}", id, fmt::ptr(eh),
fmt::ptr(userArg));
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttpSetEpollId() {
LOG_ERROR(Lib_Http, "(STUBBED) called");
return ORBIS_OK;
@ -903,9 +983,14 @@ int PS4_SYSV_ABI sceHttpTerm(int libhttpCtxId) {
req_ptr->state = HttpRequestState::Aborted;
req_ptr->cv.notify_all(); // wake blocked waiters before wiping the map
}
for (auto& [id, epoll_ptr] : g_state.epolls) {
epoll_ptr->destroyed = true;
epoll_ptr->cv.notify_all(); // wake any sceHttpWaitRequest blocker
}
g_state.requests.clear();
g_state.connections.clear();
g_state.templates.clear();
g_state.epolls.clear();
g_state.inited = false;
} else {
LOG_INFO(Lib_Http, "ctxId={} terminated, {} contexts still active", libhttpCtxId,
@ -914,16 +999,85 @@ int PS4_SYSV_ABI sceHttpTerm(int libhttpCtxId) {
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttpUnsetEpoll(int id) {
LOG_ERROR(Lib_Http, "(STUBBED) called id={}", id);
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttpWaitRequest(OrbisHttpEpollHandle eh, OrbisHttpNBEvent* nbev, int maxevents,
int timeout) {
LOG_ERROR(Lib_Http, "(STUBBED) called eh={}, nbev={}, maxevents={}, timeout={}", fmt::ptr(eh),
LOG_DEBUG(Lib_Http, "called eh={}, nbev={}, maxevents={}, timeout={}", fmt::ptr(eh),
fmt::ptr(nbev), maxevents, timeout);
return ORBIS_OK;
std::unique_lock<std::mutex> lock(g_state.m_mutex);
if (!g_state.inited) {
LOG_ERROR(Lib_Http, "Not initialized");
return ORBIS_HTTP_ERROR_BEFORE_INIT;
}
if (maxevents <= 0 || !eh || !nbev) {
LOG_ERROR(Lib_Http, "InvalidValue (maxevents={}, eh={}, nbev={})", maxevents, fmt::ptr(eh),
fmt::ptr(nbev));
return ORBIS_HTTP_ERROR_INVALID_VALUE;
}
int epoll_id = DecodeEpollHandle(eh);
auto it = g_state.epolls.find(epoll_id);
if (it == g_state.epolls.end()) {
LOG_ERROR(Lib_Http, "Invalid epoll handle (id={})", epoll_id);
return ORBIS_HTTP_ERROR_INVALID_ID;
}
auto epoll_ptr = it->second;
// if the epoll's abort flag is
// already set, return Aborted immediately without draining or waiting.
if (epoll_ptr->abort_requested) {
LOG_INFO(Lib_Http, "epoll id={} already aborted, returning ABORTED", epoll_id);
return ORBIS_HTTP_ERROR_ABORTED;
}
auto drain_into_output = [&]() -> int {
int count = 0;
while (count < maxevents && !epoll_ptr->events.empty()) {
nbev[count] = epoll_ptr->events.front();
epoll_ptr->events.pop_front();
++count;
}
return count;
};
// Events already queued: drain and return immediately.
int already = drain_into_output();
if (already > 0) {
LOG_INFO(Lib_Http, "epoll id={} returned {} events (no wait)", epoll_id, already);
return already;
}
// No events queued. Behavior depends on timeout.
if (timeout == 0) {
// Poll mode: don't wait, just return 0.
return 0;
}
if (epoll_ptr->destroyed || g_state.shutting_down.load()) {
// Don't wait if we already know we'd be woken right away.
return 0;
}
auto predicate = [&]() {
return !epoll_ptr->events.empty() || epoll_ptr->destroyed || epoll_ptr->abort_requested ||
g_state.shutting_down.load();
};
if (timeout < 0) {
epoll_ptr->cv.wait(lock, predicate);
} else {
epoll_ptr->cv.wait_for(lock, std::chrono::microseconds(timeout), predicate);
}
// If AbortWaitRequest fired during the wait, return ABORTED
if (epoll_ptr->abort_requested) {
LOG_INFO(Lib_Http, "epoll id={} woken by abort, returning ABORTED", epoll_id);
return ORBIS_HTTP_ERROR_ABORTED;
}
int count = drain_into_output();
if (epoll_ptr->destroyed) {
LOG_INFO(Lib_Http, "epoll id={} woken because destroyed; returning {} events", epoll_id,
count);
} else {
LOG_INFO(Lib_Http, "epoll id={} returned {} events after wait", epoll_id, count);
}
return count;
}
int PS4_SYSV_ABI sceHttpUriCopy() {
@ -934,6 +1088,157 @@ int PS4_SYSV_ABI sceHttpUriCopy() {
//***********************************
// Non-blocking processing functions
//***********************************
int PS4_SYSV_ABI sceHttpCreateEpoll(int libhttpCtxId, OrbisHttpEpollHandle* eh) {
LOG_INFO(Lib_Http, "called libhttpCtxId={}, eh={}", libhttpCtxId, fmt::ptr(eh));
std::lock_guard<std::mutex> lock(g_state.m_mutex);
if (!g_state.inited) {
LOG_ERROR(Lib_Http, "Not initialized");
return ORBIS_HTTP_ERROR_BEFORE_INIT;
}
if (!g_state.active_contexts.contains(libhttpCtxId)) {
LOG_ERROR(Lib_Http, "Invalid libhttpCtxId={}", libhttpCtxId);
return ORBIS_HTTP_ERROR_INVALID_ID;
}
if (!eh) {
LOG_ERROR(Lib_Http, "eh output pointer is null");
return ORBIS_HTTP_ERROR_INVALID_VALUE;
}
int epoll_id = ++g_state.next_obj_id;
auto epoll = std::make_shared<Epoll>();
epoll->ctx_id = libhttpCtxId;
g_state.epolls.emplace(epoll_id, std::move(epoll));
*eh = EncodeEpollHandle(epoll_id);
LOG_INFO(Lib_Http, "created epoll id={} (handle={})", epoll_id, fmt::ptr(*eh));
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttpDestroyEpoll(int libhttpCtxId, OrbisHttpEpollHandle eh) {
LOG_INFO(Lib_Http, "called libhttpCtxId={}, eh={}", libhttpCtxId, fmt::ptr(eh));
std::lock_guard<std::mutex> lock(g_state.m_mutex);
if (!g_state.inited) {
LOG_ERROR(Lib_Http, "Not initialized");
return ORBIS_HTTP_ERROR_BEFORE_INIT;
}
if (!g_state.active_contexts.contains(libhttpCtxId)) {
LOG_ERROR(Lib_Http, "Invalid libhttpCtxId={}", libhttpCtxId);
return ORBIS_HTTP_ERROR_INVALID_ID;
}
if (!eh) {
LOG_ERROR(Lib_Http, "eh is null");
return ORBIS_HTTP_ERROR_INVALID_VALUE;
}
int epoll_id = DecodeEpollHandle(eh);
auto it = g_state.epolls.find(epoll_id);
if (it == g_state.epolls.end()) {
LOG_ERROR(Lib_Http, "Invalid epoll handle (id={})", epoll_id);
return ORBIS_HTTP_ERROR_INVALID_ID;
}
if (it->second->ctx_id != libhttpCtxId) {
LOG_ERROR(Lib_Http, "ctxId mismatch: epoll ctx_id={} but caller passed {}",
it->second->ctx_id, libhttpCtxId);
}
auto epoll_ptr = it->second;
epoll_ptr->destroyed = true;
epoll_ptr->cv.notify_all();
g_state.epolls.erase(it);
LOG_INFO(Lib_Http, "destroyed epoll id={}", epoll_id);
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttpGetEpoll(int id, OrbisHttpEpollHandle* eh, void** userArg) {
LOG_INFO(Lib_Http, "called id={}, eh={}, userArg={}", id, fmt::ptr(eh), fmt::ptr(userArg));
std::lock_guard<std::mutex> lock(g_state.m_mutex);
if (!g_state.inited) {
LOG_ERROR(Lib_Http, "Not initialized");
return ORBIS_HTTP_ERROR_BEFORE_INIT;
}
if (!eh) {
LOG_ERROR(Lib_Http, "eh output pointer is null");
return ORBIS_HTTP_ERROR_INVALID_VALUE;
}
int* src_epoll_id = nullptr;
void** src_user_arg = nullptr;
const char* level = "";
if (!ResolveEpollBinding(id, src_epoll_id, src_user_arg, level)) {
LOG_ERROR(Lib_Http, "Invalid id={} (not a template, connection, or request)", id);
return ORBIS_HTTP_ERROR_INVALID_ID;
}
*eh = EncodeEpollHandle(*src_epoll_id);
if (userArg) {
*userArg = *src_user_arg;
}
LOG_INFO(Lib_Http, "got epoll id={} userArg={} from {} id={}", *src_epoll_id,
fmt::ptr(*src_user_arg), level, id);
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttpSetEpoll(int id, OrbisHttpEpollHandle eh, void* userArg) {
LOG_INFO(Lib_Http, "called id={}, eh={}, userArg={}", id, fmt::ptr(eh), fmt::ptr(userArg));
std::lock_guard<std::mutex> lock(g_state.m_mutex);
if (!g_state.inited) {
LOG_ERROR(Lib_Http, "Not initialized");
return ORBIS_HTTP_ERROR_BEFORE_INIT;
}
int epoll_id = DecodeEpollHandle(eh);
if (!g_state.epolls.contains(epoll_id)) {
LOG_ERROR(Lib_Http, "Invalid epoll handle (id={})", epoll_id);
return ORBIS_HTTP_ERROR_INVALID_ID;
}
int* target_epoll_id = nullptr;
void** target_user_arg = nullptr;
const char* level = "";
if (!ResolveEpollBinding(id, target_epoll_id, target_user_arg, level)) {
LOG_ERROR(Lib_Http, "Invalid id={} (not a template, connection, or request)", id);
return ORBIS_HTTP_ERROR_INVALID_ID;
}
*target_epoll_id = epoll_id;
*target_user_arg = userArg;
LOG_INFO(Lib_Http, "set epoll={} userArg={} at {} level (id={})", epoll_id, fmt::ptr(userArg),
level, id);
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttpUnsetEpoll(int id) {
LOG_INFO(Lib_Http, "called id={}", id);
std::lock_guard<std::mutex> lock(g_state.m_mutex);
if (!g_state.inited) {
LOG_ERROR(Lib_Http, "Not initialized");
return ORBIS_HTTP_ERROR_BEFORE_INIT;
}
auto it = g_state.requests.find(id);
if (it == g_state.requests.end()) {
LOG_ERROR(Lib_Http, "Invalid reqId={}", id);
return ORBIS_HTTP_ERROR_INVALID_ID;
}
it->second->epoll_id = 0;
it->second->epoll_user_arg = nullptr;
LOG_INFO(Lib_Http, "cleared epoll binding from reqId={}", id);
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttpAbortWaitRequest(OrbisHttpEpollHandle eh) {
LOG_INFO(Lib_Http, "called eh={}", fmt::ptr(eh));
std::lock_guard<std::mutex> lock(g_state.m_mutex);
if (!g_state.inited) {
LOG_ERROR(Lib_Http, "Not initialized");
return ORBIS_HTTP_ERROR_BEFORE_INIT;
}
if (!eh) {
LOG_ERROR(Lib_Http, "eh is null");
return ORBIS_HTTP_ERROR_INVALID_VALUE;
}
int epoll_id = DecodeEpollHandle(eh);
auto it = g_state.epolls.find(epoll_id);
if (it == g_state.epolls.end()) {
LOG_ERROR(Lib_Http, "Invalid epoll handle (id={})", epoll_id);
return ORBIS_HTTP_ERROR_INVALID_ID;
}
it->second->abort_requested = true;
it->second->cv.notify_all();
LOG_INFO(Lib_Http, "epoll id={} abort requested", epoll_id);
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttpGetNonblock(int id, int* isEnable) {
LOG_INFO(Lib_Http, "called id={}, isEnable={}", id, fmt::ptr(isEnable));
std::lock_guard<std::mutex> lock(g_state.m_mutex);
@ -1224,7 +1529,7 @@ int PS4_SYSV_ABI sceHttpGetResponseContentLength(int reqId, int* result, u64* co
}
int PS4_SYSV_ABI sceHttpGetStatusCode(int reqId, int* statusCode) {
LOG_INFO(Lib_Http, "called reqId={}, statusCode={}", reqId, fmt::ptr(statusCode));
LOG_INFO(Lib_Http, "called reqId={}", reqId);
std::unique_lock<std::mutex> lock(g_state.m_mutex);
if (!g_state.inited) {
LOG_ERROR(Lib_Http, "Not initialized");
@ -1256,7 +1561,7 @@ int PS4_SYSV_ABI sceHttpGetStatusCode(int reqId, int* statusCode) {
return ORBIS_HTTP_ERROR_BEFORE_SEND;
}
*statusCode = req.res.status_code;
LOG_INFO(Lib_Http, "reqId={} status={}", reqId, req.res.status_code);
LOG_INFO(Lib_Http, "reqId={} status={}", reqId, HttpStatusLabel(req.res.status_code));
return ORBIS_OK;
}

View File

@ -13,6 +13,15 @@ class SymbolsResolver;
namespace Libraries::Http {
enum OrbisHttpNBEvents : u32 {
ORBIS_HTTP_NB_EVENT_IN = 0x00000001U, // Ready to receive (response data available).
ORBIS_HTTP_NB_EVENT_OUT = 0x00000002U, // Ready to send.
ORBIS_HTTP_NB_EVENT_SOCK_ERR = 0x00000008U, // Socket-level error during send/recv.
ORBIS_HTTP_NB_EVENT_HUP = 0x00000010U, // Request interrupted by the application.
ORBIS_HTTP_NB_EVENT_RESOLVED = 0x00010000U, // DNS resolution completed.
ORBIS_HTTP_NB_EVENT_RESOLVER_ERR = 0x00020000U, // DNS resolution failed.
};
enum OrbisHttpsFlags : u32 {
ORBIS_HTTPS_FLAG_SERVER_VERIFY = 0x01,
ORBIS_HTTPS_FLAG_CLIENT_VERIFY = 0x02,
@ -129,7 +138,6 @@ using OrbisHttpsCallback = int(PS4_SYSV_ABI*)(int libsslCtxId, u32 verifyErr, vo
using OrbisHttpsCaList = Libraries::Ssl::OrbisSslCaList;
// Functions
int PS4_SYSV_ABI sceHttpAbortWaitRequest(OrbisHttpEpollHandle eh);
int PS4_SYSV_ABI sceHttpAddCookie(int libhttpCtxId, const char* url, const char* cookie,
u64 cookieLength);
int PS4_SYSV_ABI sceHttpAddQuery();
@ -146,7 +154,6 @@ int PS4_SYSV_ABI sceHttpCookieImport(int libhttpCtxId, const void* buffer, u64 b
int PS4_SYSV_ABI sceHttpCreateConnection(int tmplId, const char* serverName, const char* scheme,
u16 port, int isEnableKeepalive);
int PS4_SYSV_ABI sceHttpCreateConnectionWithURL(int tmplId, const char* url, bool enableKeepalive);
int PS4_SYSV_ABI sceHttpCreateEpoll(int libhttpCtxId, OrbisHttpEpollHandle* eh);
int PS4_SYSV_ABI sceHttpCreateRequest(int connId, int method, const char* path, u64 contentLength);
int PS4_SYSV_ABI sceHttpCreateRequestWithURL(int connId, s32 method, const char* url,
u64 contentLength);
@ -160,7 +167,6 @@ int PS4_SYSV_ABI sceHttpDbgShowConnectionStat();
int PS4_SYSV_ABI sceHttpDbgShowMemoryPoolStat();
int PS4_SYSV_ABI sceHttpDbgShowRequestStat();
int PS4_SYSV_ABI sceHttpDbgShowStat();
int PS4_SYSV_ABI sceHttpDestroyEpoll(int libhttpCtxId, OrbisHttpEpollHandle eh);
int PS4_SYSV_ABI sceHttpGetAcceptEncodingGZIPEnabled(int id, int* isEnable);
int PS4_SYSV_ABI sceHttpGetAuthEnabled(int id, int* isEnable);
int PS4_SYSV_ABI sceHttpGetConnectionStat();
@ -168,7 +174,6 @@ int PS4_SYSV_ABI sceHttpGetCookie(int libhttpCtxId, const char* url, char* cooki
u64 prepared, int isSecure);
int PS4_SYSV_ABI sceHttpGetCookieEnabled(int id, int* isEnable);
int PS4_SYSV_ABI sceHttpGetCookieStats(int libhttpCtxId, OrbisHttpCookieStats* stats);
int PS4_SYSV_ABI sceHttpGetEpoll(int id, OrbisHttpEpollHandle* eh, void** userArg);
int PS4_SYSV_ABI sceHttpGetEpollId();
int PS4_SYSV_ABI sceHttpGetMemoryPoolStats(int libhttpCtxId, OrbisHttpMemoryPoolStats* currentStat);
int PS4_SYSV_ABI sceHttpGetRegisteredCtxIds();
@ -218,13 +223,17 @@ int PS4_SYSV_ABI sceHttpsSetSslCallback(int id, OrbisHttpsCallback cbfunc, void*
int PS4_SYSV_ABI sceHttpsSetSslVersion(int id, int version);
int PS4_SYSV_ABI sceHttpsUnloadCert(int libhttpCtxId);
int PS4_SYSV_ABI sceHttpTerm(int libhttpCtxId);
int PS4_SYSV_ABI sceHttpUnsetEpoll(int id);
int PS4_SYSV_ABI sceHttpWaitRequest(OrbisHttpEpollHandle eh, OrbisHttpNBEvent* nbev, int maxevents,
int timeout);
int PS4_SYSV_ABI sceHttpUriCopy();
//***********************************
// Non-blocking processing functions
//***********************************
int PS4_SYSV_ABI sceHttpCreateEpoll(int libhttpCtxId, OrbisHttpEpollHandle* eh);
int PS4_SYSV_ABI sceHttpDestroyEpoll(int libhttpCtxId, OrbisHttpEpollHandle eh);
int PS4_SYSV_ABI sceHttpGetEpoll(int id, OrbisHttpEpollHandle* eh, void** userArg);
int PS4_SYSV_ABI sceHttpUnsetEpoll(int id);
int PS4_SYSV_ABI sceHttpAbortWaitRequest(OrbisHttpEpollHandle eh);
int PS4_SYSV_ABI sceHttpGetNonblock(int id, int* isEnable);
int PS4_SYSV_ABI sceHttpSetNonblock(int id, int isEnable);
int PS4_SYSV_ABI sceHttpTryGetNonblock(int id, int* isEnable);