mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2026-06-02 04:38:28 -06:00
http part6 (#4460)
* added http* epolls * changed info to debug * one more info to debug * helper function
This commit is contained in:
parent
82beca2bbf
commit
00339cf010
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user