Move http to core/networking

This commit is contained in:
igor725 2024-04-20 01:46:15 +03:00
parent 5853b969cc
commit a4a54b34c4
No known key found for this signature in database
GPG Key ID: 46F13BBE46F8569D
11 changed files with 1241 additions and 542 deletions

View File

@ -33,6 +33,7 @@ add_library(core SHARED
add_dependencies(core logging third_party config_emu gamereport)
target_link_libraries(core PRIVATE
libboost_url
libboost_thread
libboost_chrono
libboost_program_options

View File

@ -5,6 +5,7 @@ add_library(networking OBJECT
states/online/resolver.cpp
states/online/socket.cpp
states/online/epoll.cpp
states/online/http.cpp
wepoll.c
networking.cpp

View File

@ -1,9 +1,12 @@
#pragma once
#include "modules/libSceHttp/httpsTypes.h"
#include "modules/libSceHttp/types.h"
#include "modules/libSceNet/resolverTypes.h"
#include "modules/libSceNet/socketTypes.h"
#include "modules/libSceNet/types.h"
#include "modules/libSceNetCtl/types.h"
#include "modules/libSceSsl/types.h"
#include "modules_include/common.h"
#include "utility/utility.h"
@ -79,6 +82,73 @@ class INetworking {
virtual int socketShutdown(SceNetId s, int how) = 0;
virtual int socketClose(SceNetId s) = 0;
virtual int socketAbort(SceNetId s, int flags) = 0;
/* HTTP facility */
/* HTTP1 facility */
virtual int httpInit(int libnetMemId, int libsslCtxId, size_t poolSize) = 0;
virtual int httpTerm(int libhttpCtxId) = 0;
virtual int httpGetMemoryPoolStats(int libhttpCtxId, SceHttpMemoryPoolStats* currentStat) = 0;
virtual int httpCreateTemplate(int libhttpCtxId, const char* userAgent, int httpVer, int isAutoProxyConf) = 0;
virtual int httpDeleteTemplate(int tmplId) = 0;
virtual int httpCreateConnection(int tmplId, const char* serverName, const char* scheme, uint16_t port, int isEnableKeepalive) = 0;
virtual int httpCreateConnectionWithURL(int tmplId, const char* url, int isEnableKeepalive) = 0;
virtual int httpDeleteConnection(int connId) = 0;
virtual int httpCreateRequest(int connId, int method, const char* path, uint64_t contentLength) = 0;
virtual int httpCreateRequest2(int connId, const char* method, const char* path, uint64_t contentLength) = 0;
virtual int httpCreateRequestWithURL(int connId, int method, const char* url, uint64_t contentLength) = 0;
virtual int httpCreateRequestWithURL2(int connId, const char* method, const char* url, uint64_t contentLength) = 0;
virtual int httpDeleteRequest(int reqId) = 0;
virtual int httpSetRequestContentLength(int id, uint64_t contentLength) = 0;
virtual int httpSetChunkedTransferEnabled(int id, int isEnable) = 0;
virtual int httpSetInflateGZIPEnabled(int id, int isEnable) = 0;
virtual int httpSendRequest(int reqId, const void* postData, size_t size) = 0;
virtual int httpAbortRequest(int reqId) = 0;
virtual int httpGetResponseContentLength(int reqId, int* result, uint64_t* contentLength) = 0;
virtual int httpGetStatusCode(int reqId, int* statusCode) = 0;
virtual int httpGetAllResponseHeaders(int reqId, char** header, size_t* headerSize) = 0;
virtual int httpReadData(int reqId, void* data, size_t size) = 0;
virtual int httpAddRequestHeader(int id, const char* name, const char* value, uint32_t mode) = 0;
virtual int httpRemoveRequestHeader(int id, const char* name) = 0;
virtual int httpParseResponseHeader(const char* header, size_t headerLen, const char* fieldStr, const char** fieldValue, size_t* valueLen) = 0;
virtual int httpParseStatusLine(const char* statusLine, size_t lineLen, int* httpMajorVer, int* httpMinorVer, int* responseCode, const char** reasonPhrase,
size_t* phraseLen) = 0;
virtual int httpSetResponseHeaderMaxSize(int id, size_t headerSize) = 0;
virtual int httpSetAuthInfoCallback(int id, SceHttpAuthInfoCallback cbfunc, void* userArg) = 0;
virtual int httpSetAuthEnabled(int id, int isEnable) = 0;
virtual int httpGetAuthEnabled(int id, int* isEnable) = 0;
virtual int httpAuthCacheFlush(int libhttpCtxId) = 0;
virtual int httpSetRedirectCallback(int id, SceHttpRedirectCallback cbfunc, void* userArg) = 0;
virtual int httpSetAutoRedirect(int id, int isEnable) = 0;
virtual int httpGetAutoRedirect(int id, int* isEnable) = 0;
virtual int httpRedirectCacheFlush(int libhttpCtxId) = 0;
virtual int httpSetResolveTimeOut(int id, uint32_t usec) = 0;
virtual int httpSetResolveRetry(int id, int retry) = 0;
virtual int httpSetConnectTimeOut(int id, uint32_t usec) = 0;
virtual int httpSetSendTimeOut(int id, uint32_t usec) = 0;
virtual int httpSetRecvTimeOut(int id, uint32_t usec) = 0;
virtual int httpSetRequestStatusCallback(int id, SceHttpRequestStatusCallback cbfunc, void* userArg) = 0;
virtual int httpGetLastErrno(int reqId, int* errNum) = 0;
virtual int httpSetNonblock(int id, int isEnable) = 0;
virtual int httpGetNonblock(int id, int* isEnable) = 0;
virtual int httpTrySetNonblock(int id, int isEnable) = 0;
virtual int httpTryGetNonblock(int id, int* isEnable) = 0;
virtual int httpCreateEpoll(int libhttpCtxId, SceHttpEpollHandle* eh) = 0;
virtual int httpSetEpoll(int id, SceHttpEpollHandle eh, void* userArg) = 0;
virtual int httpUnsetEpoll(int id) = 0;
virtual int httpGetEpoll(int id, SceHttpEpollHandle* eh, void** userArg) = 0;
virtual int httpDestroyEpoll(int libhttpCtxId, SceHttpEpollHandle eh) = 0;
virtual int httpWaitRequest(SceHttpEpollHandle eh, SceHttpNBEvent* nbev, int maxevents, int timeout) = 0;
virtual int httpAbortWaitRequest(SceHttpEpollHandle eh) = 0;
// HTTPS
virtual int httpsLoadCert(int libhttpCtxId, int caCertNum, const SceSslData** caList, const SceSslData* cert, const SceSslData* privKey) = 0;
virtual int httpsUnloadCert(int libhttpCtxId) = 0;
virtual int httpsEnableOption(int id, uint32_t sslFlags) = 0;
virtual int httpsDisableOption(int id, uint32_t sslFlags) = 0;
virtual int httpsGetSslError(int id, int* errNum, uint32_t* detail) = 0;
virtual int httpsSetSslCallback(int id, SceHttpsCallback cbfunc, void* userArg) = 0;
virtual int httpsSetSslVersion(int id, SceSslVersion version) = 0;
};
#if defined(__APICALL_EXTERN)

View File

@ -135,3 +135,253 @@ int OfflineNet::socketClose(SceNetId s) {
int OfflineNet::socketAbort(SceNetId s, int flags) {
return Ok;
}
int OfflineNet::httpInit(int libnetMemId, int libsslCtxId, size_t poolSize) {
return Ok;
}
int OfflineNet::httpTerm(int libhttpCtxId) {
return Ok;
}
int OfflineNet::httpGetMemoryPoolStats(int libhttpCtxId, SceHttpMemoryPoolStats* currentStat) {
return Ok;
}
int OfflineNet::httpCreateTemplate(int libhttpCtxId, const char* userAgent, int httpVer, int isAutoProxyConf) {
static int id = 0;
return ++id;
}
int OfflineNet::httpDeleteTemplate(int tmplId) {
return Ok;
}
int OfflineNet::httpCreateConnection(int tmplId, const char* serverName, const char* scheme, uint16_t port, int isEnableKeepalive) {
static int id = 0;
return ++id;
}
int OfflineNet::httpCreateConnectionWithURL(int tmplId, const char* url, int isEnableKeepalive) {
static int id = 0;
return ++id;
}
int OfflineNet::httpDeleteConnection(int connId) {
return Ok;
}
int OfflineNet::httpCreateRequest(int connId, int method, const char* path, uint64_t contentLength) {
static int id = 0;
return ++id;
}
int OfflineNet::httpCreateRequest2(int connId, const char* method, const char* path, uint64_t contentLength) {
static int id = 0;
return ++id;
}
int OfflineNet::httpCreateRequestWithURL(int connId, int method, const char* url, uint64_t contentLength) {
static int id = 0;
return ++id;
}
int OfflineNet::httpCreateRequestWithURL2(int connId, const char* method, const char* url, uint64_t contentLength) {
static int id = 0;
return ++id;
}
int OfflineNet::httpDeleteRequest(int reqId) {
return Ok;
}
int OfflineNet::httpSetRequestContentLength(int id, uint64_t contentLength) {
return Ok;
}
int OfflineNet::httpSetChunkedTransferEnabled(int id, int isEnable) {
return Ok;
}
int OfflineNet::httpSetInflateGZIPEnabled(int id, int isEnable) {
return Ok;
}
int OfflineNet::httpSendRequest(int reqId, const void* postData, size_t size) {
return Ok;
}
int OfflineNet::httpAbortRequest(int reqId) {
return Ok;
}
int OfflineNet::httpGetResponseContentLength(int reqId, int* result, uint64_t* contentLength) {
return Ok;
}
int OfflineNet::httpGetStatusCode(int reqId, int* statusCode) {
return Ok;
}
int OfflineNet::httpGetAllResponseHeaders(int reqId, char** header, size_t* headerSize) {
return Ok;
}
int OfflineNet::httpReadData(int reqId, void* data, size_t size) {
return Ok;
}
int OfflineNet::httpAddRequestHeader(int id, const char* name, const char* value, uint32_t mode) {
return Ok;
}
int OfflineNet::httpRemoveRequestHeader(int id, const char* name) {
return Ok;
}
int OfflineNet::httpParseResponseHeader(const char* header, size_t headerLen, const char* fieldStr, const char** fieldValue, size_t* valueLen) {
return Ok;
}
int OfflineNet::httpParseStatusLine(const char* statusLine, size_t lineLen, int* httpMajorVer, int* httpMinorVer, int* responseCode, const char** reasonPhrase,
size_t* phraseLen) {
return Ok;
}
int OfflineNet::httpSetResponseHeaderMaxSize(int id, size_t headerSize) {
return Ok;
}
int OfflineNet::httpSetAuthInfoCallback(int id, SceHttpAuthInfoCallback cbfunc, void* userArg) {
return Ok;
}
int OfflineNet::httpSetAuthEnabled(int id, int isEnable) {
return Ok;
}
int OfflineNet::httpGetAuthEnabled(int id, int* isEnable) {
return Ok;
}
int OfflineNet::httpAuthCacheFlush(int libhttpCtxId) {
return Ok;
}
int OfflineNet::httpSetRedirectCallback(int id, SceHttpRedirectCallback cbfunc, void* userArg) {
return Ok;
}
int OfflineNet::httpSetAutoRedirect(int id, int isEnable) {
return Ok;
}
int OfflineNet::httpGetAutoRedirect(int id, int* isEnable) {
return Ok;
}
int OfflineNet::httpRedirectCacheFlush(int libhttpCtxId) {
return Ok;
}
int OfflineNet::httpSetResolveTimeOut(int id, uint32_t usec) {
return Ok;
}
int OfflineNet::httpSetResolveRetry(int id, int retry) {
return Ok;
}
int OfflineNet::httpSetConnectTimeOut(int id, uint32_t usec) {
return Ok;
}
int OfflineNet::httpSetSendTimeOut(int id, uint32_t usec) {
return Ok;
}
int OfflineNet::httpSetRecvTimeOut(int id, uint32_t usec) {
return Ok;
}
int OfflineNet::httpSetRequestStatusCallback(int id, SceHttpRequestStatusCallback cbfunc, void* userArg) {
return Ok;
}
int OfflineNet::httpGetLastErrno(int reqId, int* errNum) {
return Ok;
}
int OfflineNet::httpSetNonblock(int id, int isEnable) {
return Ok;
}
int OfflineNet::httpGetNonblock(int id, int* isEnable) {
return Ok;
}
int OfflineNet::httpTrySetNonblock(int id, int isEnable) {
return Ok;
}
int OfflineNet::httpTryGetNonblock(int id, int* isEnable) {
return Ok;
}
int OfflineNet::httpCreateEpoll(int libhttpCtxId, SceHttpEpollHandle* eh) {
static int id = 0;
return ++id;
}
int OfflineNet::httpSetEpoll(int id, SceHttpEpollHandle eh, void* userArg) {
return Ok;
}
int OfflineNet::httpUnsetEpoll(int id) {
return Ok;
}
int OfflineNet::httpGetEpoll(int id, SceHttpEpollHandle* eh, void** userArg) {
return Ok;
}
int OfflineNet::httpDestroyEpoll(int libhttpCtxId, SceHttpEpollHandle eh) {
return Ok;
}
int OfflineNet::httpWaitRequest(SceHttpEpollHandle eh, SceHttpNBEvent* nbev, int maxevents, int timeout) {
return Ok;
}
int OfflineNet::httpAbortWaitRequest(SceHttpEpollHandle eh) {
return Ok;
}
// HTTPS
int OfflineNet::httpsLoadCert(int libhttpCtxId, int caCertNum, const SceSslData** caList, const SceSslData* cert, const SceSslData* privKey) {
return Ok;
}
int OfflineNet::httpsUnloadCert(int libhttpCtxId) {
return Ok;
}
int OfflineNet::httpsEnableOption(int id, uint32_t sslFlags) {
return Ok;
}
int OfflineNet::httpsDisableOption(int id, uint32_t sslFlags) {
return Ok;
}
int OfflineNet::httpsGetSslError(int id, int* errNum, uint32_t* detail) {
return Ok;
}
int OfflineNet::httpsSetSslCallback(int id, SceHttpsCallback cbfunc, void* userArg) {
return Ok;
}
int OfflineNet::httpsSetSslVersion(int id, SceSslVersion version) {
return Ok;
}

View File

@ -51,4 +51,71 @@ class OfflineNet: public INetworking {
int socketShutdown(SceNetId s, int how) final;
int socketClose(SceNetId s) final;
int socketAbort(SceNetId s, int flags) final;
/* HTTP facility */
/* HTTP1 facility */
int httpInit(int libnetMemId, int libsslCtxId, size_t poolSize) final;
int httpTerm(int libhttpCtxId) final;
int httpGetMemoryPoolStats(int libhttpCtxId, SceHttpMemoryPoolStats* currentStat) final;
int httpCreateTemplate(int libhttpCtxId, const char* userAgent, int httpVer, int isAutoProxyConf) final;
int httpDeleteTemplate(int tmplId) final;
int httpCreateConnection(int tmplId, const char* serverName, const char* scheme, uint16_t port, int isEnableKeepalive) final;
int httpCreateConnectionWithURL(int tmplId, const char* url, int isEnableKeepalive) final;
int httpDeleteConnection(int connId) final;
int httpCreateRequest(int connId, int method, const char* path, uint64_t contentLength) final;
int httpCreateRequest2(int connId, const char* method, const char* path, uint64_t contentLength) final;
int httpCreateRequestWithURL(int connId, int method, const char* url, uint64_t contentLength) final;
int httpCreateRequestWithURL2(int connId, const char* method, const char* url, uint64_t contentLength) final;
int httpDeleteRequest(int reqId) final;
int httpSetRequestContentLength(int id, uint64_t contentLength) final;
int httpSetChunkedTransferEnabled(int id, int isEnable) final;
int httpSetInflateGZIPEnabled(int id, int isEnable) final;
int httpSendRequest(int reqId, const void* postData, size_t size) final;
int httpAbortRequest(int reqId) final;
int httpGetResponseContentLength(int reqId, int* result, uint64_t* contentLength) final;
int httpGetStatusCode(int reqId, int* statusCode) final;
int httpGetAllResponseHeaders(int reqId, char** header, size_t* headerSize) final;
int httpReadData(int reqId, void* data, size_t size) final;
int httpAddRequestHeader(int id, const char* name, const char* value, uint32_t mode) final;
int httpRemoveRequestHeader(int id, const char* name) final;
int httpParseResponseHeader(const char* header, size_t headerLen, const char* fieldStr, const char** fieldValue, size_t* valueLen) final;
int httpParseStatusLine(const char* statusLine, size_t lineLen, int* httpMajorVer, int* httpMinorVer, int* responseCode, const char** reasonPhrase,
size_t* phraseLen) final;
int httpSetResponseHeaderMaxSize(int id, size_t headerSize) final;
int httpSetAuthInfoCallback(int id, SceHttpAuthInfoCallback cbfunc, void* userArg) final;
int httpSetAuthEnabled(int id, int isEnable) final;
int httpGetAuthEnabled(int id, int* isEnable) final;
int httpAuthCacheFlush(int libhttpCtxId) final;
int httpSetRedirectCallback(int id, SceHttpRedirectCallback cbfunc, void* userArg) final;
int httpSetAutoRedirect(int id, int isEnable) final;
int httpGetAutoRedirect(int id, int* isEnable) final;
int httpRedirectCacheFlush(int libhttpCtxId) final;
int httpSetResolveTimeOut(int id, uint32_t usec) final;
int httpSetResolveRetry(int id, int retry) final;
int httpSetConnectTimeOut(int id, uint32_t usec) final;
int httpSetSendTimeOut(int id, uint32_t usec) final;
int httpSetRecvTimeOut(int id, uint32_t usec) final;
int httpSetRequestStatusCallback(int id, SceHttpRequestStatusCallback cbfunc, void* userArg) final;
int httpGetLastErrno(int reqId, int* errNum) final;
int httpSetNonblock(int id, int isEnable) final;
int httpGetNonblock(int id, int* isEnable) final;
int httpTrySetNonblock(int id, int isEnable) final;
int httpTryGetNonblock(int id, int* isEnable) final;
int httpCreateEpoll(int libhttpCtxId, SceHttpEpollHandle* eh) final;
int httpSetEpoll(int id, SceHttpEpollHandle eh, void* userArg) final;
int httpUnsetEpoll(int id) final;
int httpGetEpoll(int id, SceHttpEpollHandle* eh, void** userArg) final;
int httpDestroyEpoll(int libhttpCtxId, SceHttpEpollHandle eh) final;
int httpWaitRequest(SceHttpEpollHandle eh, SceHttpNBEvent* nbev, int maxevents, int timeout) final;
int httpAbortWaitRequest(SceHttpEpollHandle eh) final;
// HTTPS
int httpsLoadCert(int libhttpCtxId, int caCertNum, const SceSslData** caList, const SceSslData* cert, const SceSslData* privKey) final;
int httpsUnloadCert(int libhttpCtxId) final;
int httpsEnableOption(int id, uint32_t sslFlags) final;
int httpsDisableOption(int id, uint32_t sslFlags) final;
int httpsGetSslError(int id, int* errNum, uint32_t* detail) final;
int httpsSetSslCallback(int id, SceHttpsCallback cbfunc, void* userArg) final;
int httpsSetSslVersion(int id, SceSslVersion version) final;
};

View File

@ -55,4 +55,71 @@ class OnlineNet: public INetworking {
int socketShutdown(SceNetId s, int how) final;
int socketClose(SceNetId s) final;
int socketAbort(SceNetId s, int flags) final;
/* HTTP facility */
/* HTTP1 facility */
int httpInit(int libnetMemId, int libsslCtxId, size_t poolSize) final;
int httpTerm(int libhttpCtxId) final;
int httpGetMemoryPoolStats(int libhttpCtxId, SceHttpMemoryPoolStats* currentStat) final;
int httpCreateTemplate(int libhttpCtxId, const char* userAgent, int httpVer, int isAutoProxyConf) final;
int httpDeleteTemplate(int tmplId) final;
int httpCreateConnection(int tmplId, const char* serverName, const char* scheme, uint16_t port, int isEnableKeepalive) final;
int httpCreateConnectionWithURL(int tmplId, const char* url, int isEnableKeepalive) final;
int httpDeleteConnection(int connId) final;
int httpCreateRequest(int connId, int method, const char* path, uint64_t contentLength) final;
int httpCreateRequest2(int connId, const char* method, const char* path, uint64_t contentLength) final;
int httpCreateRequestWithURL(int connId, int method, const char* url, uint64_t contentLength) final;
int httpCreateRequestWithURL2(int connId, const char* method, const char* url, uint64_t contentLength) final;
int httpDeleteRequest(int reqId) final;
int httpSetRequestContentLength(int id, uint64_t contentLength) final;
int httpSetChunkedTransferEnabled(int id, int isEnable) final;
int httpSetInflateGZIPEnabled(int id, int isEnable) final;
int httpSendRequest(int reqId, const void* postData, size_t size) final;
int httpAbortRequest(int reqId) final;
int httpGetResponseContentLength(int reqId, int* result, uint64_t* contentLength) final;
int httpGetStatusCode(int reqId, int* statusCode) final;
int httpGetAllResponseHeaders(int reqId, char** header, size_t* headerSize) final;
int httpReadData(int reqId, void* data, size_t size) final;
int httpAddRequestHeader(int id, const char* name, const char* value, uint32_t mode) final;
int httpRemoveRequestHeader(int id, const char* name) final;
int httpParseResponseHeader(const char* header, size_t headerLen, const char* fieldStr, const char** fieldValue, size_t* valueLen) final;
int httpParseStatusLine(const char* statusLine, size_t lineLen, int* httpMajorVer, int* httpMinorVer, int* responseCode, const char** reasonPhrase,
size_t* phraseLen) final;
int httpSetResponseHeaderMaxSize(int id, size_t headerSize) final;
int httpSetAuthInfoCallback(int id, SceHttpAuthInfoCallback cbfunc, void* userArg) final;
int httpSetAuthEnabled(int id, int isEnable) final;
int httpGetAuthEnabled(int id, int* isEnable) final;
int httpAuthCacheFlush(int libhttpCtxId) final;
int httpSetRedirectCallback(int id, SceHttpRedirectCallback cbfunc, void* userArg) final;
int httpSetAutoRedirect(int id, int isEnable) final;
int httpGetAutoRedirect(int id, int* isEnable) final;
int httpRedirectCacheFlush(int libhttpCtxId) final;
int httpSetResolveTimeOut(int id, uint32_t usec) final;
int httpSetResolveRetry(int id, int retry) final;
int httpSetConnectTimeOut(int id, uint32_t usec) final;
int httpSetSendTimeOut(int id, uint32_t usec) final;
int httpSetRecvTimeOut(int id, uint32_t usec) final;
int httpSetRequestStatusCallback(int id, SceHttpRequestStatusCallback cbfunc, void* userArg) final;
int httpGetLastErrno(int reqId, int* errNum) final;
int httpSetNonblock(int id, int isEnable) final;
int httpGetNonblock(int id, int* isEnable) final;
int httpTrySetNonblock(int id, int isEnable) final;
int httpTryGetNonblock(int id, int* isEnable) final;
int httpCreateEpoll(int libhttpCtxId, SceHttpEpollHandle* eh) final;
int httpSetEpoll(int id, SceHttpEpollHandle eh, void* userArg) final;
int httpUnsetEpoll(int id) final;
int httpGetEpoll(int id, SceHttpEpollHandle* eh, void** userArg) final;
int httpDestroyEpoll(int libhttpCtxId, SceHttpEpollHandle eh) final;
int httpWaitRequest(SceHttpEpollHandle eh, SceHttpNBEvent* nbev, int maxevents, int timeout) final;
int httpAbortWaitRequest(SceHttpEpollHandle eh) final;
// HTTPS
int httpsLoadCert(int libhttpCtxId, int caCertNum, const SceSslData** caList, const SceSslData* cert, const SceSslData* privKey) final;
int httpsUnloadCert(int libhttpCtxId) final;
int httpsEnableOption(int id, uint32_t sslFlags) final;
int httpsDisableOption(int id, uint32_t sslFlags) final;
int httpsGetSslError(int id, int* errNum, uint32_t* detail) final;
int httpsSetSslCallback(int id, SceHttpsCallback cbfunc, void* userArg) final;
int httpsSetSslVersion(int id, SceSslVersion version) final;
};

View File

@ -0,0 +1,715 @@
#include "../online.h"
#include "logging.h"
#include <Windows.h>
#include <boost/asio.hpp>
#include <boost/url.hpp>
LOG_DEFINE_MODULE(OnlineNetCore_http);
using namespace boost::asio;
namespace {
constexpr size_t ARRAY_LENGTH = 128;
template <typename T, size_t size>
class HttpContainer {
T* m_data[size] = {nullptr};
public:
int lookupAvailableIdx(T* action) {
int i;
bool found = false;
for (i = 1; i < size; i++) {
if (!m_data[i]) {
m_data[i] = action;
break;
}
}
if (found == false) {
delete action;
return 0;
}
return i;
}
int testId(int id) {
if (id < 1 || id >= size || m_data[id] == nullptr) return Err::HTTP_BAD_ID;
return Ok;
}
void remove(int id) {
delete m_data[id];
m_data[id] = nullptr;
}
T* getId(int id) { return m_data[id]; }
};
static io_service svc;
static ip::tcp::resolver resolver(svc);
struct HttpClient {
int libnetMemId;
int libsslCtxId;
size_t poolSize;
uint32_t connectTimeout;
HttpClient(int libnetMemId, int libsslCtxId, size_t poolSize): libnetMemId(libnetMemId), libsslCtxId(libsslCtxId), poolSize(poolSize) {}
};
struct HttpTemplate {
HttpClient* parentClient;
const char* userAgent;
int httpVer;
int isAutoProxyConf;
HttpTemplate(HttpClient* parentClient, const char* userAgent, int httpVer, int isAutoProxyConf)
: parentClient(parentClient), userAgent(userAgent), httpVer(httpVer), isAutoProxyConf(isAutoProxyConf) {}
};
struct HttpConnection {
HttpTemplate* parentTemplate;
const char* serverName;
const char* scheme;
uint16_t port;
int isEnableKeepalive;
bool connected = false;
bool shouldFreeStrings;
ip::tcp::resolver::query* query = nullptr;
ip::tcp::resolver::iterator endpoint_iterator;
ip::tcp::socket* socket = nullptr;
HttpConnection(HttpTemplate* parentTemplate, const char* serverName, const char* scheme, uint16_t port, int isEnableKeepalive, bool shouldFreeStrings)
: parentTemplate(parentTemplate), serverName(serverName), scheme(scheme), port(port), isEnableKeepalive(isEnableKeepalive),
shouldFreeStrings(shouldFreeStrings) {}
};
struct HttpResponse {
int statusCode;
uint32_t contentLength;
const char* body = nullptr;
};
struct HttpRequest {
HttpConnection* parentConnection;
int method;
const char* path;
uint64_t contentLength;
const void* postData = nullptr;
size_t size;
HttpResponse* lastResponse = nullptr;
bool shouldFreePath;
HttpRequest(HttpConnection* parentConnection, int method, const char* path, uint64_t contentLength, bool shouldFreePath)
: parentConnection(parentConnection), method(method), path(path), contentLength(contentLength), shouldFreePath(shouldFreePath) {}
};
struct HttpRequestParams {
HttpConnection* connection;
HttpRequest* request;
uint32_t connectTimeout;
const char* userAgent;
int httpVer;
int isAutoProxyConf;
const char* serverName;
const char* scheme;
uint16_t port;
int isEnableKeepalive;
int method;
const char* path;
uint64_t contentLength;
const void* postData; // will be assigned to nullptr
size_t size;
HttpRequestParams(HttpRequest* from) {
connection = from->parentConnection;
request = from;
connectTimeout = from->parentConnection->parentTemplate->parentClient->connectTimeout;
userAgent = from->parentConnection->parentTemplate->userAgent;
httpVer = from->parentConnection->parentTemplate->httpVer;
isAutoProxyConf = from->parentConnection->parentTemplate->isAutoProxyConf;
serverName = from->parentConnection->serverName;
scheme = from->parentConnection->scheme;
port = from->parentConnection->port;
isEnableKeepalive = from->parentConnection->isEnableKeepalive;
method = from->method;
path = from->path;
contentLength = from->contentLength;
postData = from->postData;
size = from->size;
}
};
static HttpContainer<HttpClient, ARRAY_LENGTH> g_client;
static HttpContainer<HttpTemplate, ARRAY_LENGTH> g_template;
static HttpContainer<HttpConnection, ARRAY_LENGTH> g_connection;
static HttpContainer<HttpRequest, ARRAY_LENGTH> g_request;
#define GET_LAST_RESPONSE \
HttpRequest* request = g_request.getId(reqId); \
HttpResponse* response = request->lastResponse; \
if (response == nullptr) return Err::HTTP_SEND_REQUIRED;
static void deleteResponse(HttpResponse* response) {
if (response->body != nullptr) {
delete response->body;
}
delete response;
}
static int httpMethodStringToInt(const char* method) {
if (::_stricmp(method, "get") == 0) {
return SCE_HTTP_GET;
} else if (::_stricmp(method, "post") == 0) {
return SCE_HTTP_POST;
}
LOG_USE_MODULE(OnlineNetCore_http);
LOG_TRACE(L"unsupported http method: %s", method);
return -1;
}
static int32_t performHttpRequest(HttpRequestParams* request, HttpResponse* response) {
LOG_USE_MODULE(OnlineNetCore_http);
HttpConnection* connection = request->connection;
try {
if (!connection->connected) {
connection->query = new ip::tcp::resolver::query(request->serverName, std::to_string(request->port));
connection->endpoint_iterator = resolver.resolve(*connection->query);
connection->socket = new ip::tcp::socket(svc);
boost::asio::connect(*connection->socket, connection->endpoint_iterator);
connection->connected = true;
if (std::strcmp(connection->scheme, "https") == 0) {
LOG_TRACE(L"detected an attempt to connect via https, it's not supported yet");
return Err::HTTP_SSL_ERROR;
}
if (std::strcmp(connection->scheme, "http") != 0) {
LOG_TRACE(L"unknown scheme: %s://", connection->scheme);
return Err::HTTP_BAD_SCHEME;
}
}
if (request->request->lastResponse != nullptr) {
deleteResponse(request->request->lastResponse);
}
boost::asio::streambuf buffer;
std::ostream bufferStream(&buffer);
if (request->method == SCE_HTTP_GET) {
bufferStream << "GET ";
} else if (request->method == SCE_HTTP_POST) {
bufferStream << "POST ";
} else {
LOG_TRACE(L"unsupported request method code (%d), pretending we've failed to connect", request->method);
return Err::HTTP_FAILURE;
}
bufferStream << request->path;
if (request->httpVer == 1)
bufferStream << "HTTP/1.0";
else
bufferStream << "HTTP/1.1";
bufferStream << "\r\n";
if (request->httpVer != 1 /* means HTTP 1.1 */) {
bufferStream << "Host: " << request->serverName << "\r\n";
bufferStream << "User-Agent: " << request->userAgent << "\r\n";
bufferStream << "Accept: */*\r\n";
bufferStream << "Connection: " << (request->isEnableKeepalive ? "keep-alive" : "close") << "\r\n";
}
if (request->postData != nullptr) {
bufferStream << "Content-Length: " << request->contentLength << "\r\n\r\n";
for (size_t i = 0; i < request->size; i++) {
bufferStream << ((char*)request->postData)[i];
}
}
boost::asio::write(*connection->socket, buffer);
boost::asio::streambuf responseBuffer;
boost::asio::read_until(*connection->socket, responseBuffer, "\r\n");
std::istream responseBufferStream(&responseBuffer);
std::string httpVersion;
int statusCode;
std::string statusDescription;
responseBufferStream >> httpVersion;
responseBufferStream >> statusCode;
std::getline(responseBufferStream, statusDescription);
boost::asio::read_until(*connection->socket, responseBuffer, "\r\n\r\n");
bool foundContentLengthHeader = false;
uint32_t contentLength;
std::string header;
while (std::getline(responseBufferStream, header) && header != "\r") {
if (header.rfind("Content-Length: ", 0) == 0) { // todo: remove case-sensitive check
std::string contentLengthUnparsed = header.substr(16);
contentLength = std::stoi(contentLengthUnparsed);
foundContentLengthHeader = true;
break;
}
}
if (!foundContentLengthHeader) {
LOG_TRACE(L"failed to find \"Content-Length\" header in the response");
return Err::HTTP_FAILURE;
}
bool tooLow;
if ((tooLow = contentLength < 1) || contentLength > 1610612736) {
LOG_TRACE(L"bad content length: %s", (tooLow ? "less than 1 byte" : "more than 1.5 GiB"));
return Err::HTTP_FAILURE;
}
size_t currentIdx = 0;
char* body;
try {
body = new char[contentLength];
} catch (std::bad_alloc&) {
LOG_TRACE(L"failed to allocate %d bytes", contentLength);
return Err::HTTP_FAILURE;
}
response->statusCode = statusCode;
response->contentLength = contentLength;
response->body = body;
boost::system::error_code error;
while (boost::asio::read(*connection->socket, responseBuffer, boost::asio::transfer_at_least(1), error)) {
std::streamsize available = responseBuffer.in_avail();
char c;
for (std::streamsize i = 0; i < available; i++) {
responseBufferStream >> c;
body[currentIdx++] = c;
}
}
if (error != boost::asio::error::eof) throw boost::system::system_error(error);
return Ok;
} catch (const boost::exception& e) {
LOG_TRACE(L"caught a boost exception while performing an http request");
return Err::HTTP_FAILURE;
} catch (const std::exception& e) {
LOG_TRACE(L"caught an std::exception while performing an http request");
return Err::HTTP_FAILURE;
}
}
} // namespace
int OnlineNet::httpInit(int libnetMemId, int libsslCtxId, size_t poolSize) {
auto const handle = g_client.lookupAvailableIdx(new HttpClient(libnetMemId, libsslCtxId, poolSize));
if (handle == 0) return Err::HTTP_OUT_OF_MEMORY;
LOG_USE_MODULE(OnlineNetCore_http);
LOG_TRACE(L"new http client (id: %d, memId: %d, sslCtxId: %d, poolSize: %d)", handle, libnetMemId, libsslCtxId, poolSize);
return handle;
}
int OnlineNet::httpTerm(int libhttpCtxId) {
if (auto ret = g_client.testId(libhttpCtxId)) return ret;
g_client.remove(libhttpCtxId);
LOG_USE_MODULE(OnlineNetCore_http);
LOG_TRACE(L"http client removed (id: %d)", libhttpCtxId);
return Ok;
}
int OnlineNet::httpGetMemoryPoolStats(int libhttpCtxId, SceHttpMemoryPoolStats* currentStat) {
if (auto ret = g_client.testId(libhttpCtxId)) return ret;
currentStat->currentInuseSize = 16384; // todo (?)
currentStat->maxInuseSize = 131072;
currentStat->poolSize = g_client.getId(libhttpCtxId)->poolSize;
LOG_USE_MODULE(OnlineNetCore_http);
LOG_TRACE(L"memory pool stats were requested (client id: %d)", libhttpCtxId);
return Ok;
}
int OnlineNet::httpCreateTemplate(int libhttpCtxId, const char* userAgent, int httpVer, int isAutoProxyConf) {
if (auto ret = g_client.testId(libhttpCtxId)) return ret;
HttpClient* client = g_client.getId(libhttpCtxId);
auto const handle = g_template.lookupAvailableIdx(new HttpTemplate(client, userAgent, httpVer, isAutoProxyConf));
if (handle == 0) return Err::HTTP_OUT_OF_MEMORY;
LOG_USE_MODULE(OnlineNetCore_http);
LOG_TRACE(L"new http template (id: %d, client id: %d)", handle, libhttpCtxId);
return handle;
}
int OnlineNet::httpDeleteTemplate(int tmplId) {
if (auto ret = g_template.testId(tmplId)) return ret;
g_template.remove(tmplId);
LOG_USE_MODULE(OnlineNetCore_http);
LOG_TRACE(L"http template removed (id: %d)", tmplId);
return Ok;
}
static int sceHttpCreateConnection(int tmplId, const char* serverName, const char* scheme, uint16_t port, int isEnableKeepalive, bool shouldFreeStrings) {
if (auto ret = g_template.testId(tmplId)) return ret;
HttpTemplate* httpTemplate = g_template.getId(tmplId);
auto const handle = g_connection.lookupAvailableIdx(new HttpConnection(httpTemplate, serverName, scheme, port, isEnableKeepalive, shouldFreeStrings));
LOG_USE_MODULE(OnlineNetCore_http);
LOG_TRACE(L"new http connection (id: %d, template id: %d)", handle, tmplId);
return handle;
}
int OnlineNet::httpCreateConnection(int tmplId, const char* serverName, const char* scheme, uint16_t port, int isEnableKeepalive) {
return sceHttpCreateConnection(tmplId, serverName, scheme, port, isEnableKeepalive, false);
}
int OnlineNet::httpCreateConnectionWithURL(int tmplId, const char* url, int isEnableKeepalive) {
boost::urls::url link(url);
uint16_t port;
bool isNotHttp;
if ((isNotHttp = std::strcmp(link.scheme().data(), "http") != 0) && std::strcmp(link.scheme().data(), "https") != 0) {
return Err::HTTP_BAD_SCHEME;
}
if (link.has_port()) {
port = link.port_number();
} else {
if (isNotHttp)
port = 443;
else
port = 80;
}
int result = sceHttpCreateConnection(tmplId, link.host().data(), link.scheme().data(), port, isEnableKeepalive, true);
return result;
}
int OnlineNet::httpDeleteConnection(int connId) {
if (auto ret = g_connection.testId(connId)) return ret;
HttpConnection* connection = g_connection.getId(connId);
if (connection->query != nullptr) {
delete connection->query;
}
if (connection->socket != nullptr) {
connection->socket->close();
delete connection->socket;
}
if (connection->shouldFreeStrings) {
delete connection->scheme;
delete connection->serverName;
}
g_connection.remove(connId);
LOG_USE_MODULE(OnlineNetCore_http);
LOG_TRACE(L"http connection removed (id: %d)", connId);
return Ok;
}
static int sceHttpCreateRequest(int connId, int method, const char* path, uint64_t contentLength, bool shouldFreePath) {
if (auto ret = g_connection.testId(connId)) return ret;
HttpConnection* httpConnection = g_connection.getId(connId);
auto handle = g_request.lookupAvailableIdx(new HttpRequest(httpConnection, method, path, contentLength, shouldFreePath));
LOG_USE_MODULE(OnlineNetCore_http);
LOG_TRACE(L"new http request (id: %d, connection id: %d)", handle, connId);
return Ok;
}
int OnlineNet::httpCreateRequest(int connId, int method, const char* path, uint64_t contentLength) {
return sceHttpCreateRequest(connId, method, path, contentLength, false);
}
int OnlineNet::httpCreateRequest2(int connId, const char* method, const char* path, uint64_t contentLength) {
return httpCreateRequest(connId, httpMethodStringToInt(method), path, contentLength);
}
int OnlineNet::httpCreateRequestWithURL(int connId, int method, const char* url, uint64_t contentLength) {
boost::urls::url link(url);
if (link.has_password()) {
LOG_USE_MODULE(OnlineNetCore_http);
LOG_TRACE(L"urls containing credentials are not supported");
return Err::HTTP_BAD_PARAM;
}
int result = sceHttpCreateRequest(connId, method, link.path().data(), contentLength, true);
return result;
}
int OnlineNet::httpCreateRequestWithURL2(int connId, const char* method, const char* url, uint64_t contentLength) {
return httpCreateRequestWithURL(connId, httpMethodStringToInt(method), url, contentLength);
}
int OnlineNet::httpDeleteRequest(int reqId) {
if (auto ret = g_request.testId(reqId)) return ret;
HttpRequest* request = g_request.getId(reqId);
if (request->lastResponse != nullptr) {
deleteResponse(request->lastResponse);
}
if (request->shouldFreePath) {
delete request->path;
}
g_request.remove(reqId);
LOG_USE_MODULE(OnlineNetCore_http);
LOG_TRACE(L"http request removed (id: %d)", reqId);
return Ok;
}
int OnlineNet::httpSetRequestContentLength(int id, uint64_t contentLength) {
int reqId = id; // (?)
if (auto ret = g_request.testId(reqId)) return ret;
g_request.getId(reqId)->contentLength = contentLength;
return Ok;
}
int OnlineNet::httpSetChunkedTransferEnabled(int id, int isEnable) {
return Ok;
}
int OnlineNet::httpSetInflateGZIPEnabled(int id, int isEnable) {
return Ok;
}
int OnlineNet::httpSendRequest(int reqId, const void* postData, size_t size) {
if (auto ret = g_request.testId(reqId)) return ret;
HttpRequest* request = g_request.getId(reqId);
request->postData = postData;
request->size = size;
HttpRequestParams* fullParams = new HttpRequestParams(request);
HttpResponse* response = new HttpResponse();
int32_t result = performHttpRequest(fullParams, response);
delete fullParams;
if (result == Ok) {
request->lastResponse = response;
} else {
deleteResponse(response);
}
return result;
}
int OnlineNet::httpAbortRequest(int reqId) {
return Ok;
}
int OnlineNet::httpGetResponseContentLength(int reqId, int* result, uint64_t* contentLength) {
if (auto ret = g_request.testId(reqId)) return ret;
GET_LAST_RESPONSE;
*result = 0; // Content-Length is guaranteed to exist, otherwise performHttpRequest would have failed
*contentLength = response->contentLength;
return Ok;
}
int OnlineNet::httpGetStatusCode(int reqId, int* statusCode) {
if (auto ret = g_request.testId(reqId)) return ret;
GET_LAST_RESPONSE;
*statusCode = response->statusCode;
return Ok;
}
int OnlineNet::httpGetAllResponseHeaders(int reqId, char** header, size_t* headerSize) {
*headerSize = 0;
return Ok;
}
int OnlineNet::httpReadData(int reqId, void* data, size_t size) {
if (auto ret = g_request.testId(reqId)) return ret;
GET_LAST_RESPONSE;
size_t finalSize = min(size, response->contentLength);
memcpy(data, response->body, finalSize);
return Ok;
}
int OnlineNet::httpAddRequestHeader(int id, const char* name, const char* value, uint32_t mode) {
return Ok;
}
int OnlineNet::httpRemoveRequestHeader(int id, const char* name) {
return Ok;
}
int OnlineNet::httpParseResponseHeader(const char* header, size_t headerLen, const char* fieldStr, const char** fieldValue, size_t* valueLen) {
return Ok;
}
int OnlineNet::httpParseStatusLine(const char* statusLine, size_t lineLen, int* httpMajorVer, int* httpMinorVer, int* responseCode, const char** reasonPhrase,
size_t* phraseLen) {
return Ok;
}
int OnlineNet::httpSetResponseHeaderMaxSize(int id, size_t headerSize) {
return Ok;
}
int OnlineNet::httpSetAuthInfoCallback(int id, SceHttpAuthInfoCallback cbfunc, void* userArg) {
return Ok;
}
int OnlineNet::httpSetAuthEnabled(int id, int isEnable) {
return Ok;
}
int OnlineNet::httpGetAuthEnabled(int id, int* isEnable) {
return Ok;
}
int OnlineNet::httpAuthCacheFlush(int libhttpCtxId) {
return Ok;
}
int OnlineNet::httpSetRedirectCallback(int id, SceHttpRedirectCallback cbfunc, void* userArg) {
return Ok;
}
int OnlineNet::httpSetAutoRedirect(int id, int isEnable) {
return Ok;
}
int OnlineNet::httpGetAutoRedirect(int id, int* isEnable) {
return Ok;
}
int OnlineNet::httpRedirectCacheFlush(int libhttpCtxId) {
return Ok;
}
int OnlineNet::httpSetResolveTimeOut(int id, uint32_t usec) {
return Ok;
}
int OnlineNet::httpSetResolveRetry(int id, int retry) {
return Ok;
}
int OnlineNet::httpSetConnectTimeOut(int id, uint32_t usec) {
return Ok;
}
int OnlineNet::httpSetSendTimeOut(int id, uint32_t usec) {
return Err::SEND_TIMEOUT;
}
int OnlineNet::httpSetRecvTimeOut(int id, uint32_t usec) {
return Ok;
}
int OnlineNet::httpSetRequestStatusCallback(int id, SceHttpRequestStatusCallback cbfunc, void* userArg) {
return Ok;
}
int OnlineNet::httpGetLastErrno(int reqId, int* errNum) {
return Ok;
}
int OnlineNet::httpSetNonblock(int id, int isEnable) {
return Ok;
}
int OnlineNet::httpGetNonblock(int id, int* isEnable) {
return Ok;
}
int OnlineNet::httpTrySetNonblock(int id, int isEnable) {
return Ok;
}
int OnlineNet::httpTryGetNonblock(int id, int* isEnable) {
return Ok;
}
int OnlineNet::httpCreateEpoll(int libhttpCtxId, SceHttpEpollHandle* eh) {
return Ok;
}
int OnlineNet::httpSetEpoll(int id, SceHttpEpollHandle eh, void* userArg) {
return Ok;
}
int OnlineNet::httpUnsetEpoll(int id) {
return Ok;
}
int OnlineNet::httpGetEpoll(int id, SceHttpEpollHandle* eh, void** userArg) {
return Ok;
}
int OnlineNet::httpDestroyEpoll(int libhttpCtxId, SceHttpEpollHandle eh) {
return Ok;
}
int OnlineNet::httpWaitRequest(SceHttpEpollHandle eh, SceHttpNBEvent* nbev, int maxevents, int timeout) {
return Ok;
}
int OnlineNet::httpAbortWaitRequest(SceHttpEpollHandle eh) {
return Ok;
}
// HTTPS
int OnlineNet::httpsLoadCert(int libhttpCtxId, int caCertNum, const SceSslData** caList, const SceSslData* cert, const SceSslData* privKey) {
return Ok;
}
int OnlineNet::httpsUnloadCert(int libhttpCtxId) {
return Ok;
}
int OnlineNet::httpsEnableOption(int id, uint32_t sslFlags) {
return Ok;
}
int OnlineNet::httpsDisableOption(int id, uint32_t sslFlags) {
return Ok;
}
int OnlineNet::httpsGetSslError(int id, int* errNum, uint32_t* detail) {
return Ok;
}
int OnlineNet::httpsSetSslCallback(int id, SceHttpsCallback cbfunc, void* userArg) {
return Ok;
}
int OnlineNet::httpsSetSslVersion(int id, SceSslVersion version) {
return Ok;
}

View File

@ -5,8 +5,7 @@ set(libName libSceHttp)
project(${libName})
add_library(${libName} SHARED entry.cpp)
add_dependencies(${libName} third_party)
target_link_libraries(${libName} PUBLIC libboost_url)
target_compile_definitions(${libName} PRIVATE BOOST_ALL_NO_LIB)
add_dependencies(${libName} core)
target_link_libraries(${libName} PUBLIC core.lib)
setupModule(${libName})
setupModule(${libName})

View File

@ -1,728 +1,253 @@
#include "../libSceSsl/types.h"
#include "common.h"
#include "core/networking/networking.h"
#include "httpsTypes.h"
#include "logging.h"
#include "types.h"
#include "utility/utility.h"
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <boost/asio.hpp>
#include <boost/url.hpp>
using namespace boost::asio;
LOG_DEFINE_MODULE(libSceHttp);
namespace {
using SceHttpsCallback = SYSV_ABI int (*)(int libsslCtxId, unsigned int verifyErr, SceSslCert* const sslCert[], int certNum, void* userArg);
constexpr size_t ARRAY_LENGTH = 128;
template <typename T, size_t size>
class HttpContainer {
T* m_data[size] = {nullptr};
public:
int lookupAvailableIdx(T* action) {
int i;
bool found = false;
for (i = 1; i < size; i++) {
if (!m_data[i]) {
m_data[i] = action;
break;
}
}
if (found == false) {
delete action;
return 0;
}
return i;
}
int testId(int id) {
if (id < 1 || id >= size || m_data[id] == nullptr) return Err::HTTP_BAD_ID;
return Ok;
}
void remove(int id) {
delete m_data[id];
m_data[id] = nullptr;
}
T* getId(int id) { return m_data[id]; }
};
static io_service svc;
static ip::tcp::resolver resolver(svc);
struct HttpClient {
int libnetMemId;
int libsslCtxId;
size_t poolSize;
uint32_t connectTimeout;
HttpClient(int libnetMemId, int libsslCtxId, size_t poolSize): libnetMemId(libnetMemId), libsslCtxId(libsslCtxId), poolSize(poolSize) {}
};
struct HttpTemplate {
HttpClient* parentClient;
const char* userAgent;
int httpVer;
int isAutoProxyConf;
HttpTemplate(HttpClient* parentClient, const char* userAgent, int httpVer, int isAutoProxyConf)
: parentClient(parentClient), userAgent(userAgent), httpVer(httpVer), isAutoProxyConf(isAutoProxyConf) {}
};
struct HttpConnection {
HttpTemplate* parentTemplate;
const char* serverName;
const char* scheme;
uint16_t port;
int isEnableKeepalive;
bool connected = false;
bool shouldFreeStrings;
ip::tcp::resolver::query* query = nullptr;
ip::tcp::resolver::iterator endpoint_iterator;
ip::tcp::socket* socket = nullptr;
HttpConnection(HttpTemplate* parentTemplate, const char* serverName, const char* scheme, uint16_t port, int isEnableKeepalive, bool shouldFreeStrings)
: parentTemplate(parentTemplate), serverName(serverName), scheme(scheme), port(port), isEnableKeepalive(isEnableKeepalive),
shouldFreeStrings(shouldFreeStrings) {}
};
struct HttpResponse {
int statusCode;
uint32_t contentLength;
const char* body = nullptr;
};
struct HttpRequest {
HttpConnection* parentConnection;
int method;
const char* path;
uint64_t contentLength;
const void* postData = nullptr;
size_t size;
HttpResponse* lastResponse = nullptr;
bool shouldFreePath;
HttpRequest(HttpConnection* parentConnection, int method, const char* path, uint64_t contentLength, bool shouldFreePath)
: parentConnection(parentConnection), method(method), path(path), contentLength(contentLength), shouldFreePath(shouldFreePath) {}
};
struct HttpRequestParams {
HttpConnection* connection;
HttpRequest* request;
uint32_t connectTimeout;
const char* userAgent;
int httpVer;
int isAutoProxyConf;
const char* serverName;
const char* scheme;
uint16_t port;
int isEnableKeepalive;
int method;
const char* path;
uint64_t contentLength;
const void* postData; // will be assigned to nullptr
size_t size;
HttpRequestParams(HttpRequest* from) {
connection = from->parentConnection;
request = from;
connectTimeout = from->parentConnection->parentTemplate->parentClient->connectTimeout;
userAgent = from->parentConnection->parentTemplate->userAgent;
httpVer = from->parentConnection->parentTemplate->httpVer;
isAutoProxyConf = from->parentConnection->parentTemplate->isAutoProxyConf;
serverName = from->parentConnection->serverName;
scheme = from->parentConnection->scheme;
port = from->parentConnection->port;
isEnableKeepalive = from->parentConnection->isEnableKeepalive;
method = from->method;
path = from->path;
contentLength = from->contentLength;
postData = from->postData;
size = from->size;
}
};
static HttpContainer<HttpClient, ARRAY_LENGTH> g_client;
static HttpContainer<HttpTemplate, ARRAY_LENGTH> g_template;
static HttpContainer<HttpConnection, ARRAY_LENGTH> g_connection;
static HttpContainer<HttpRequest, ARRAY_LENGTH> g_request;
#define GET_LAST_RESPONSE \
HttpRequest* request = g_request.getId(reqId); \
HttpResponse* response = request->lastResponse; \
if (response == nullptr) return Err::HTTP_SEND_REQUIRED;
static void deleteResponse(HttpResponse* response) {
if (response->body != nullptr) {
delete response->body;
}
delete response;
}
static int httpMethodStringToInt(const char* method) {
if (std::strcmp(method, "get") == 0 || std::strcmp(method, "GET") == 0) {
return SCE_HTTP_GET;
} else if (std::strcmp(method, "post") == 0 || std::strcmp(method, "POST") == 0) {
return SCE_HTTP_POST;
}
LOG_USE_MODULE(libSceHttp);
LOG_TRACE(L"unsupported http method: %s", method);
return -1;
}
static int32_t performHttpRequest(HttpRequestParams* request, HttpResponse* response) {
LOG_USE_MODULE(libSceHttp);
HttpConnection* connection = request->connection;
try {
if (!connection->connected) {
connection->query = new ip::tcp::resolver::query(request->serverName, std::to_string(request->port));
connection->endpoint_iterator = resolver.resolve(*connection->query);
connection->socket = new ip::tcp::socket(svc);
boost::asio::connect(*connection->socket, connection->endpoint_iterator);
connection->connected = true;
if (std::strcmp(connection->scheme, "https") == 0) {
LOG_TRACE(L"detected an attempt to connect via https, it's not supported yet");
return Err::HTTP_SSL_ERROR;
}
if (std::strcmp(connection->scheme, "http") != 0) {
LOG_TRACE(L"unknown scheme: %s://", connection->scheme);
return Err::HTTP_BAD_SCHEME;
}
}
if (request->request->lastResponse != nullptr) {
deleteResponse(request->request->lastResponse);
}
boost::asio::streambuf buffer;
std::ostream bufferStream(&buffer);
if (request->method == SCE_HTTP_GET) {
bufferStream << "GET ";
} else if (request->method == SCE_HTTP_POST) {
bufferStream << "POST ";
} else {
LOG_TRACE(L"unsupported request method code (%d), pretending we've failed to connect", request->method);
return Err::HTTP_FAILURE;
}
bufferStream << request->path;
if (request->httpVer == 1)
bufferStream << "HTTP/1.0";
else
bufferStream << "HTTP/1.1";
bufferStream << "\r\n";
if (request->httpVer != 1 /* means HTTP 1.1 */) {
bufferStream << "Host: " << request->serverName << "\r\n";
bufferStream << "User-Agent: " << request->userAgent << "\r\n";
bufferStream << "Accept: */*\r\n";
bufferStream << "Connection: " << (request->isEnableKeepalive ? "keep-alive" : "close") << "\r\n";
}
if (request->postData != nullptr) {
bufferStream << "Content-Length: " << request->contentLength << "\r\n\r\n";
for (size_t i = 0; i < request->size; i++) {
bufferStream << ((char*)request->postData)[i];
}
}
boost::asio::write(*connection->socket, buffer);
boost::asio::streambuf responseBuffer;
boost::asio::read_until(*connection->socket, responseBuffer, "\r\n");
std::istream responseBufferStream(&responseBuffer);
std::string httpVersion;
int statusCode;
std::string statusDescription;
responseBufferStream >> httpVersion;
responseBufferStream >> statusCode;
std::getline(responseBufferStream, statusDescription);
boost::asio::read_until(*connection->socket, responseBuffer, "\r\n\r\n");
bool foundContentLengthHeader = false;
uint32_t contentLength;
std::string header;
while (std::getline(responseBufferStream, header) && header != "\r") {
if (header.rfind("Content-Length: ", 0) == 0) { // todo: remove case-sensitive check
std::string contentLengthUnparsed = header.substr(16);
contentLength = std::stoi(contentLengthUnparsed);
foundContentLengthHeader = true;
break;
}
}
if (!foundContentLengthHeader) {
LOG_TRACE(L"failed to find \"Content-Length\" header in the response");
return Err::HTTP_FAILURE;
}
bool tooLow;
if ((tooLow = contentLength < 1) || contentLength > 1610612736) {
LOG_TRACE(L"bad content length: %s", (tooLow ? "less than 1 byte" : "more than 1.5 GiB"));
return Err::HTTP_FAILURE;
}
size_t currentIdx = 0;
char* body;
try {
body = new char[contentLength];
} catch (std::bad_alloc&) {
LOG_TRACE(L"failed to allocate %d bytes", contentLength);
return Err::HTTP_FAILURE;
}
response->statusCode = statusCode;
response->contentLength = contentLength;
response->body = body;
boost::system::error_code error;
while (boost::asio::read(*connection->socket, responseBuffer, boost::asio::transfer_at_least(1), error)) {
std::streamsize available = responseBuffer.in_avail();
char c;
for (std::streamsize i = 0; i < available; i++) {
responseBufferStream >> c;
body[currentIdx++] = c;
}
}
if (error != boost::asio::error::eof) throw boost::system::system_error(error);
return Ok;
} catch (const boost::exception& e) {
LOG_TRACE(L"caught a boost exception while performing an http request");
return Err::HTTP_FAILURE;
} catch (const std::exception& e) {
LOG_TRACE(L"caught an std::exception while performing an http request");
return Err::HTTP_FAILURE;
}
}
} // namespace
extern "C" {
EXPORT const char* MODULE_NAME = "libSceHttp";
EXPORT SYSV_ABI int sceHttpInit(int libnetMemId, int libsslCtxId, size_t poolSize) {
auto const handle = g_client.lookupAvailableIdx(new HttpClient(libnetMemId, libsslCtxId, poolSize));
if (handle == 0) return Err::HTTP_OUT_OF_MEMORY;
LOG_USE_MODULE(libSceHttp);
LOG_TRACE(L"new http client (id: %d, memId: %d, sslCtxId: %d, poolSize: %d)", handle, libnetMemId, libsslCtxId, poolSize);
return handle;
return accessNetworking().httpInit(libnetMemId, libsslCtxId, poolSize);
}
EXPORT SYSV_ABI int sceHttpTerm(int libhttpCtxId) {
if (auto ret = g_client.testId(libhttpCtxId)) return ret;
g_client.remove(libhttpCtxId);
LOG_USE_MODULE(libSceHttp);
LOG_TRACE(L"http client removed (id: %d)", libhttpCtxId);
return Ok;
return accessNetworking().httpTerm(libhttpCtxId);
}
EXPORT SYSV_ABI int sceHttpGetMemoryPoolStats(int libhttpCtxId, SceHttpMemoryPoolStats* currentStat) {
if (auto ret = g_client.testId(libhttpCtxId)) return ret;
currentStat->currentInuseSize = 16384; // todo (?)
currentStat->maxInuseSize = 131072;
currentStat->poolSize = g_client.getId(libhttpCtxId)->poolSize;
LOG_USE_MODULE(libSceHttp);
LOG_TRACE(L"memory pool stats were requested (client id: %d)", libhttpCtxId);
return Ok;
return accessNetworking().httpGetMemoryPoolStats(libhttpCtxId, currentStat);
}
EXPORT SYSV_ABI int sceHttpCreateTemplate(int libhttpCtxId, const char* userAgent, int httpVer, int isAutoProxyConf) {
if (auto ret = g_client.testId(libhttpCtxId)) return ret;
HttpClient* client = g_client.getId(libhttpCtxId);
auto const handle = g_template.lookupAvailableIdx(new HttpTemplate(client, userAgent, httpVer, isAutoProxyConf));
if (handle == 0) return Err::HTTP_OUT_OF_MEMORY;
LOG_USE_MODULE(libSceHttp);
LOG_TRACE(L"new http template (id: %d, client id: %d)", handle, libhttpCtxId);
return handle;
return accessNetworking().httpCreateTemplate(libhttpCtxId, userAgent, httpVer, isAutoProxyConf);
}
EXPORT SYSV_ABI int sceHttpDeleteTemplate(int tmplId) {
if (auto ret = g_template.testId(tmplId)) return ret;
g_template.remove(tmplId);
LOG_USE_MODULE(libSceHttp);
LOG_TRACE(L"http template removed (id: %d)", tmplId);
return Ok;
}
static int sceHttpCreateConnection(int tmplId, const char* serverName, const char* scheme, uint16_t port, int isEnableKeepalive, bool shouldFreeStrings) {
if (auto ret = g_template.testId(tmplId)) return ret;
HttpTemplate* httpTemplate = g_template.getId(tmplId);
auto const handle = g_connection.lookupAvailableIdx(new HttpConnection(httpTemplate, serverName, scheme, port, isEnableKeepalive, shouldFreeStrings));
LOG_USE_MODULE(libSceHttp);
LOG_TRACE(L"new http connection (id: %d, template id: %d)", handle, tmplId);
return handle;
return accessNetworking().httpDeleteTemplate(tmplId);
}
EXPORT SYSV_ABI int sceHttpCreateConnection(int tmplId, const char* serverName, const char* scheme, uint16_t port, int isEnableKeepalive) {
return sceHttpCreateConnection(tmplId, serverName, scheme, port, isEnableKeepalive, false);
return accessNetworking().httpCreateConnection(tmplId, serverName, scheme, port, isEnableKeepalive);
}
EXPORT SYSV_ABI int sceHttpCreateConnectionWithURL(int tmplId, const char* url, int isEnableKeepalive) {
boost::urls::url link(url);
uint16_t port;
bool isNotHttp;
if ((isNotHttp = std::strcmp(link.scheme().data(), "http") != 0) && std::strcmp(link.scheme().data(), "https") != 0) {
return Err::HTTP_BAD_SCHEME;
}
if (link.has_port()) {
port = link.port_number();
} else {
if (isNotHttp)
port = 443;
else
port = 80;
}
int result = sceHttpCreateConnection(tmplId, link.host().data(), link.scheme().data(), port, isEnableKeepalive, true);
return result;
return accessNetworking().httpCreateConnectionWithURL(tmplId, url, isEnableKeepalive);
}
EXPORT SYSV_ABI int sceHttpDeleteConnection(int connId) {
if (auto ret = g_connection.testId(connId)) return ret;
HttpConnection* connection = g_connection.getId(connId);
if (connection->query != nullptr) {
delete connection->query;
}
if (connection->socket != nullptr) {
connection->socket->close();
delete connection->socket;
}
if (connection->shouldFreeStrings) {
delete connection->scheme;
delete connection->serverName;
}
g_connection.remove(connId);
LOG_USE_MODULE(libSceHttp);
LOG_TRACE(L"http connection removed (id: %d)", connId);
return Ok;
}
static int sceHttpCreateRequest(int connId, int method, const char* path, uint64_t contentLength, bool shouldFreePath) {
if (auto ret = g_connection.testId(connId)) return ret;
HttpConnection* httpConnection = g_connection.getId(connId);
auto handle = g_request.lookupAvailableIdx(new HttpRequest(httpConnection, method, path, contentLength, shouldFreePath));
LOG_USE_MODULE(libSceHttp);
LOG_TRACE(L"new http request (id: %d, connection id: %d)", handle, connId);
return Ok;
return accessNetworking().httpDeleteConnection(connId);
}
EXPORT SYSV_ABI int sceHttpCreateRequest(int connId, int method, const char* path, uint64_t contentLength) {
return sceHttpCreateRequest(connId, method, path, contentLength, false);
return accessNetworking().httpCreateRequest(connId, method, path, contentLength);
}
EXPORT SYSV_ABI int sceHttpCreateRequest2(int connId, const char* method, const char* path, uint64_t contentLength) {
return sceHttpCreateRequest(connId, httpMethodStringToInt(method), path, contentLength);
return accessNetworking().httpCreateRequest2(connId, method, path, contentLength);
}
EXPORT SYSV_ABI int sceHttpCreateRequestWithURL(int connId, int method, const char* url, uint64_t contentLength) {
boost::urls::url link(url);
if (link.has_password()) {
LOG_USE_MODULE(libSceHttp);
LOG_TRACE(L"urls containing credentials are not supported");
return Err::HTTP_BAD_PARAM;
}
int result = sceHttpCreateRequest(connId, method, link.path().data(), contentLength, true);
return result;
return accessNetworking().httpCreateRequestWithURL(connId, method, url, contentLength);
}
EXPORT SYSV_ABI int sceHttpCreateRequestWithURL2(int connId, const char* method, const char* url, uint64_t contentLength) {
return sceHttpCreateRequestWithURL(connId, httpMethodStringToInt(method), url, contentLength);
return accessNetworking().httpCreateRequestWithURL2(connId, method, url, contentLength);
}
EXPORT SYSV_ABI int sceHttpDeleteRequest(int reqId) {
if (auto ret = g_request.testId(reqId)) return ret;
HttpRequest* request = g_request.getId(reqId);
if (request->lastResponse != nullptr) {
deleteResponse(request->lastResponse);
}
if (request->shouldFreePath) {
delete request->path;
}
g_request.remove(reqId);
LOG_USE_MODULE(libSceHttp);
LOG_TRACE(L"http request removed (id: %d)", reqId);
return Ok;
return accessNetworking().httpDeleteRequest(reqId);
}
EXPORT SYSV_ABI int sceHttpSetRequestContentLength(int id, uint64_t contentLength) {
int reqId = id; // (?)
if (auto ret = g_request.testId(reqId)) return ret;
g_request.getId(reqId)->contentLength = contentLength;
return Ok;
return accessNetworking().httpSetRequestContentLength(id, contentLength);
}
EXPORT SYSV_ABI int sceHttpSetChunkedTransferEnabled(int id, int isEnable) {
return Ok;
return accessNetworking().httpSetChunkedTransferEnabled(id, isEnable);
}
EXPORT SYSV_ABI int sceHttpSetInflateGZIPEnabled(int id, int isEnable) {
return Ok;
return accessNetworking().httpSetInflateGZIPEnabled(id, isEnable);
}
EXPORT SYSV_ABI int sceHttpSendRequest(int reqId, const void* postData, size_t size) {
if (auto ret = g_request.testId(reqId)) return ret;
HttpRequest* request = g_request.getId(reqId);
request->postData = postData;
request->size = size;
HttpRequestParams* fullParams = new HttpRequestParams(request);
HttpResponse* response = new HttpResponse();
int32_t result = performHttpRequest(fullParams, response);
delete fullParams;
if (result == Ok) {
request->lastResponse = response;
} else {
deleteResponse(response);
}
return result;
return accessNetworking().httpSendRequest(reqId, postData, size);
}
EXPORT SYSV_ABI int sceHttpAbortRequest(int reqId) {
return Ok;
return accessNetworking().httpAbortRequest(reqId);
}
EXPORT SYSV_ABI int sceHttpGetResponseContentLength(int reqId, int* result, uint64_t* contentLength) {
if (auto ret = g_request.testId(reqId)) return ret;
GET_LAST_RESPONSE;
*result = 0; // Content-Length is guaranteed to exist, otherwise performHttpRequest would have failed
*contentLength = response->contentLength;
return Ok;
return accessNetworking().httpGetResponseContentLength(reqId, result, contentLength);
}
EXPORT SYSV_ABI int sceHttpGetStatusCode(int reqId, int* statusCode) {
if (auto ret = g_request.testId(reqId)) return ret;
GET_LAST_RESPONSE;
*statusCode = response->statusCode;
return Ok;
return accessNetworking().httpGetStatusCode(reqId, statusCode);
}
EXPORT SYSV_ABI int sceHttpGetAllResponseHeaders(int reqId, char** header, size_t* headerSize) {
*headerSize = 0;
return Ok;
return accessNetworking().httpGetAllResponseHeaders(reqId, header, headerSize);
}
EXPORT SYSV_ABI int sceHttpReadData(int reqId, void* data, size_t size) {
if (auto ret = g_request.testId(reqId)) return ret;
GET_LAST_RESPONSE;
size_t finalSize = min(size, response->contentLength);
memcpy(data, response->body, finalSize);
return Ok;
return accessNetworking().httpReadData(reqId, data, size);
}
EXPORT SYSV_ABI int sceHttpAddRequestHeader(int id, const char* name, const char* value, uint32_t mode) {
return Ok;
return accessNetworking().httpAddRequestHeader(id, name, value, mode);
}
EXPORT SYSV_ABI int sceHttpRemoveRequestHeader(int id, const char* name) {
return Ok;
return accessNetworking().httpRemoveRequestHeader(id, name);
}
EXPORT SYSV_ABI int sceHttpParseResponseHeader(const char* header, size_t headerLen, const char* fieldStr, const char** fieldValue, size_t* valueLen) {
return Ok;
return accessNetworking().httpParseResponseHeader(header, headerLen, fieldStr, fieldValue, valueLen);
}
EXPORT SYSV_ABI int sceHttpParseStatusLine(const char* statusLine, size_t lineLen, int* httpMajorVer, int* httpMinorVer, int* responseCode,
const char** reasonPhrase, size_t* phraseLen) {
return Ok;
return accessNetworking().httpParseStatusLine(statusLine, lineLen, httpMajorVer, httpMinorVer, responseCode, reasonPhrase, phraseLen);
}
EXPORT SYSV_ABI int sceHttpSetResponseHeaderMaxSize(int id, size_t headerSize) {
return Ok;
return accessNetworking().httpSetResponseHeaderMaxSize(id, headerSize);
}
EXPORT SYSV_ABI int sceHttpSetAuthInfoCallback(int id, SceHttpAuthInfoCallback cbfunc, void* userArg) {
return Ok;
return accessNetworking().httpSetAuthInfoCallback(id, cbfunc, userArg);
}
EXPORT SYSV_ABI int sceHttpSetAuthEnabled(int id, int isEnable) {
return Ok;
return accessNetworking().httpSetAuthEnabled(id, isEnable);
}
EXPORT SYSV_ABI int sceHttpGetAuthEnabled(int id, int* isEnable) {
return Ok;
return accessNetworking().httpGetAuthEnabled(id, isEnable);
}
EXPORT SYSV_ABI int sceHttpAuthCacheFlush(int libhttpCtxId) {
return Ok;
return accessNetworking().httpAuthCacheFlush(libhttpCtxId);
}
EXPORT SYSV_ABI int sceHttpSetRedirectCallback(int id, SceHttpRedirectCallback cbfunc, void* userArg) {
return Ok;
return accessNetworking().httpSetRedirectCallback(id, cbfunc, userArg);
}
EXPORT SYSV_ABI int sceHttpSetAutoRedirect(int id, int isEnable) {
return Ok;
return accessNetworking().httpSetAutoRedirect(id, isEnable);
}
EXPORT SYSV_ABI int sceHttpGetAutoRedirect(int id, int* isEnable) {
return Ok;
return accessNetworking().httpGetAutoRedirect(id, isEnable);
}
EXPORT SYSV_ABI int sceHttpRedirectCacheFlush(int libhttpCtxId) {
return Ok;
return accessNetworking().httpRedirectCacheFlush(libhttpCtxId);
}
EXPORT SYSV_ABI int sceHttpSetResolveTimeOut(int id, uint32_t usec) {
return Ok;
return accessNetworking().httpSetResolveTimeOut(id, usec);
}
EXPORT SYSV_ABI int sceHttpSetResolveRetry(int id, int retry) {
return Ok;
return accessNetworking().httpSetResolveRetry(id, retry);
}
EXPORT SYSV_ABI int sceHttpSetConnectTimeOut(int id, uint32_t usec) {
return Ok;
return accessNetworking().httpSetConnectTimeOut(id, usec);
}
EXPORT SYSV_ABI int sceHttpSetSendTimeOut(int id, uint32_t usec) {
return Err::SEND_TIMEOUT;
return accessNetworking().httpSetSendTimeOut(id, usec);
}
EXPORT SYSV_ABI int sceHttpSetRecvTimeOut(int id, uint32_t usec) {
return Ok;
return accessNetworking().httpSetRecvTimeOut(id, usec);
}
EXPORT SYSV_ABI int sceHttpSetRequestStatusCallback(int id, SceHttpRequestStatusCallback cbfunc, void* userArg) {
return Ok;
return accessNetworking().httpSetRequestStatusCallback(id, cbfunc, userArg);
}
EXPORT SYSV_ABI int sceHttpGetLastErrno(int reqId, int* errNum) {
return Ok;
return accessNetworking().httpGetLastErrno(reqId, errNum);
}
EXPORT SYSV_ABI int sceHttpSetNonblock(int id, int isEnable) {
return Ok;
return accessNetworking().httpSetNonblock(id, isEnable);
}
EXPORT SYSV_ABI int sceHttpGetNonblock(int id, int* isEnable) {
return Ok;
return accessNetworking().httpGetNonblock(id, isEnable);
}
EXPORT SYSV_ABI int sceHttpTrySetNonblock(int id, int isEnable) {
return Ok;
return accessNetworking().httpTrySetNonblock(id, isEnable);
}
EXPORT SYSV_ABI int sceHttpTryGetNonblock(int id, int* isEnable) {
return Ok;
return accessNetworking().httpTryGetNonblock(id, isEnable);
}
EXPORT SYSV_ABI int sceHttpCreateEpoll(int libhttpCtxId, SceHttpEpollHandle* eh) {
return Ok;
return accessNetworking().httpCreateEpoll(libhttpCtxId, eh);
}
EXPORT SYSV_ABI int sceHttpSetEpoll(int id, SceHttpEpollHandle eh, void* userArg) {
return Ok;
return accessNetworking().httpSetEpoll(id, eh, userArg);
}
EXPORT SYSV_ABI int sceHttpUnsetEpoll(int id) {
return Ok;
return accessNetworking().httpUnsetEpoll(id);
}
EXPORT SYSV_ABI int sceHttpGetEpoll(int id, SceHttpEpollHandle* eh, void** userArg) {
return Ok;
return accessNetworking().httpGetEpoll(id, eh, userArg);
}
EXPORT SYSV_ABI int sceHttpDestroyEpoll(int libhttpCtxId, SceHttpEpollHandle eh) {
return Ok;
return accessNetworking().httpDestroyEpoll(libhttpCtxId, eh);
}
EXPORT SYSV_ABI int sceHttpWaitRequest(SceHttpEpollHandle eh, SceHttpNBEvent* nbev, int maxevents, int timeout) {
return Ok;
return accessNetworking().httpWaitRequest(eh, nbev, maxevents, timeout);
}
EXPORT SYSV_ABI int sceHttpAbortWaitRequest(SceHttpEpollHandle eh) {
return Ok;
return accessNetworking().httpAbortWaitRequest(eh);
}
// HTTPS
EXPORT SYSV_ABI int sceHttpsLoadCert(int libhttpCtxId, int caCertNum, const SceSslData** caList, const SceSslData* cert, const SceSslData* privKey) {
return Ok;
return accessNetworking().httpsLoadCert(libhttpCtxId, caCertNum, caList, cert, privKey);
}
EXPORT SYSV_ABI int sceHttpsUnloadCert(int libhttpCtxId) {
return Ok;
return accessNetworking().httpsUnloadCert(libhttpCtxId);
}
EXPORT SYSV_ABI int sceHttpsEnableOption(int id, uint32_t sslFlags) {
return Ok;
return accessNetworking().httpsEnableOption(id, sslFlags);
}
EXPORT SYSV_ABI int sceHttpsDisableOption(int id, uint32_t sslFlags) {
return Ok;
return accessNetworking().httpsDisableOption(id, sslFlags);
}
EXPORT SYSV_ABI int sceHttpsGetSslError(int id, int* errNum, uint32_t* detail) {
return Ok;
return accessNetworking().httpsGetSslError(id, errNum, detail);
}
EXPORT SYSV_ABI int sceHttpsSetSslCallback(int id, SceHttpsCallback cbfunc, void* userArg) {
return Ok;
return accessNetworking().httpsSetSslCallback(id, cbfunc, userArg);
}
EXPORT SYSV_ABI int sceHttpsSetSslVersion(int id, SceSslVersion version) {
return Ok;
return accessNetworking().httpsSetSslVersion(id, version);
}
}

View File

@ -1,5 +1,7 @@
#pragma once
#include "../libSceSsl/types.h"
enum class SceHttpsFlags : unsigned int {
SERVER_VERIFY = 0x01U, // Server Certificate Verify
CLIENT_VERIFY = 0x02U, // Client Certificate Verify
@ -12,4 +14,6 @@ enum class SceHttpsFlags : unsigned int {
};
enum class SceHttpSslVersion { SSLV23, SSLV2, SSLV3, TLSV1 };
enum class SceHttpSslVersion { SSLV23, SSLV2, SSLV3, TLSV1 };
using SceHttpsCallback = SYSV_ABI int (*)(int libsslCtxId, unsigned int verifyErr, SceSslCert* const sslCert[], int certNum, void* userArg);

View File

@ -57,4 +57,4 @@ struct SceHttpNBEvent {
uint32_t eventDetail;
int id;
void* userArg;
};
};