mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2026-06-02 12:45:46 -06:00
http part5 (#4453)
* added async state sending support * typo * implemented blocking * clang is not my friend * fixed stephen's review * code organize / nothing changed
This commit is contained in:
parent
03ebac577b
commit
82beca2bbf
@ -3,16 +3,19 @@
|
||||
|
||||
#include <atomic>
|
||||
#include <cctype>
|
||||
#include <condition_variable>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <thread>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "core/emulator_settings.h"
|
||||
#include "core/libraries/error_codes.h"
|
||||
#include "core/libraries/kernel/orbis_error.h"
|
||||
#include "core/libraries/libs.h"
|
||||
@ -35,6 +38,7 @@ struct HttpSettings {
|
||||
bool auto_redirect = true;
|
||||
bool inflate_gzip = true;
|
||||
u32 ssl_flags = ORBIS_HTTPS_FLAG_SDK_DEFAULT; // SSL flag mask. Bitmask of OrbisHttpsFlags.
|
||||
bool nonblock = false; // false = blocking (default), true = nonblock (EAGAIN)
|
||||
};
|
||||
|
||||
struct HttpTemplate {
|
||||
@ -56,6 +60,15 @@ struct HttpConnection {
|
||||
HttpSettings settings;
|
||||
};
|
||||
|
||||
struct HttpResponse {
|
||||
int status_code = 0;
|
||||
u64 content_length = 0;
|
||||
int content_length_result = ORBIS_HTTP_ERROR_NO_CONTENT_LENGTH;
|
||||
std::vector<u8> body;
|
||||
u64 read_cursor = 0;
|
||||
std::string all_headers_blob; // Pre-formatted "Name: Value\r\n..." string.
|
||||
};
|
||||
|
||||
struct HttpRequest {
|
||||
int conn_id = 0;
|
||||
int method = 0;
|
||||
@ -66,6 +79,9 @@ struct HttpRequest {
|
||||
bool deleted = false;
|
||||
s32 last_errno = 0; // populated by SendRequest, read by GetLastErrno
|
||||
HttpSettings settings;
|
||||
HttpResponse res;
|
||||
std::condition_variable cv; // waiters in blocking getters block on this
|
||||
// notified when state leaves Sending.
|
||||
};
|
||||
|
||||
struct HttpState {
|
||||
@ -82,6 +98,10 @@ struct HttpState {
|
||||
|
||||
static HttpState g_state;
|
||||
|
||||
//***********************************
|
||||
// Helper functions
|
||||
//***********************************
|
||||
|
||||
static HttpSettings* ResolveSettings(int id, const char*& level) {
|
||||
if (auto it = g_state.templates.find(id); it != g_state.templates.end()) {
|
||||
level = "template";
|
||||
@ -99,6 +119,40 @@ static HttpSettings* ResolveSettings(int id, const char*& level) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// 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) {
|
||||
res.status_code = 0;
|
||||
res.content_length = 0;
|
||||
res.content_length_result = ORBIS_HTTP_ERROR_NO_CONTENT_LENGTH;
|
||||
res.body.clear();
|
||||
res.read_cursor = 0;
|
||||
res.all_headers_blob.clear();
|
||||
}
|
||||
|
||||
static int WaitForResponseReady(HttpRequest& req, std::unique_lock<std::mutex>& lock) {
|
||||
if (req.state == HttpRequestState::Aborted) {
|
||||
return ORBIS_HTTP_ERROR_ABORTED;
|
||||
}
|
||||
if (req.state == HttpRequestState::Created) {
|
||||
return ORBIS_HTTP_ERROR_BEFORE_SEND;
|
||||
}
|
||||
if (req.state == HttpRequestState::Sent) {
|
||||
return ORBIS_OK;
|
||||
}
|
||||
// state == Sending. Honor nonblock: return EAGAIN instead of blocking.
|
||||
if (req.settings.nonblock) {
|
||||
return ORBIS_HTTP_ERROR_EAGAIN;
|
||||
}
|
||||
req.cv.wait(lock, [&req]() {
|
||||
return req.state != HttpRequestState::Sending || g_state.shutting_down.load();
|
||||
});
|
||||
if (g_state.shutting_down.load() || req.state == HttpRequestState::Aborted) {
|
||||
return ORBIS_HTTP_ERROR_ABORTED;
|
||||
}
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
void NormalizeAndAppendPath(char* dest, char* src) {
|
||||
char* lastSlash;
|
||||
u64 length;
|
||||
@ -160,15 +214,9 @@ static bool ContainsCrLf(const char* s) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttpAbortRequest(int reqId) {
|
||||
LOG_ERROR(Lib_Http, "(STUBBED) called reqId={}", reqId);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttpAbortRequestForce(int reqId) {
|
||||
LOG_ERROR(Lib_Http, "(STUBBED) called reqId={}", reqId);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
//***********************************
|
||||
// TODO/WIP/Stubbed functions
|
||||
//***********************************
|
||||
|
||||
int PS4_SYSV_ABI sceHttpAbortWaitRequest(OrbisHttpEpollHandle eh) {
|
||||
LOG_ERROR(Lib_Http, "(STUBBED) called eh={}", fmt::ptr(eh));
|
||||
@ -493,53 +541,6 @@ int PS4_SYSV_ABI sceHttpDbgShowStat() {
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttpDeleteConnection(int connId) {
|
||||
LOG_INFO(Lib_Http, "called connId={}", connId);
|
||||
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.connections.erase(connId) == 0) {
|
||||
LOG_ERROR(Lib_Http, "Invalid connId={}", connId);
|
||||
return ORBIS_HTTP_ERROR_INVALID_ID;
|
||||
}
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttpDeleteRequest(int reqId) {
|
||||
LOG_INFO(Lib_Http, "called reqId={}", reqId);
|
||||
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(reqId);
|
||||
if (it == g_state.requests.end()) {
|
||||
LOG_ERROR(Lib_Http, "Invalid reqId={}", reqId);
|
||||
return ORBIS_HTTP_ERROR_INVALID_ID;
|
||||
}
|
||||
auto req_ptr = it->second;
|
||||
req_ptr->deleted = true;
|
||||
req_ptr->state = HttpRequestState::Aborted;
|
||||
g_state.requests.erase(it);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttpDeleteTemplate(int tmplId) {
|
||||
LOG_INFO(Lib_Http, "called tmplId={}", tmplId);
|
||||
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.templates.erase(tmplId) == 0) {
|
||||
LOG_ERROR(Lib_Http, "Invalid tmplId={}", tmplId);
|
||||
return ORBIS_HTTP_ERROR_INVALID_ID;
|
||||
}
|
||||
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;
|
||||
@ -550,12 +551,6 @@ int PS4_SYSV_ABI sceHttpGetAcceptEncodingGZIPEnabled(int id, int* isEnable) {
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttpGetAllResponseHeaders(int reqId, char** header, u64* headerSize) {
|
||||
LOG_ERROR(Lib_Http, "(STUBBED) called reqId={}, header={}, headerSize={}", reqId,
|
||||
fmt::ptr(header), fmt::ptr(headerSize));
|
||||
return ORBIS_FAIL;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttpGetAuthEnabled(int id, int* isEnable) {
|
||||
LOG_ERROR(Lib_Http, "(STUBBED) called id={}, isEnable={}", id, fmt::ptr(isEnable));
|
||||
return ORBIS_OK;
|
||||
@ -605,57 +600,11 @@ int PS4_SYSV_ABI sceHttpGetMemoryPoolStats(int libhttpCtxId,
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttpGetNonblock(int id, int* isEnable) {
|
||||
LOG_ERROR(Lib_Http, "(STUBBED) called id={}, isEnable={}", id, fmt::ptr(isEnable));
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttpGetRegisteredCtxIds() {
|
||||
LOG_ERROR(Lib_Http, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttpGetResponseContentLength(int reqId, int* result, u64* contentLength) {
|
||||
LOG_ERROR(Lib_Http, "(STUBBED) called reqId={}, result={}, contentLength={}", reqId,
|
||||
fmt::ptr(result), fmt::ptr(contentLength));
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttpGetStatusCode(int reqId, int* statusCode) {
|
||||
LOG_INFO(Lib_Http, "(STUBBED) called reqId={}, statusCode={}", reqId, fmt::ptr(statusCode));
|
||||
#if 0
|
||||
if (!g_state.inited)
|
||||
return ORBIS_HTTP_ERROR_BEFORE_INIT;
|
||||
|
||||
if (statusCode == nullptr)
|
||||
return ORBIS_HTTP_ERROR_INVALID_VALUE;
|
||||
|
||||
int ret = 0;
|
||||
// Lookup HttpRequestInternal by reqId
|
||||
HttpRequestInternal* request = nullptr;
|
||||
ret = HttpRequestInternal_Acquire(&request, reqId);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
request->m_mutex.lock();
|
||||
if (request->state > 0x11) {
|
||||
if (request->state == 0x16) {
|
||||
ret = request->errorCode;
|
||||
} else {
|
||||
*statusCode = request->httpStatusCode;
|
||||
ret = 0;
|
||||
}
|
||||
} else {
|
||||
ret = ORBIS_HTTP_ERROR_BEFORE_SEND;
|
||||
}
|
||||
request->m_mutex.unlock();
|
||||
HttpRequestInternal_Release(request);
|
||||
|
||||
return ret;
|
||||
#else
|
||||
return ORBIS_HTTP_ERROR_BEFORE_SEND;
|
||||
#endif
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttpInit(int libnetMemId, int libsslCtxId, u64 poolSize) {
|
||||
LOG_INFO(Lib_Http, "called libnetMemId={}, libsslCtxId={}, poolSize={}", libnetMemId,
|
||||
libsslCtxId, poolSize);
|
||||
@ -673,11 +622,6 @@ int PS4_SYSV_ABI sceHttpInit(int libnetMemId, int libsslCtxId, u64 poolSize) {
|
||||
return ctx_id;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttpReadData(s32 reqId, void* data, u64 size) {
|
||||
LOG_ERROR(Lib_Http, "(STUBBED) called reqId={}, data={}, size={}", reqId, fmt::ptr(data), size);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttpRedirectCacheFlush(int libhttpCtxId) {
|
||||
LOG_ERROR(Lib_Http, "(STUBBED) called libhttpCtxId={}", libhttpCtxId);
|
||||
return ORBIS_OK;
|
||||
@ -695,31 +639,59 @@ int PS4_SYSV_ABI sceHttpRequestGetAllHeaders() {
|
||||
|
||||
int PS4_SYSV_ABI sceHttpSendRequest(int reqId, const void* postData, u64 size) {
|
||||
LOG_INFO(Lib_Http, "called reqId={}, postData={}, size={}", reqId, fmt::ptr(postData), size);
|
||||
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(reqId);
|
||||
if (it == g_state.requests.end()) {
|
||||
LOG_ERROR(Lib_Http, "Invalid reqId={}", reqId);
|
||||
return ORBIS_HTTP_ERROR_INVALID_ID;
|
||||
}
|
||||
auto& req = *it->second;
|
||||
if (req.state == HttpRequestState::Sent) {
|
||||
LOG_ERROR(Lib_Http, "Request already sent (reqId={})", reqId);
|
||||
return ORBIS_HTTP_ERROR_AFTER_SEND;
|
||||
}
|
||||
if (req.state == HttpRequestState::Aborted) {
|
||||
LOG_ERROR(Lib_Http, "Request was aborted (reqId={})", reqId);
|
||||
return ORBIS_HTTP_ERROR_ABORTED;
|
||||
std::shared_ptr<HttpRequest> req_ptr;
|
||||
{
|
||||
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(reqId);
|
||||
if (it == g_state.requests.end()) {
|
||||
LOG_ERROR(Lib_Http, "Invalid reqId={}", reqId);
|
||||
return ORBIS_HTTP_ERROR_INVALID_ID;
|
||||
}
|
||||
auto& req = *it->second;
|
||||
if (req.state == HttpRequestState::Sending || req.state == HttpRequestState::Sent) {
|
||||
LOG_ERROR(Lib_Http, "Request already sent (reqId={})", reqId);
|
||||
return ORBIS_HTTP_ERROR_AFTER_SEND;
|
||||
}
|
||||
if (req.state == HttpRequestState::Aborted) {
|
||||
LOG_ERROR(Lib_Http, "Request was aborted (reqId={})", reqId);
|
||||
return ORBIS_HTTP_ERROR_ABORTED;
|
||||
}
|
||||
// Created -> Sending. Worker thread will move to Sent.
|
||||
req.state = HttpRequestState::Sending;
|
||||
req_ptr = it->second;
|
||||
}
|
||||
|
||||
req.last_errno = ORBIS_HTTP_ERROR_RESOLVER_ENODNS;
|
||||
req.state = HttpRequestState::Sent;
|
||||
LOG_INFO(Lib_Http, "reqId={} send failed: last_errno={:#x} (no-internet path)", reqId,
|
||||
static_cast<u32>(req.last_errno));
|
||||
return ORBIS_HTTP_ERROR_RESOLVER_ENODNS;
|
||||
LOG_INFO(Lib_Http, "reqId={} dispatched to async worker [{}]", reqId,
|
||||
EmulatorSettings.IsConnectedToNetwork() ? "ONLINE (TODO real I/O)"
|
||||
: "OFFLINE no-internet path");
|
||||
std::thread([req_ptr, reqId]() {
|
||||
HttpResponse local_res;
|
||||
if (!EmulatorSettings.IsConnectedToNetwork()) {
|
||||
SynthesizeTransportFailureResponse(local_res);
|
||||
} else {
|
||||
// TODO: real network I/O path but for now return the same so switching doesn't affect
|
||||
// something
|
||||
SynthesizeTransportFailureResponse(local_res);
|
||||
}
|
||||
std::lock_guard<std::mutex> lock(g_state.m_mutex);
|
||||
if (g_state.shutting_down.load() || req_ptr->deleted ||
|
||||
req_ptr->state == HttpRequestState::Aborted) {
|
||||
req_ptr->cv.notify_all();
|
||||
return;
|
||||
}
|
||||
req_ptr->res = std::move(local_res);
|
||||
req_ptr->state = HttpRequestState::Sent;
|
||||
req_ptr->last_errno = ORBIS_HTTP_ERROR_RESOLVER_ENODNS;
|
||||
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();
|
||||
}).detach();
|
||||
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttpSetAcceptEncodingGZIPEnabled(int id, int isEnable) {
|
||||
@ -809,11 +781,6 @@ int PS4_SYSV_ABI sceHttpSetHttp09Enabled(int id, int isEnable) {
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttpSetNonblock(int id, int isEnable) {
|
||||
LOG_ERROR(Lib_Http, "(STUBBED) called id={}, isEnable={}", id, isEnable);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttpSetPolicyOption() {
|
||||
LOG_ERROR(Lib_Http, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
@ -934,6 +901,7 @@ int PS4_SYSV_ABI sceHttpTerm(int libhttpCtxId) {
|
||||
for (auto& [id, req_ptr] : g_state.requests) {
|
||||
req_ptr->deleted = true;
|
||||
req_ptr->state = HttpRequestState::Aborted;
|
||||
req_ptr->cv.notify_all(); // wake blocked waiters before wiping the map
|
||||
}
|
||||
g_state.requests.clear();
|
||||
g_state.connections.clear();
|
||||
@ -946,16 +914,6 @@ int PS4_SYSV_ABI sceHttpTerm(int libhttpCtxId) {
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttpTryGetNonblock(int id, int* isEnable) {
|
||||
LOG_ERROR(Lib_Http, "(STUBBED) called id={}, isEnable={}", id, fmt::ptr(isEnable));
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttpTrySetNonblock(int id, int isEnable) {
|
||||
LOG_ERROR(Lib_Http, "(STUBBED) called id={}, isEnable={}", id, isEnable);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttpUnsetEpoll(int id) {
|
||||
LOG_ERROR(Lib_Http, "(STUBBED) called id={}", id);
|
||||
return ORBIS_OK;
|
||||
@ -973,6 +931,127 @@ int PS4_SYSV_ABI sceHttpUriCopy() {
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
//***********************************
|
||||
// Non-blocking processing functions
|
||||
//***********************************
|
||||
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);
|
||||
if (!g_state.inited) {
|
||||
LOG_ERROR(Lib_Http, "Not initialized");
|
||||
return ORBIS_HTTP_ERROR_BEFORE_INIT;
|
||||
}
|
||||
if (!isEnable) {
|
||||
LOG_ERROR(Lib_Http, "isEnable output pointer is null");
|
||||
return ORBIS_HTTP_ERROR_INVALID_VALUE;
|
||||
}
|
||||
const char* level = "";
|
||||
HttpSettings* s = ResolveSettings(id, level);
|
||||
if (!s) {
|
||||
LOG_ERROR(Lib_Http, "Invalid id={}", id);
|
||||
return ORBIS_HTTP_ERROR_INVALID_ID;
|
||||
}
|
||||
*isEnable = s->nonblock ? 1 : 0;
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttpSetNonblock(int id, int isEnable) {
|
||||
LOG_INFO(Lib_Http, "called id={}, isEnable={}", id, isEnable);
|
||||
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;
|
||||
}
|
||||
const char* level = "";
|
||||
HttpSettings* s = ResolveSettings(id, level);
|
||||
if (!s) {
|
||||
LOG_ERROR(Lib_Http, "Invalid id={}", id);
|
||||
return ORBIS_HTTP_ERROR_INVALID_ID;
|
||||
}
|
||||
s->nonblock = (isEnable != 0);
|
||||
LOG_INFO(Lib_Http, "set {} id={} nonblock={}", level, id, s->nonblock);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttpTryGetNonblock(int id, int* isEnable) {
|
||||
LOG_INFO(Lib_Http, "called id={}, isEnable={}", id, fmt::ptr(isEnable));
|
||||
return sceHttpGetNonblock(id, isEnable);
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttpTrySetNonblock(int id, int isEnable) {
|
||||
LOG_INFO(Lib_Http, "called id={}, isEnable={}", id, isEnable);
|
||||
return sceHttpSetNonblock(id, isEnable);
|
||||
}
|
||||
|
||||
//***********************************
|
||||
// Http Communication functions
|
||||
//***********************************
|
||||
int PS4_SYSV_ABI sceHttpReadData(s32 reqId, void* data, u64 size) {
|
||||
LOG_INFO(Lib_Http, "called reqId={}, data={}, size={}", reqId, fmt::ptr(data), size);
|
||||
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 (!data) {
|
||||
LOG_ERROR(Lib_Http, "data output pointer is null");
|
||||
return ORBIS_HTTP_ERROR_INVALID_VALUE;
|
||||
}
|
||||
auto it = g_state.requests.find(reqId);
|
||||
if (it == g_state.requests.end()) {
|
||||
LOG_ERROR(Lib_Http, "Invalid reqId={}", reqId);
|
||||
return ORBIS_HTTP_ERROR_INVALID_ID;
|
||||
}
|
||||
auto& req = *it->second;
|
||||
int wr = WaitForResponseReady(req, lock);
|
||||
if (wr != ORBIS_OK) {
|
||||
if (wr == ORBIS_HTTP_ERROR_EAGAIN) {
|
||||
LOG_DEBUG(Lib_Http, "reqId={}: EAGAIN (response not yet ready)", reqId);
|
||||
} else {
|
||||
LOG_ERROR(Lib_Http, "Wait failed for reqId={}: {:#x}", reqId, static_cast<u32>(wr));
|
||||
}
|
||||
return wr;
|
||||
}
|
||||
u64 remaining = req.res.body.size() - req.res.read_cursor;
|
||||
u64 to_copy = std::min(size, remaining);
|
||||
if (to_copy > 0) {
|
||||
std::memcpy(data, req.res.body.data() + req.res.read_cursor, to_copy);
|
||||
req.res.read_cursor += to_copy;
|
||||
}
|
||||
LOG_INFO(Lib_Http, "reqId={} copied {} bytes (cursor {}/{}) ", reqId, to_copy,
|
||||
req.res.read_cursor, req.res.body.size());
|
||||
return static_cast<int>(to_copy);
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttpAbortRequest(int reqId) {
|
||||
LOG_INFO(Lib_Http, "called reqId={}", reqId);
|
||||
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(reqId);
|
||||
if (it == g_state.requests.end()) {
|
||||
LOG_ERROR(Lib_Http, "Invalid reqId={}", reqId);
|
||||
return ORBIS_HTTP_ERROR_INVALID_ID;
|
||||
}
|
||||
auto& req = *it->second;
|
||||
|
||||
if (req.state == HttpRequestState::Created || req.state == HttpRequestState::Sending) {
|
||||
req.state = HttpRequestState::Aborted;
|
||||
req.cv.notify_all();
|
||||
LOG_INFO(Lib_Http, "reqId={} marked Aborted", reqId);
|
||||
} else {
|
||||
LOG_INFO(Lib_Http, "reqId={} already Sent/Aborted, no-op", reqId);
|
||||
}
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttpAbortRequestForce(int reqId) {
|
||||
LOG_INFO(Lib_Http, "called reqId={}", reqId);
|
||||
return sceHttpAbortRequest(reqId);
|
||||
}
|
||||
|
||||
//***********************************
|
||||
// Https Option setting functions
|
||||
//***********************************
|
||||
@ -1075,6 +1154,112 @@ int PS4_SYSV_ABI sceHttpsEnableOptionPrivate(int id, u32 sslFlags) {
|
||||
//***********************************
|
||||
// Response Information functions
|
||||
//***********************************
|
||||
int PS4_SYSV_ABI sceHttpGetAllResponseHeaders(int reqId, char** header, u64* headerSize) {
|
||||
LOG_INFO(Lib_Http, "called reqId={}, header={}, headerSize={}", reqId, fmt::ptr(header),
|
||||
fmt::ptr(headerSize));
|
||||
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 (!header || !headerSize) {
|
||||
LOG_ERROR(Lib_Http, "header or headerSize output pointer is null");
|
||||
return ORBIS_HTTP_ERROR_INVALID_VALUE;
|
||||
}
|
||||
auto it = g_state.requests.find(reqId);
|
||||
if (it == g_state.requests.end()) {
|
||||
LOG_ERROR(Lib_Http, "Invalid reqId={}", reqId);
|
||||
return ORBIS_HTTP_ERROR_INVALID_ID;
|
||||
}
|
||||
auto& req = *it->second;
|
||||
int wr = WaitForResponseReady(req, lock);
|
||||
if (wr != ORBIS_OK) {
|
||||
if (wr == ORBIS_HTTP_ERROR_EAGAIN) {
|
||||
LOG_DEBUG(Lib_Http, "reqId={}: EAGAIN (response not yet ready)", reqId);
|
||||
} else {
|
||||
LOG_ERROR(Lib_Http, "Wait failed for reqId={}: {:#x}", reqId, static_cast<u32>(wr));
|
||||
}
|
||||
return wr;
|
||||
}
|
||||
if (req.res.all_headers_blob.empty()) {
|
||||
*header = nullptr;
|
||||
*headerSize = 0;
|
||||
} else {
|
||||
*header = const_cast<char*>(req.res.all_headers_blob.c_str());
|
||||
*headerSize = req.res.all_headers_blob.size();
|
||||
}
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttpGetResponseContentLength(int reqId, int* result, u64* contentLength) {
|
||||
LOG_INFO(Lib_Http, "called reqId={}, result={}, contentLength={}", reqId, fmt::ptr(result),
|
||||
fmt::ptr(contentLength));
|
||||
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 (!result || !contentLength) {
|
||||
LOG_ERROR(Lib_Http, "result or contentLength output pointer is null");
|
||||
return ORBIS_HTTP_ERROR_INVALID_VALUE;
|
||||
}
|
||||
auto it = g_state.requests.find(reqId);
|
||||
if (it == g_state.requests.end()) {
|
||||
LOG_ERROR(Lib_Http, "Invalid reqId={}", reqId);
|
||||
return ORBIS_HTTP_ERROR_INVALID_ID;
|
||||
}
|
||||
auto& req = *it->second;
|
||||
int wr = WaitForResponseReady(req, lock);
|
||||
if (wr == ORBIS_HTTP_ERROR_EAGAIN) {
|
||||
LOG_DEBUG(Lib_Http, "reqId={}: response not yet ready, returning BEFORE_SEND", reqId);
|
||||
return ORBIS_HTTP_ERROR_BEFORE_SEND;
|
||||
}
|
||||
if (wr != ORBIS_OK) {
|
||||
LOG_ERROR(Lib_Http, "Wait failed for reqId={}: {:#x}", reqId, static_cast<u32>(wr));
|
||||
return wr;
|
||||
}
|
||||
*result = req.res.content_length_result;
|
||||
*contentLength = req.res.content_length;
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttpGetStatusCode(int reqId, int* statusCode) {
|
||||
LOG_INFO(Lib_Http, "called reqId={}, statusCode={}", reqId, fmt::ptr(statusCode));
|
||||
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 (!statusCode) {
|
||||
LOG_ERROR(Lib_Http, "statusCode output pointer is null");
|
||||
return ORBIS_HTTP_ERROR_INVALID_VALUE;
|
||||
}
|
||||
auto it = g_state.requests.find(reqId);
|
||||
if (it == g_state.requests.end()) {
|
||||
LOG_ERROR(Lib_Http, "Invalid reqId={}", reqId);
|
||||
return ORBIS_HTTP_ERROR_INVALID_ID;
|
||||
}
|
||||
auto& req = *it->second;
|
||||
int wr = WaitForResponseReady(req, lock);
|
||||
if (wr == ORBIS_HTTP_ERROR_EAGAIN) {
|
||||
LOG_DEBUG(Lib_Http, "reqId={}: response not yet ready, returning BEFORE_SEND", reqId);
|
||||
return ORBIS_HTTP_ERROR_BEFORE_SEND;
|
||||
}
|
||||
if (wr != ORBIS_OK) {
|
||||
LOG_ERROR(Lib_Http, "Wait failed for reqId={}: {:#x}", reqId, static_cast<u32>(wr));
|
||||
return wr;
|
||||
}
|
||||
// Transport failure: no status line was ever received from a server.
|
||||
if (req.res.status_code == 0 && req.last_errno != 0) {
|
||||
LOG_INFO(Lib_Http, "reqId={} transport failure, errno={:#x}, returning BEFORE_SEND", reqId,
|
||||
static_cast<u32>(req.last_errno));
|
||||
return ORBIS_HTTP_ERROR_BEFORE_SEND;
|
||||
}
|
||||
*statusCode = req.res.status_code;
|
||||
LOG_INFO(Lib_Http, "reqId={} status={}", reqId, req.res.status_code);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttpSetInflateGZIPEnabled(int id, int isEnable) {
|
||||
LOG_INFO(Lib_Http, "called id={}, isEnable={}", id, isEnable);
|
||||
std::lock_guard<std::mutex> lock(g_state.m_mutex);
|
||||
@ -1216,9 +1401,63 @@ int PS4_SYSV_ABI sceHttpSetRecvTimeOut(int id, u32 usec) {
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
//***********************************
|
||||
// Connection functions
|
||||
//***********************************
|
||||
int PS4_SYSV_ABI sceHttpDeleteConnection(int connId) {
|
||||
LOG_INFO(Lib_Http, "called connId={}", connId);
|
||||
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.connections.erase(connId) == 0) {
|
||||
LOG_ERROR(Lib_Http, "Invalid connId={}", connId);
|
||||
return ORBIS_HTTP_ERROR_INVALID_ID;
|
||||
}
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
//***********************************
|
||||
// Template functions
|
||||
//***********************************
|
||||
int PS4_SYSV_ABI sceHttpDeleteTemplate(int tmplId) {
|
||||
LOG_INFO(Lib_Http, "called tmplId={}", tmplId);
|
||||
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.templates.erase(tmplId) == 0) {
|
||||
LOG_ERROR(Lib_Http, "Invalid tmplId={}", tmplId);
|
||||
return ORBIS_HTTP_ERROR_INVALID_ID;
|
||||
}
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
//***********************************
|
||||
// Request functions
|
||||
//***********************************
|
||||
int PS4_SYSV_ABI sceHttpDeleteRequest(int reqId) {
|
||||
LOG_INFO(Lib_Http, "called reqId={}", reqId);
|
||||
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(reqId);
|
||||
if (it == g_state.requests.end()) {
|
||||
LOG_ERROR(Lib_Http, "Invalid reqId={}", reqId);
|
||||
return ORBIS_HTTP_ERROR_INVALID_ID;
|
||||
}
|
||||
auto req_ptr = it->second;
|
||||
req_ptr->deleted = true;
|
||||
req_ptr->state = HttpRequestState::Aborted;
|
||||
req_ptr->cv.notify_all();
|
||||
g_state.requests.erase(it);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttpCreateRequest2(int connId, const char* method, const char* path,
|
||||
u64 contentLength) {
|
||||
LOG_INFO(Lib_Http, "called connId={}, method={}, path={}, contentLength={}", connId,
|
||||
@ -1241,42 +1480,47 @@ int PS4_SYSV_ABI sceHttpCreateRequest2(int connId, const char* method, const cha
|
||||
return ORBIS_HTTP_METHOD_TRACE;
|
||||
return -1;
|
||||
};
|
||||
// Resolve the connection's URL under the lock, then delegate.
|
||||
// Resolve the connection's URL under the lock, then drop the lock before
|
||||
// delegating to sceHttpCreateRequestWithURL
|
||||
std::string url;
|
||||
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.connections.find(connId);
|
||||
if (it == g_state.connections.end()) {
|
||||
LOG_ERROR(Lib_Http, "Invalid connId={}", connId);
|
||||
return ORBIS_HTTP_ERROR_INVALID_ID;
|
||||
}
|
||||
if (!path) {
|
||||
LOG_ERROR(Lib_Http, "path is null");
|
||||
return ORBIS_HTTP_ERROR_INVALID_VALUE;
|
||||
}
|
||||
if (ContainsCrLf(path)) {
|
||||
LOG_ERROR(Lib_Http, "path contains CR/LF (CRLF-injection rejected): {}", path);
|
||||
return ORBIS_HTTP_ERROR_INVALID_VALUE;
|
||||
}
|
||||
int int_method = map_method(method);
|
||||
if (int_method < 0) {
|
||||
if (!method) {
|
||||
LOG_ERROR(Lib_Http, "method is null");
|
||||
int int_method;
|
||||
{
|
||||
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.connections.find(connId);
|
||||
if (it == g_state.connections.end()) {
|
||||
LOG_ERROR(Lib_Http, "Invalid connId={}", connId);
|
||||
return ORBIS_HTTP_ERROR_INVALID_ID;
|
||||
}
|
||||
if (!path) {
|
||||
LOG_ERROR(Lib_Http, "path is null");
|
||||
return ORBIS_HTTP_ERROR_INVALID_VALUE;
|
||||
}
|
||||
LOG_INFO(Lib_Http, "method '{}' not in standard table; routing via CUSTOM slot", method);
|
||||
int_method = ORBIS_HTTP_METHOD_CUSTOM;
|
||||
}
|
||||
const auto& conn = it->second;
|
||||
url = conn.scheme + "://" + conn.hostname + ":" + std::to_string(conn.port);
|
||||
if (path[0] != '\0') {
|
||||
if (path[0] != '/') {
|
||||
url.push_back('/');
|
||||
if (ContainsCrLf(path)) {
|
||||
LOG_ERROR(Lib_Http, "path contains CR/LF (CRLF-injection rejected): {}", path);
|
||||
return ORBIS_HTTP_ERROR_INVALID_VALUE;
|
||||
}
|
||||
int_method = map_method(method);
|
||||
if (int_method < 0) {
|
||||
if (!method) {
|
||||
LOG_ERROR(Lib_Http, "method is null");
|
||||
return ORBIS_HTTP_ERROR_INVALID_VALUE;
|
||||
}
|
||||
LOG_INFO(Lib_Http, "method '{}' not in standard table; routing via CUSTOM slot",
|
||||
method);
|
||||
int_method = ORBIS_HTTP_METHOD_CUSTOM;
|
||||
}
|
||||
const auto& conn = it->second;
|
||||
url = conn.scheme + "://" + conn.hostname + ":" + std::to_string(conn.port);
|
||||
if (path[0] != '\0') {
|
||||
if (path[0] != '/') {
|
||||
url.push_back('/');
|
||||
}
|
||||
url.append(path);
|
||||
}
|
||||
url.append(path);
|
||||
}
|
||||
int reqId = sceHttpCreateRequestWithURL(connId, int_method, url.c_str(), contentLength);
|
||||
if (reqId > 0 && method) {
|
||||
|
||||
@ -129,8 +129,6 @@ using OrbisHttpsCallback = int(PS4_SYSV_ABI*)(int libsslCtxId, u32 verifyErr, vo
|
||||
using OrbisHttpsCaList = Libraries::Ssl::OrbisSslCaList;
|
||||
|
||||
// Functions
|
||||
int PS4_SYSV_ABI sceHttpAbortRequest(int reqId);
|
||||
int PS4_SYSV_ABI sceHttpAbortRequestForce(int reqId);
|
||||
int PS4_SYSV_ABI sceHttpAbortWaitRequest(OrbisHttpEpollHandle eh);
|
||||
int PS4_SYSV_ABI sceHttpAddCookie(int libhttpCtxId, const char* url, const char* cookie,
|
||||
u64 cookieLength);
|
||||
@ -162,12 +160,8 @@ int PS4_SYSV_ABI sceHttpDbgShowConnectionStat();
|
||||
int PS4_SYSV_ABI sceHttpDbgShowMemoryPoolStat();
|
||||
int PS4_SYSV_ABI sceHttpDbgShowRequestStat();
|
||||
int PS4_SYSV_ABI sceHttpDbgShowStat();
|
||||
int PS4_SYSV_ABI sceHttpDeleteConnection(int connId);
|
||||
int PS4_SYSV_ABI sceHttpDeleteRequest(int reqId);
|
||||
int PS4_SYSV_ABI sceHttpDeleteTemplate(int tmplId);
|
||||
int PS4_SYSV_ABI sceHttpDestroyEpoll(int libhttpCtxId, OrbisHttpEpollHandle eh);
|
||||
int PS4_SYSV_ABI sceHttpGetAcceptEncodingGZIPEnabled(int id, int* isEnable);
|
||||
int PS4_SYSV_ABI sceHttpGetAllResponseHeaders(int reqId, char** header, u64* headerSize);
|
||||
int PS4_SYSV_ABI sceHttpGetAuthEnabled(int id, int* isEnable);
|
||||
int PS4_SYSV_ABI sceHttpGetConnectionStat();
|
||||
int PS4_SYSV_ABI sceHttpGetCookie(int libhttpCtxId, const char* url, char* cookie, u64* required,
|
||||
@ -177,12 +171,8 @@ int PS4_SYSV_ABI sceHttpGetCookieStats(int libhttpCtxId, OrbisHttpCookieStats* s
|
||||
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 sceHttpGetNonblock(int id, int* isEnable);
|
||||
int PS4_SYSV_ABI sceHttpGetRegisteredCtxIds();
|
||||
int PS4_SYSV_ABI sceHttpGetResponseContentLength(int reqId, int* result, u64* contentLength);
|
||||
int PS4_SYSV_ABI sceHttpGetStatusCode(int reqId, int* statusCode);
|
||||
int PS4_SYSV_ABI sceHttpInit(int libnetMemId, int libsslCtxId, u64 poolSize);
|
||||
int PS4_SYSV_ABI sceHttpReadData(s32 reqId, void* data, u64 size);
|
||||
int PS4_SYSV_ABI sceHttpRedirectCacheFlush(int libhttpCtxId);
|
||||
int PS4_SYSV_ABI sceHttpRemoveRequestHeader(int id, const char* name);
|
||||
int PS4_SYSV_ABI sceHttpRequestGetAllHeaders();
|
||||
@ -206,7 +196,6 @@ int PS4_SYSV_ABI sceHttpSetDelayBuildRequestEnabled(int id, int isEnable);
|
||||
int PS4_SYSV_ABI sceHttpSetEpoll(int id, OrbisHttpEpollHandle eh, void* userArg);
|
||||
int PS4_SYSV_ABI sceHttpSetEpollId();
|
||||
int PS4_SYSV_ABI sceHttpSetHttp09Enabled(int id, int isEnable);
|
||||
int PS4_SYSV_ABI sceHttpSetNonblock(int id, int isEnable);
|
||||
int PS4_SYSV_ABI sceHttpSetPolicyOption();
|
||||
int PS4_SYSV_ABI sceHttpSetPriorityOption();
|
||||
int PS4_SYSV_ABI sceHttpSetProxy();
|
||||
@ -229,13 +218,23 @@ 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 sceHttpTryGetNonblock(int id, int* isEnable);
|
||||
int PS4_SYSV_ABI sceHttpTrySetNonblock(int id, int isEnable);
|
||||
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 sceHttpGetNonblock(int id, int* isEnable);
|
||||
int PS4_SYSV_ABI sceHttpSetNonblock(int id, int isEnable);
|
||||
int PS4_SYSV_ABI sceHttpTryGetNonblock(int id, int* isEnable);
|
||||
int PS4_SYSV_ABI sceHttpTrySetNonblock(int id, int isEnable);
|
||||
//***********************************
|
||||
// Http Communication functions
|
||||
//***********************************
|
||||
int PS4_SYSV_ABI sceHttpReadData(s32 reqId, void* data, u64 size);
|
||||
int PS4_SYSV_ABI sceHttpAbortRequest(int reqId);
|
||||
int PS4_SYSV_ABI sceHttpAbortRequestForce(int reqId);
|
||||
//***********************************
|
||||
// Https Option setting functions
|
||||
//***********************************
|
||||
@ -246,6 +245,9 @@ int PS4_SYSV_ABI sceHttpsEnableOptionPrivate(int id, u32 sslFlags);
|
||||
//***********************************
|
||||
// Response Information functions
|
||||
//***********************************
|
||||
int PS4_SYSV_ABI sceHttpGetAllResponseHeaders(int reqId, char** header, u64* headerSize);
|
||||
int PS4_SYSV_ABI sceHttpGetResponseContentLength(int reqId, int* result, u64* contentLength);
|
||||
int PS4_SYSV_ABI sceHttpGetStatusCode(int reqId, int* statusCode);
|
||||
int PS4_SYSV_ABI sceHttpSetInflateGZIPEnabled(int id, int isEnable);
|
||||
//***********************************
|
||||
// Http Header setting functions
|
||||
@ -263,8 +265,17 @@ int PS4_SYSV_ABI sceHttpSetConnectTimeOut(int id, u32 usec);
|
||||
int PS4_SYSV_ABI sceHttpSetSendTimeOut(int id, u32 usec);
|
||||
int PS4_SYSV_ABI sceHttpSetRecvTimeOut(int id, u32 usec);
|
||||
//***********************************
|
||||
// Connection functions
|
||||
//***********************************
|
||||
int PS4_SYSV_ABI sceHttpDeleteConnection(int connId);
|
||||
//***********************************
|
||||
// Template functions
|
||||
//***********************************
|
||||
int PS4_SYSV_ABI sceHttpDeleteTemplate(int tmplId);
|
||||
//***********************************
|
||||
// Request functions
|
||||
//***********************************
|
||||
int PS4_SYSV_ABI sceHttpDeleteRequest(int reqId);
|
||||
int PS4_SYSV_ABI sceHttpCreateRequest2(int connId, const char* method, const char* path,
|
||||
u64 contentLength);
|
||||
int PS4_SYSV_ABI sceHttpCreateRequestWithURL2(int connId, const char* method, const char* url,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user