mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-04-20 03:24:49 +00:00
[Lib] libsceHttp (#2576)
* implemented sceHttpUriParse * argg clang * improved in case of file://// (probably) * rewrote httpuriparse to support file://// * fixed uriparse
This commit is contained in:
parent
a583a9abe0
commit
951128389d
4 changed files with 352 additions and 10 deletions
|
@ -298,6 +298,7 @@ set(KERNEL_LIB src/core/libraries/kernel/sync/mutex.cpp
|
|||
|
||||
set(NETWORK_LIBS src/core/libraries/network/http.cpp
|
||||
src/core/libraries/network/http.h
|
||||
src/core/libraries/network/http_error.h
|
||||
src/core/libraries/network/http2.cpp
|
||||
src/core/libraries/network/http2.h
|
||||
src/core/libraries/network/net.cpp
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "core/libraries/error_codes.h"
|
||||
#include "core/libraries/libs.h"
|
||||
#include "core/libraries/network/http.h"
|
||||
#include "http_error.h"
|
||||
|
||||
namespace Libraries::Http {
|
||||
|
||||
|
@ -566,17 +567,277 @@ int PS4_SYSV_ABI sceHttpUriMerge() {
|
|||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttpUriParse() {
|
||||
int PS4_SYSV_ABI sceHttpUriParse(OrbisHttpUriElement* out, const char* srcUri, void* pool,
|
||||
size_t* require, size_t prepare) {
|
||||
LOG_INFO(Lib_Http, "srcUri = {}", std::string(srcUri));
|
||||
if (!srcUri) {
|
||||
LOG_ERROR(Lib_Http, "invalid url");
|
||||
return ORBIS_HTTP_ERROR_INVALID_URL;
|
||||
}
|
||||
if (!out && !pool && !require) {
|
||||
LOG_ERROR(Lib_Http, "invalid values");
|
||||
return ORBIS_HTTP_ERROR_INVALID_VALUE;
|
||||
}
|
||||
|
||||
if (out && pool) {
|
||||
memset(out, 0, sizeof(OrbisHttpUriElement));
|
||||
out->scheme = (char*)pool;
|
||||
}
|
||||
|
||||
// Track the total required buffer size
|
||||
size_t requiredSize = 0;
|
||||
|
||||
// Parse the scheme (e.g., "http:", "https:", "file:")
|
||||
size_t schemeLength = 0;
|
||||
while (srcUri[schemeLength] && srcUri[schemeLength] != ':') {
|
||||
if (!isalnum(srcUri[schemeLength])) {
|
||||
LOG_ERROR(Lib_Http, "invalid url");
|
||||
return ORBIS_HTTP_ERROR_INVALID_URL;
|
||||
}
|
||||
schemeLength++;
|
||||
}
|
||||
|
||||
if (pool && prepare < schemeLength + 1) {
|
||||
LOG_ERROR(Lib_Http, "out of memory");
|
||||
return ORBIS_HTTP_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
if (out && pool) {
|
||||
memcpy(out->scheme, srcUri, schemeLength);
|
||||
out->scheme[schemeLength] = '\0';
|
||||
}
|
||||
|
||||
requiredSize += schemeLength + 1;
|
||||
|
||||
// Move past the scheme and ':' character
|
||||
size_t offset = schemeLength + 1;
|
||||
|
||||
// Check if "//" appears after the scheme
|
||||
if (strncmp(srcUri + offset, "//", 2) == 0) {
|
||||
// "//" is present
|
||||
if (out) {
|
||||
out->opaque = false;
|
||||
}
|
||||
offset += 2; // Move past "//"
|
||||
} else {
|
||||
// "//" is not present
|
||||
if (out) {
|
||||
out->opaque = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle "file" scheme
|
||||
if (strncmp(srcUri, "file", 4) == 0) {
|
||||
// File URIs typically start with "file://"
|
||||
if (out && !out->opaque) {
|
||||
// Skip additional slashes (e.g., "////")
|
||||
while (srcUri[offset] == '/') {
|
||||
offset++;
|
||||
}
|
||||
|
||||
// Parse the path (everything after the slashes)
|
||||
char* pathStart = (char*)srcUri + offset;
|
||||
size_t pathLength = 0;
|
||||
while (pathStart[pathLength] && pathStart[pathLength] != '?' &&
|
||||
pathStart[pathLength] != '#') {
|
||||
pathLength++;
|
||||
}
|
||||
|
||||
// Ensure the path starts with '/'
|
||||
if (pathLength > 0 && pathStart[0] != '/') {
|
||||
// Prepend '/' to the path
|
||||
requiredSize += pathLength + 2; // Include '/' and null terminator
|
||||
|
||||
if (pool && prepare < requiredSize) {
|
||||
LOG_ERROR(Lib_Http, "out of memory");
|
||||
return ORBIS_HTTP_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
if (out && pool) {
|
||||
out->path = (char*)pool + (requiredSize - pathLength - 2);
|
||||
out->path[0] = '/'; // Add leading '/'
|
||||
memcpy(out->path + 1, pathStart, pathLength);
|
||||
out->path[pathLength + 1] = '\0';
|
||||
}
|
||||
} else {
|
||||
// Path already starts with '/'
|
||||
requiredSize += pathLength + 1;
|
||||
|
||||
if (pool && prepare < requiredSize) {
|
||||
LOG_ERROR(Lib_Http, "out of memory");
|
||||
return ORBIS_HTTP_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
if (out && pool) {
|
||||
memcpy((char*)pool + (requiredSize - pathLength - 1), pathStart, pathLength);
|
||||
out->path = (char*)pool + (requiredSize - pathLength - 1);
|
||||
out->path[pathLength] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
// Move past the path
|
||||
offset += pathLength;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle non-file schemes (e.g., "http", "https")
|
||||
else {
|
||||
// Parse the host and port
|
||||
char* hostStart = (char*)srcUri + offset;
|
||||
while (*hostStart == '/') {
|
||||
hostStart++;
|
||||
}
|
||||
|
||||
size_t hostLength = 0;
|
||||
while (hostStart[hostLength] && hostStart[hostLength] != '/' &&
|
||||
hostStart[hostLength] != '?' && hostStart[hostLength] != ':') {
|
||||
hostLength++;
|
||||
}
|
||||
|
||||
requiredSize += hostLength + 1;
|
||||
|
||||
if (pool && prepare < requiredSize) {
|
||||
LOG_ERROR(Lib_Http, "out of memory");
|
||||
return ORBIS_HTTP_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
if (out && pool) {
|
||||
memcpy((char*)pool + (requiredSize - hostLength - 1), hostStart, hostLength);
|
||||
out->hostname = (char*)pool + (requiredSize - hostLength - 1);
|
||||
out->hostname[hostLength] = '\0';
|
||||
}
|
||||
|
||||
// Move past the host
|
||||
offset += hostLength;
|
||||
|
||||
// Parse the port (if present)
|
||||
if (hostStart[hostLength] == ':') {
|
||||
char* portStart = hostStart + hostLength + 1;
|
||||
size_t portLength = 0;
|
||||
while (portStart[portLength] && isdigit(portStart[portLength])) {
|
||||
portLength++;
|
||||
}
|
||||
|
||||
requiredSize += portLength + 1;
|
||||
|
||||
if (pool && prepare < requiredSize) {
|
||||
LOG_ERROR(Lib_Http, "out of memory");
|
||||
return ORBIS_HTTP_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
// Convert the port string to a uint16_t
|
||||
char portStr[6]; // Max length for a port number (65535)
|
||||
if (portLength > 5) {
|
||||
LOG_ERROR(Lib_Http, "invalid url");
|
||||
return ORBIS_HTTP_ERROR_INVALID_URL;
|
||||
}
|
||||
memcpy(portStr, portStart, portLength);
|
||||
portStr[portLength] = '\0';
|
||||
|
||||
uint16_t port = (uint16_t)atoi(portStr);
|
||||
if (port == 0 && portStr[0] != '0') {
|
||||
LOG_ERROR(Lib_Http, "invalid url");
|
||||
return ORBIS_HTTP_ERROR_INVALID_URL;
|
||||
}
|
||||
|
||||
// Set the port in the output structure
|
||||
if (out) {
|
||||
out->port = port;
|
||||
}
|
||||
|
||||
// Move past the port
|
||||
offset += portLength + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Parse the path (if present)
|
||||
if (srcUri[offset] == '/') {
|
||||
char* pathStart = (char*)srcUri + offset;
|
||||
size_t pathLength = 0;
|
||||
while (pathStart[pathLength] && pathStart[pathLength] != '?' &&
|
||||
pathStart[pathLength] != '#') {
|
||||
pathLength++;
|
||||
}
|
||||
|
||||
requiredSize += pathLength + 1;
|
||||
|
||||
if (pool && prepare < requiredSize) {
|
||||
LOG_ERROR(Lib_Http, "out of memory");
|
||||
return ORBIS_HTTP_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
if (out && pool) {
|
||||
memcpy((char*)pool + (requiredSize - pathLength - 1), pathStart, pathLength);
|
||||
out->path = (char*)pool + (requiredSize - pathLength - 1);
|
||||
out->path[pathLength] = '\0';
|
||||
}
|
||||
|
||||
// Move past the path
|
||||
offset += pathLength;
|
||||
}
|
||||
|
||||
// Parse the query (if present)
|
||||
if (srcUri[offset] == '?') {
|
||||
char* queryStart = (char*)srcUri + offset + 1;
|
||||
size_t queryLength = 0;
|
||||
while (queryStart[queryLength] && queryStart[queryLength] != '#') {
|
||||
queryLength++;
|
||||
}
|
||||
|
||||
requiredSize += queryLength + 1;
|
||||
|
||||
if (pool && prepare < requiredSize) {
|
||||
LOG_ERROR(Lib_Http, "out of memory");
|
||||
return ORBIS_HTTP_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
if (out && pool) {
|
||||
memcpy((char*)pool + (requiredSize - queryLength - 1), queryStart, queryLength);
|
||||
out->query = (char*)pool + (requiredSize - queryLength - 1);
|
||||
out->query[queryLength] = '\0';
|
||||
}
|
||||
|
||||
// Move past the query
|
||||
offset += queryLength + 1;
|
||||
}
|
||||
|
||||
// Parse the fragment (if present)
|
||||
if (srcUri[offset] == '#') {
|
||||
char* fragmentStart = (char*)srcUri + offset + 1;
|
||||
size_t fragmentLength = 0;
|
||||
while (fragmentStart[fragmentLength]) {
|
||||
fragmentLength++;
|
||||
}
|
||||
|
||||
requiredSize += fragmentLength + 1;
|
||||
|
||||
if (pool && prepare < requiredSize) {
|
||||
LOG_ERROR(Lib_Http, "out of memory");
|
||||
return ORBIS_HTTP_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
if (out && pool) {
|
||||
memcpy((char*)pool + (requiredSize - fragmentLength - 1), fragmentStart,
|
||||
fragmentLength);
|
||||
out->fragment = (char*)pool + (requiredSize - fragmentLength - 1);
|
||||
out->fragment[fragmentLength] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate the total required buffer size
|
||||
if (require) {
|
||||
*require = requiredSize; // Update with actual required size
|
||||
}
|
||||
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttpUriSweepPath(char* dst, const char* src, size_t srcSize) {
|
||||
LOG_ERROR(Lib_Http, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttpUriSweepPath() {
|
||||
LOG_ERROR(Lib_Http, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceHttpUriUnescape() {
|
||||
int PS4_SYSV_ABI sceHttpUriUnescape(char* out, size_t* require, size_t prepare, const char* in) {
|
||||
LOG_ERROR(Lib_Http, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,19 @@ class SymbolsResolver;
|
|||
|
||||
namespace Libraries::Http {
|
||||
|
||||
struct OrbisHttpUriElement {
|
||||
bool opaque;
|
||||
char* scheme;
|
||||
char* username;
|
||||
char* password;
|
||||
char* hostname;
|
||||
char* path;
|
||||
char* query;
|
||||
char* fragment;
|
||||
u16 port;
|
||||
u8 reserved[10];
|
||||
};
|
||||
|
||||
int PS4_SYSV_ABI sceHttpAbortRequest();
|
||||
int PS4_SYSV_ABI sceHttpAbortRequestForce();
|
||||
int PS4_SYSV_ABI sceHttpAbortWaitRequest();
|
||||
|
@ -122,9 +135,10 @@ int PS4_SYSV_ABI sceHttpUriBuild();
|
|||
int PS4_SYSV_ABI sceHttpUriCopy();
|
||||
int PS4_SYSV_ABI sceHttpUriEscape();
|
||||
int PS4_SYSV_ABI sceHttpUriMerge();
|
||||
int PS4_SYSV_ABI sceHttpUriParse();
|
||||
int PS4_SYSV_ABI sceHttpUriSweepPath();
|
||||
int PS4_SYSV_ABI sceHttpUriUnescape();
|
||||
int PS4_SYSV_ABI sceHttpUriParse(OrbisHttpUriElement* out, const char* srcUri, void* pool,
|
||||
size_t* require, size_t prepare);
|
||||
int PS4_SYSV_ABI sceHttpUriSweepPath(char* dst, const char* src, size_t srcSize);
|
||||
int PS4_SYSV_ABI sceHttpUriUnescape(char* out, size_t* require, size_t prepare, const char* in);
|
||||
int PS4_SYSV_ABI sceHttpWaitRequest();
|
||||
|
||||
void RegisterlibSceHttp(Core::Loader::SymbolsResolver* sym);
|
||||
|
|
66
src/core/libraries/network/http_error.h
Normal file
66
src/core/libraries/network/http_error.h
Normal file
|
@ -0,0 +1,66 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/libraries/error_codes.h"
|
||||
|
||||
constexpr int ORBIS_HTTP_ERROR_BEFORE_INIT = 0x80431001;
|
||||
constexpr int ORBIS_HTTP_ERROR_ALREADY_INITED = 0x80431020;
|
||||
constexpr int ORBIS_HTTP_ERROR_BUSY = 0x80431021;
|
||||
constexpr int ORBIS_HTTP_ERROR_OUT_OF_MEMORY = 0x80431022;
|
||||
constexpr int ORBIS_HTTP_ERROR_NOT_FOUND = 0x80431025;
|
||||
constexpr int ORBIS_HTTP_ERROR_INVALID_VERSION = 0x8043106a;
|
||||
constexpr int ORBIS_HTTP_ERROR_INVALID_ID = 0x80431100;
|
||||
constexpr int ORBIS_HTTP_ERROR_OUT_OF_SIZE = 0x80431104;
|
||||
constexpr int ORBIS_HTTP_ERROR_INVALID_VALUE = 0x804311fe;
|
||||
|
||||
constexpr int ORBIS_HTTP_ERROR_INVALID_URL = 0x80433060;
|
||||
constexpr int ORBIS_HTTP_ERROR_UNKNOWN_SCHEME = 0x80431061;
|
||||
constexpr int ORBIS_HTTP_ERROR_NETWORK = 0x80431063;
|
||||
constexpr int ORBIS_HTTP_ERROR_BAD_RESPONSE = 0x80431064;
|
||||
constexpr int ORBIS_HTTP_ERROR_BEFORE_SEND = 0x80431065;
|
||||
constexpr int ORBIS_HTTP_ERROR_AFTER_SEND = 0x80431066;
|
||||
constexpr int ORBIS_HTTP_ERROR_TIMEOUT = 0x80431068;
|
||||
constexpr int ORBIS_HTTP_ERROR_UNKNOWN_AUTH_TYPE = 0x80431069;
|
||||
constexpr int ORBIS_HTTP_ERROR_UNKNOWN_METHOD = 0x8043106b;
|
||||
constexpr int ORBIS_HTTP_ERROR_READ_BY_HEAD_METHOD = 0x8043106f;
|
||||
constexpr int ORBIS_HTTP_ERROR_NOT_IN_COM = 0x80431070;
|
||||
constexpr int ORBIS_HTTP_ERROR_NO_CONTENT_LENGTH = 0x80431071;
|
||||
constexpr int ORBIS_HTTP_ERROR_CHUNK_ENC = 0x80431072;
|
||||
constexpr int ORBIS_HTTP_ERROR_TOO_LARGE_RESPONSE_HEADER = 0x80431073;
|
||||
constexpr int ORBIS_HTTP_ERROR_SSL = 0x80431075;
|
||||
constexpr int ORBIS_HTTP_ERROR_INSUFFICIENT_STACKSIZE = 0x80431076;
|
||||
constexpr int ORBIS_HTTP_ERROR_ABORTED = 0x80431080;
|
||||
constexpr int ORBIS_HTTP_ERROR_UNKNOWN = 0x80431081;
|
||||
constexpr int ORBIS_HTTP_ERROR_EAGAIN = 0x80431082;
|
||||
constexpr int ORBIS_HTTP_ERROR_PROXY = 0x80431084;
|
||||
constexpr int ORBIS_HTTP_ERROR_BROKEN = 0x80431085;
|
||||
|
||||
constexpr int ORBIS_HTTP_ERROR_PARSE_HTTP_NOT_FOUND = 0x80432025;
|
||||
constexpr int ORBIS_HTTP_ERROR_PARSE_HTTP_INVALID_RESPONSE = 0x80432060;
|
||||
constexpr int ORBIS_HTTP_ERROR_PARSE_HTTP_INVALID_VALUE = 0x804321fe;
|
||||
|
||||
constexpr int ORBIS_HTTP_ERROR_RESOLVER_EPACKET = 0x80436001;
|
||||
constexpr int ORBIS_HTTP_ERROR_RESOLVER_ENODNS = 0x80436002;
|
||||
constexpr int ORBIS_HTTP_ERROR_RESOLVER_ETIMEDOUT = 0x80436003;
|
||||
constexpr int ORBIS_HTTP_ERROR_RESOLVER_ENOSUPPORT = 0x80436004;
|
||||
constexpr int ORBIS_HTTP_ERROR_RESOLVER_EFORMAT = 0x80436005;
|
||||
constexpr int ORBIS_HTTP_ERROR_RESOLVER_ESERVERFAILURE = 0x80436006;
|
||||
constexpr int ORBIS_HTTP_ERROR_RESOLVER_ENOHOST = 0x80436007;
|
||||
constexpr int ORBIS_HTTP_ERROR_RESOLVER_ENOTIMPLEMENTED = 0x80436008;
|
||||
constexpr int ORBIS_HTTP_ERROR_RESOLVER_ESERVERREFUSED = 0x80436009;
|
||||
constexpr int ORBIS_HTTP_ERROR_RESOLVER_ENORECORD = 0x8043600a;
|
||||
|
||||
constexpr int ORBIS_HTTPS_ERROR_CERT = 0x80435060;
|
||||
constexpr int ORBIS_HTTPS_ERROR_HANDSHAKE = 0x80435061;
|
||||
constexpr int ORBIS_HTTPS_ERROR_IO = 0x80435062;
|
||||
constexpr int ORBIS_HTTPS_ERROR_INTERNAL = 0x80435063;
|
||||
constexpr int ORBIS_HTTPS_ERROR_PROXY = 0x80435064;
|
||||
|
||||
constexpr int ORBIS_HTTPS_ERROR_SSL_INTERNAL = 0x01;
|
||||
constexpr int ORBIS_HTTPS_ERROR_SSL_INVALID_CERT = 0x02;
|
||||
constexpr int ORBIS_HTTPS_ERROR_SSL_CN_CHECK = 0x04;
|
||||
constexpr int ORBIS_HTTPS_ERROR_SSL_NOT_AFTER_CHECK = 0x08;
|
||||
constexpr int ORBIS_HTTPS_ERROR_SSL_NOT_BEFORE_CHECK = 0x10;
|
||||
constexpr int ORBIS_HTTPS_ERROR_SSL_UNKNOWN_CA = 0x20;
|
Loading…
Add table
Reference in a new issue