mirror of
https://github.com/SysRay/psOff_public.git
synced 2025-02-11 09:25:18 +00:00
Move http to core/networking
This commit is contained in:
parent
5853b969cc
commit
a4a54b34c4
@ -33,6 +33,7 @@ add_library(core SHARED
|
|||||||
|
|
||||||
add_dependencies(core logging third_party config_emu gamereport)
|
add_dependencies(core logging third_party config_emu gamereport)
|
||||||
target_link_libraries(core PRIVATE
|
target_link_libraries(core PRIVATE
|
||||||
|
libboost_url
|
||||||
libboost_thread
|
libboost_thread
|
||||||
libboost_chrono
|
libboost_chrono
|
||||||
libboost_program_options
|
libboost_program_options
|
||||||
|
@ -5,6 +5,7 @@ add_library(networking OBJECT
|
|||||||
states/online/resolver.cpp
|
states/online/resolver.cpp
|
||||||
states/online/socket.cpp
|
states/online/socket.cpp
|
||||||
states/online/epoll.cpp
|
states/online/epoll.cpp
|
||||||
|
states/online/http.cpp
|
||||||
wepoll.c
|
wepoll.c
|
||||||
|
|
||||||
networking.cpp
|
networking.cpp
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "modules/libSceHttp/httpsTypes.h"
|
||||||
|
#include "modules/libSceHttp/types.h"
|
||||||
#include "modules/libSceNet/resolverTypes.h"
|
#include "modules/libSceNet/resolverTypes.h"
|
||||||
#include "modules/libSceNet/socketTypes.h"
|
#include "modules/libSceNet/socketTypes.h"
|
||||||
#include "modules/libSceNet/types.h"
|
#include "modules/libSceNet/types.h"
|
||||||
#include "modules/libSceNetCtl/types.h"
|
#include "modules/libSceNetCtl/types.h"
|
||||||
|
#include "modules/libSceSsl/types.h"
|
||||||
#include "modules_include/common.h"
|
#include "modules_include/common.h"
|
||||||
#include "utility/utility.h"
|
#include "utility/utility.h"
|
||||||
|
|
||||||
@ -79,6 +82,73 @@ class INetworking {
|
|||||||
virtual int socketShutdown(SceNetId s, int how) = 0;
|
virtual int socketShutdown(SceNetId s, int how) = 0;
|
||||||
virtual int socketClose(SceNetId s) = 0;
|
virtual int socketClose(SceNetId s) = 0;
|
||||||
virtual int socketAbort(SceNetId s, int flags) = 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)
|
#if defined(__APICALL_EXTERN)
|
||||||
|
@ -135,3 +135,253 @@ int OfflineNet::socketClose(SceNetId s) {
|
|||||||
int OfflineNet::socketAbort(SceNetId s, int flags) {
|
int OfflineNet::socketAbort(SceNetId s, int flags) {
|
||||||
return Ok;
|
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;
|
||||||
|
}
|
||||||
|
@ -51,4 +51,71 @@ class OfflineNet: public INetworking {
|
|||||||
int socketShutdown(SceNetId s, int how) final;
|
int socketShutdown(SceNetId s, int how) final;
|
||||||
int socketClose(SceNetId s) final;
|
int socketClose(SceNetId s) final;
|
||||||
int socketAbort(SceNetId s, int flags) 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;
|
||||||
};
|
};
|
||||||
|
@ -55,4 +55,71 @@ class OnlineNet: public INetworking {
|
|||||||
int socketShutdown(SceNetId s, int how) final;
|
int socketShutdown(SceNetId s, int how) final;
|
||||||
int socketClose(SceNetId s) final;
|
int socketClose(SceNetId s) final;
|
||||||
int socketAbort(SceNetId s, int flags) 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;
|
||||||
};
|
};
|
||||||
|
715
core/networking/states/online/http.cpp
Normal file
715
core/networking/states/online/http.cpp
Normal 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;
|
||||||
|
}
|
@ -5,8 +5,7 @@ set(libName libSceHttp)
|
|||||||
project(${libName})
|
project(${libName})
|
||||||
|
|
||||||
add_library(${libName} SHARED entry.cpp)
|
add_library(${libName} SHARED entry.cpp)
|
||||||
add_dependencies(${libName} third_party)
|
add_dependencies(${libName} core)
|
||||||
target_link_libraries(${libName} PUBLIC libboost_url)
|
target_link_libraries(${libName} PUBLIC core.lib)
|
||||||
target_compile_definitions(${libName} PRIVATE BOOST_ALL_NO_LIB)
|
|
||||||
|
|
||||||
setupModule(${libName})
|
setupModule(${libName})
|
||||||
|
@ -1,728 +1,253 @@
|
|||||||
#include "../libSceSsl/types.h"
|
#include "../libSceSsl/types.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "core/networking/networking.h"
|
||||||
#include "httpsTypes.h"
|
#include "httpsTypes.h"
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
#include "types.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" {
|
extern "C" {
|
||||||
|
|
||||||
EXPORT const char* MODULE_NAME = "libSceHttp";
|
EXPORT const char* MODULE_NAME = "libSceHttp";
|
||||||
|
|
||||||
EXPORT SYSV_ABI int sceHttpInit(int libnetMemId, int libsslCtxId, size_t poolSize) {
|
EXPORT SYSV_ABI int sceHttpInit(int libnetMemId, int libsslCtxId, size_t poolSize) {
|
||||||
auto const handle = g_client.lookupAvailableIdx(new HttpClient(libnetMemId, libsslCtxId, poolSize));
|
return accessNetworking().httpInit(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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT SYSV_ABI int sceHttpTerm(int libhttpCtxId) {
|
EXPORT SYSV_ABI int sceHttpTerm(int libhttpCtxId) {
|
||||||
if (auto ret = g_client.testId(libhttpCtxId)) return ret;
|
return accessNetworking().httpTerm(libhttpCtxId);
|
||||||
|
|
||||||
g_client.remove(libhttpCtxId);
|
|
||||||
|
|
||||||
LOG_USE_MODULE(libSceHttp);
|
|
||||||
LOG_TRACE(L"http client removed (id: %d)", libhttpCtxId);
|
|
||||||
|
|
||||||
return Ok;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT SYSV_ABI int sceHttpGetMemoryPoolStats(int libhttpCtxId, SceHttpMemoryPoolStats* currentStat) {
|
EXPORT SYSV_ABI int sceHttpGetMemoryPoolStats(int libhttpCtxId, SceHttpMemoryPoolStats* currentStat) {
|
||||||
if (auto ret = g_client.testId(libhttpCtxId)) return ret;
|
return accessNetworking().httpGetMemoryPoolStats(libhttpCtxId, currentStat);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT SYSV_ABI int sceHttpCreateTemplate(int libhttpCtxId, const char* userAgent, int httpVer, int isAutoProxyConf) {
|
EXPORT SYSV_ABI int sceHttpCreateTemplate(int libhttpCtxId, const char* userAgent, int httpVer, int isAutoProxyConf) {
|
||||||
if (auto ret = g_client.testId(libhttpCtxId)) return ret;
|
return accessNetworking().httpCreateTemplate(libhttpCtxId, userAgent, httpVer, isAutoProxyConf);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT SYSV_ABI int sceHttpDeleteTemplate(int tmplId) {
|
EXPORT SYSV_ABI int sceHttpDeleteTemplate(int tmplId) {
|
||||||
if (auto ret = g_template.testId(tmplId)) return ret;
|
return accessNetworking().httpDeleteTemplate(tmplId);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT SYSV_ABI int sceHttpCreateConnection(int tmplId, const char* serverName, const char* scheme, uint16_t port, int isEnableKeepalive) {
|
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) {
|
EXPORT SYSV_ABI int sceHttpCreateConnectionWithURL(int tmplId, const char* url, int isEnableKeepalive) {
|
||||||
boost::urls::url link(url);
|
return accessNetworking().httpCreateConnectionWithURL(tmplId, url, isEnableKeepalive);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT SYSV_ABI int sceHttpDeleteConnection(int connId) {
|
EXPORT SYSV_ABI int sceHttpDeleteConnection(int connId) {
|
||||||
if (auto ret = g_connection.testId(connId)) return ret;
|
return accessNetworking().httpDeleteConnection(connId);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT SYSV_ABI int sceHttpCreateRequest(int connId, int method, const char* path, uint64_t contentLength) {
|
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) {
|
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) {
|
EXPORT SYSV_ABI int sceHttpCreateRequestWithURL(int connId, int method, const char* url, uint64_t contentLength) {
|
||||||
boost::urls::url link(url);
|
return accessNetworking().httpCreateRequestWithURL(connId, method, url, contentLength);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT SYSV_ABI int sceHttpCreateRequestWithURL2(int connId, const char* method, const char* url, uint64_t 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) {
|
EXPORT SYSV_ABI int sceHttpDeleteRequest(int reqId) {
|
||||||
if (auto ret = g_request.testId(reqId)) return ret;
|
return accessNetworking().httpDeleteRequest(reqId);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT SYSV_ABI int sceHttpSetRequestContentLength(int id, uint64_t contentLength) {
|
EXPORT SYSV_ABI int sceHttpSetRequestContentLength(int id, uint64_t contentLength) {
|
||||||
int reqId = id; // (?)
|
return accessNetworking().httpSetRequestContentLength(id, contentLength);
|
||||||
if (auto ret = g_request.testId(reqId)) return ret;
|
|
||||||
|
|
||||||
g_request.getId(reqId)->contentLength = contentLength;
|
|
||||||
|
|
||||||
return Ok;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT SYSV_ABI int sceHttpSetChunkedTransferEnabled(int id, int isEnable) {
|
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) {
|
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) {
|
EXPORT SYSV_ABI int sceHttpSendRequest(int reqId, const void* postData, size_t size) {
|
||||||
if (auto ret = g_request.testId(reqId)) return ret;
|
return accessNetworking().httpSendRequest(reqId, postData, size);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT SYSV_ABI int sceHttpAbortRequest(int reqId) {
|
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) {
|
EXPORT SYSV_ABI int sceHttpGetResponseContentLength(int reqId, int* result, uint64_t* contentLength) {
|
||||||
if (auto ret = g_request.testId(reqId)) return ret;
|
return accessNetworking().httpGetResponseContentLength(reqId, result, contentLength);
|
||||||
|
|
||||||
GET_LAST_RESPONSE;
|
|
||||||
*result = 0; // Content-Length is guaranteed to exist, otherwise performHttpRequest would have failed
|
|
||||||
*contentLength = response->contentLength;
|
|
||||||
|
|
||||||
return Ok;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT SYSV_ABI int sceHttpGetStatusCode(int reqId, int* statusCode) {
|
EXPORT SYSV_ABI int sceHttpGetStatusCode(int reqId, int* statusCode) {
|
||||||
if (auto ret = g_request.testId(reqId)) return ret;
|
return accessNetworking().httpGetStatusCode(reqId, statusCode);
|
||||||
|
|
||||||
GET_LAST_RESPONSE;
|
|
||||||
*statusCode = response->statusCode;
|
|
||||||
|
|
||||||
return Ok;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT SYSV_ABI int sceHttpGetAllResponseHeaders(int reqId, char** header, size_t* headerSize) {
|
EXPORT SYSV_ABI int sceHttpGetAllResponseHeaders(int reqId, char** header, size_t* headerSize) {
|
||||||
*headerSize = 0;
|
return accessNetworking().httpGetAllResponseHeaders(reqId, header, headerSize);
|
||||||
|
|
||||||
return Ok;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT SYSV_ABI int sceHttpReadData(int reqId, void* data, size_t size) {
|
EXPORT SYSV_ABI int sceHttpReadData(int reqId, void* data, size_t size) {
|
||||||
if (auto ret = g_request.testId(reqId)) return ret;
|
return accessNetworking().httpReadData(reqId, data, size);
|
||||||
|
|
||||||
GET_LAST_RESPONSE;
|
|
||||||
size_t finalSize = min(size, response->contentLength);
|
|
||||||
memcpy(data, response->body, finalSize);
|
|
||||||
|
|
||||||
return Ok;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT SYSV_ABI int sceHttpAddRequestHeader(int id, const char* name, const char* value, uint32_t mode) {
|
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) {
|
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) {
|
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,
|
EXPORT SYSV_ABI int sceHttpParseStatusLine(const char* statusLine, size_t lineLen, int* httpMajorVer, int* httpMinorVer, int* responseCode,
|
||||||
const char** reasonPhrase, size_t* phraseLen) {
|
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) {
|
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) {
|
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) {
|
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) {
|
EXPORT SYSV_ABI int sceHttpGetAuthEnabled(int id, int* isEnable) {
|
||||||
return Ok;
|
return accessNetworking().httpGetAuthEnabled(id, isEnable);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT SYSV_ABI int sceHttpAuthCacheFlush(int libhttpCtxId) {
|
EXPORT SYSV_ABI int sceHttpAuthCacheFlush(int libhttpCtxId) {
|
||||||
return Ok;
|
return accessNetworking().httpAuthCacheFlush(libhttpCtxId);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT SYSV_ABI int sceHttpSetRedirectCallback(int id, SceHttpRedirectCallback cbfunc, void* userArg) {
|
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) {
|
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) {
|
EXPORT SYSV_ABI int sceHttpGetAutoRedirect(int id, int* isEnable) {
|
||||||
return Ok;
|
return accessNetworking().httpGetAutoRedirect(id, isEnable);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT SYSV_ABI int sceHttpRedirectCacheFlush(int libhttpCtxId) {
|
EXPORT SYSV_ABI int sceHttpRedirectCacheFlush(int libhttpCtxId) {
|
||||||
return Ok;
|
return accessNetworking().httpRedirectCacheFlush(libhttpCtxId);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT SYSV_ABI int sceHttpSetResolveTimeOut(int id, uint32_t usec) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
EXPORT SYSV_ABI int sceHttpUnsetEpoll(int id) {
|
||||||
return Ok;
|
return accessNetworking().httpUnsetEpoll(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT SYSV_ABI int sceHttpGetEpoll(int id, SceHttpEpollHandle* eh, void** userArg) {
|
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) {
|
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) {
|
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) {
|
EXPORT SYSV_ABI int sceHttpAbortWaitRequest(SceHttpEpollHandle eh) {
|
||||||
return Ok;
|
return accessNetworking().httpAbortWaitRequest(eh);
|
||||||
}
|
}
|
||||||
|
|
||||||
// HTTPS
|
// HTTPS
|
||||||
EXPORT SYSV_ABI int sceHttpsLoadCert(int libhttpCtxId, int caCertNum, const SceSslData** caList, const SceSslData* cert, const SceSslData* privKey) {
|
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) {
|
EXPORT SYSV_ABI int sceHttpsUnloadCert(int libhttpCtxId) {
|
||||||
return Ok;
|
return accessNetworking().httpsUnloadCert(libhttpCtxId);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT SYSV_ABI int sceHttpsEnableOption(int id, uint32_t sslFlags) {
|
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) {
|
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) {
|
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) {
|
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) {
|
EXPORT SYSV_ABI int sceHttpsSetSslVersion(int id, SceSslVersion version) {
|
||||||
return Ok;
|
return accessNetworking().httpsSetSslVersion(id, version);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "../libSceSsl/types.h"
|
||||||
|
|
||||||
enum class SceHttpsFlags : unsigned int {
|
enum class SceHttpsFlags : unsigned int {
|
||||||
SERVER_VERIFY = 0x01U, // Server Certificate Verify
|
SERVER_VERIFY = 0x01U, // Server Certificate Verify
|
||||||
CLIENT_VERIFY = 0x02U, // Client 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);
|
||||||
|
@ -57,4 +57,4 @@ struct SceHttpNBEvent {
|
|||||||
uint32_t eventDetail;
|
uint32_t eventDetail;
|
||||||
int id;
|
int id;
|
||||||
void* userArg;
|
void* userArg;
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user