ppsspp/Core/HLE/sceHttp.h

292 lines
10 KiB
C++

// Copyright (c) 2012- PPSSPP Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0 or later versions.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#pragma once
#include <map>
#include "Common/Net/HTTPClient.h"
// Based on https://docs.vitasdk.org/group__SceHttpUser.html
#define SCE_HTTP_DEFAULT_RESOLVER_TIMEOUT (1 * 1000 * 1000U)
#define SCE_HTTP_DEFAULT_RESOLVER_RETRY (5U)
#define SCE_HTTP_DEFAULT_CONNECT_TIMEOUT (30* 1000 * 1000U)
#define SCE_HTTP_DEFAULT_SEND_TIMEOUT (120* 1000 * 1000U)
#define SCE_HTTP_DEFAULT_RECV_TIMEOUT (120* 1000 * 1000U)
#define SCE_HTTP_DEFAULT_RECV_BLOCK_SIZE (1500U)
#define SCE_HTTP_DEFAULT_RESPONSE_HEADER_MAX (5000U)
#define SCE_HTTP_DEFAULT_REDIRECT_MAX (6U)
#define SCE_HTTP_DEFAULT_TRY_AUTH_MAX (6U)
#define SCE_HTTP_INVALID_ID 0
#define SCE_HTTP_ENABLE (1)
#define SCE_HTTP_DISABLE (0)
#define SCE_HTTP_USERNAME_MAX_SIZE 256
#define SCE_HTTP_PASSWORD_MAX_SIZE 256
// If http isn't loaded (seems unlikely), most functions should return SCE_KERNEL_ERROR_LIBRARY_NOTFOUND
// lib_http specific error codes, based on https://uofw.github.io/uofw/lib__http_8h_source.html, combined with https://github.com/vitasdk/vita-headers/blob/master/include/psp2/net/http.h
enum SceHttpErrorCode {
SCE_HTTP_ERROR_BEFORE_INIT = 0x80431001,
SCE_HTTP_ERROR_NOT_SUPPORTED = 0x80431004,
SCE_HTTP_ERROR_ALREADY_INITED = 0x80431020,
SCE_HTTP_ERROR_BUSY = 0x80431021,
SCE_HTTP_ERROR_OUT_OF_MEMORY = 0x80431022,
SCE_HTTP_ERROR_NOT_FOUND = 0x80431025,
SCE_HTTP_ERROR_UNKNOWN_SCHEME = 0x80431061,
SCE_HTTP_ERROR_NETWORK = 0x80431063,
SCE_HTTP_ERROR_BAD_RESPONSE = 0x80431064,
SCE_HTTP_ERROR_BEFORE_SEND = 0x80431065,
SCE_HTTP_ERROR_AFTER_SEND = 0x80431066,
SCE_HTTP_ERROR_TIMEOUT = 0x80431068,
SCE_HTTP_ERROR_UNKOWN_AUTH_TYPE = 0x80431069,
SCE_HTTP_ERROR_INVALID_VERSION = 0x8043106A,
SCE_HTTP_ERROR_UNKNOWN_METHOD = 0x8043106B,
SCE_HTTP_ERROR_READ_BY_HEAD_METHOD = 0x8043106F,
SCE_HTTP_ERROR_NOT_IN_COM = 0x80431070,
SCE_HTTP_ERROR_NO_CONTENT_LENGTH = 0x80431071,
SCE_HTTP_ERROR_CHUNK_ENC = 0x80431072,
SCE_HTTP_ERROR_TOO_LARGE_RESPONSE_HEADER = 0x80431073,
SCE_HTTP_ERROR_SSL = 0x80431075,
SCE_HTTP_ERROR_INSUFFICIENT_HEAPSIZE = 0x80431077,
SCE_HTTP_ERROR_BEFORE_COOKIE_LOAD = 0x80431078,
SCE_HTTP_ERROR_ABORTED = 0x80431080,
SCE_HTTP_ERROR_UNKNOWN = 0x80431081,
SCE_HTTP_ERROR_INVALID_ID = 0x80431100,
SCE_HTTP_ERROR_OUT_OF_SIZE = 0x80431104,
SCE_HTTP_ERROR_INVALID_VALUE = 0x804311FE,
SCE_HTTP_ERROR_PARSE_HTTP_NOT_FOUND = 0x80432025,
SCE_HTTP_ERROR_PARSE_HTTP_INVALID_RESPONSE = 0x80432060,
SCE_HTTP_ERROR_PARSE_HTTP_INVALID_VALUE = 0x804321FE,
SCE_HTTP_ERROR_INVALID_URL = 0x80433060,
SCE_HTTP_ERROR_RESOLVER_EPACKET = 0x80436001,
SCE_HTTP_ERROR_RESOLVER_ENODNS = 0x80436002,
SCE_HTTP_ERROR_RESOLVER_ETIMEDOUT = 0x80436003,
SCE_HTTP_ERROR_RESOLVER_ENOSUPPORT = 0x80436004,
SCE_HTTP_ERROR_RESOLVER_EFORMAT = 0x80436005,
SCE_HTTP_ERROR_RESOLVER_ESERVERFAILURE = 0x80436006,
SCE_HTTP_ERROR_RESOLVER_ENOHOST = 0x80436007,
SCE_HTTP_ERROR_RESOLVER_ENOTIMPLEMENTED = 0x80436008,
SCE_HTTP_ERROR_RESOLVER_ESERVERREFUSED = 0x80436009,
SCE_HTTP_ERROR_RESOLVER_ENORECORD = 0x8043600A
};
// lib_https specific error codes, based on https://uofw.github.io/uofw/lib__https_8h_source.html, combined with https://github.com/vitasdk/vita-headers/blob/master/include/psp2/net/http.h
enum SceHttpsErrorCode {
SCE_HTTPS_ERROR_OUT_OF_MEMORY = 0x80435022,
SCE_HTTPS_ERROR_CERT = 0x80435060,
SCE_HTTPS_ERROR_HANDSHAKE = 0x80435061,
SCE_HTTPS_ERROR_IO = 0x80435062,
SCE_HTTPS_ERROR_INTERNAL = 0x80435063,
SCE_HTTPS_ERROR_PROXY = 0x80435064
};
// Could come in handy someday if we ever implement sceHttp* for real.
enum PSPHttpMethod {
PSP_HTTP_METHOD_GET,
PSP_HTTP_METHOD_POST,
PSP_HTTP_METHOD_HEAD
};
// Based on https://github.com/vitasdk/vita-headers/blob/master/include/psp2/net/http.h
enum SceHttpStatusCode {
SCE_HTTP_STATUS_CODE_CONTINUE = 100,
SCE_HTTP_STATUS_CODE_SWITCHING_PROTOCOLS = 101,
SCE_HTTP_STATUS_CODE_PROCESSING = 102,
SCE_HTTP_STATUS_CODE_OK = 200,
SCE_HTTP_STATUS_CODE_CREATED = 201,
SCE_HTTP_STATUS_CODE_ACCEPTED = 202,
SCE_HTTP_STATUS_CODE_NON_AUTHORITATIVE_INFORMATION = 203,
SCE_HTTP_STATUS_CODE_NO_CONTENT = 204,
SCE_HTTP_STATUS_CODE_RESET_CONTENT = 205,
SCE_HTTP_STATUS_CODE_PARTIAL_CONTENT = 206,
SCE_HTTP_STATUS_CODE_MULTI_STATUS = 207,
SCE_HTTP_STATUS_CODE_MULTIPLE_CHOICES = 300,
SCE_HTTP_STATUS_CODE_MOVED_PERMANENTLY = 301,
SCE_HTTP_STATUS_CODE_FOUND = 302,
SCE_HTTP_STATUS_CODE_SEE_OTHER = 303,
SCE_HTTP_STATUS_CODE_NOT_MODIFIED = 304,
SCE_HTTP_STATUS_CODE_USE_PROXY = 305,
SCE_HTTP_STATUS_CODE_TEMPORARY_REDIRECT = 307,
SCE_HTTP_STATUS_CODE_BAD_REQUEST = 400,
SCE_HTTP_STATUS_CODE_UNAUTHORIZED = 401,
SCE_HTTP_STATUS_CODE_PAYMENT_REQUIRED = 402,
SCE_HTTP_STATUS_CODE_FORBIDDDEN = 403,
SCE_HTTP_STATUS_CODE_NOT_FOUND = 404,
SCE_HTTP_STATUS_CODE_METHOD_NOT_ALLOWED = 405,
SCE_HTTP_STATUS_CODE_NOT_ACCEPTABLE = 406,
SCE_HTTP_STATUS_CODE_PROXY_AUTHENTICATION_REQUIRED = 407,
SCE_HTTP_STATUS_CODE_REQUEST_TIME_OUT = 408,
SCE_HTTP_STATUS_CODE_CONFLICT = 409,
SCE_HTTP_STATUS_CODE_GONE = 410,
SCE_HTTP_STATUS_CODE_LENGTH_REQUIRED = 411,
SCE_HTTP_STATUS_CODE_PRECONDITION_FAILED = 412,
SCE_HTTP_STATUS_CODE_REQUEST_ENTITY_TOO_LARGE = 413,
SCE_HTTP_STATUS_CODE_REQUEST_URI_TOO_LARGE = 414,
SCE_HTTP_STATUS_CODE_UNSUPPORTED_MEDIA_TYPE = 415,
SCE_HTTP_STATUS_CODE_REQUEST_RANGE_NOT_SATISFIBLE = 416,
SCE_HTTP_STATUS_CODE_EXPECTATION_FAILED = 417,
SCE_HTTP_STATUS_CODE_UNPROCESSABLE_ENTITY = 422,
SCE_HTTP_STATUS_CODE_LOCKED = 423,
SCE_HTTP_STATUS_CODE_FAILED_DEPENDENCY = 424,
SCE_HTTP_STATUS_CODE_UPGRADE_REQUIRED = 426,
SCE_HTTP_STATUS_CODE_INTERNAL_SERVER_ERROR = 500,
SCE_HTTP_STATUS_CODE_NOT_IMPLEMENTED = 501,
SCE_HTTP_STATUS_CODE_BAD_GATEWAY = 502,
SCE_HTTP_STATUS_CODE_SERVICE_UNAVAILABLE = 503,
SCE_HTTP_STATUS_CODE_GATEWAY_TIME_OUT = 504,
SCE_HTTP_STATUS_CODE_HTTP_VERSION_NOT_SUPPORTED = 505,
SCE_HTTP_STATUS_CODE_INSUFFICIENT_STORAGE = 507
};
enum SceHttpVersion {
SCE_HTTP_VERSION_1_0 = 1,
SCE_HTTP_VERSION_1_1
};
enum SceHttpProxyMode {
SCE_HTTP_PROXY_AUTO,
SCE_HTTP_PROXY_MANUAL
};
enum SceHttpAddHeaderMode {
SCE_HTTP_HEADER_OVERWRITE,
SCE_HTTP_HEADER_ADD
};
// Just a holder for class names
static const char* name_HTTPTemplate = "HTTPTemplate";
static const char* name_HTTPConnection = "HTTPConnection";
static const char* name_HTTPRequest = "HTTPRequest";
class HTTPTemplate {
protected:
std::string userAgent; // char userAgent[512];
SceHttpVersion httpVer = SCE_HTTP_VERSION_1_0;
SceHttpProxyMode autoProxyConf = SCE_HTTP_PROXY_AUTO;
int useCookie = 0;
int useKeepAlive = 0;
int useCache = 0;
int useAuth = 0;
int useRedirect = 0;
u32 connectTimeout = SCE_HTTP_DEFAULT_CONNECT_TIMEOUT;
u32 sendTimeout = SCE_HTTP_DEFAULT_SEND_TIMEOUT;
u32 recvTimeout = SCE_HTTP_DEFAULT_RECV_TIMEOUT;
u32 resolveTimeout = SCE_HTTP_DEFAULT_RESOLVER_TIMEOUT;
int resolveRetryCount = SCE_HTTP_DEFAULT_RESOLVER_RETRY;
std::map<std::string, std::string> requestHeaders_;
public:
HTTPTemplate() {}
HTTPTemplate(const char* userAgent, int httpVer, int autoProxyConf);
virtual ~HTTPTemplate() = default;
virtual const char* className() { return name_HTTPTemplate; } // to be more consistent, unlike typeid(v).name() which may varies among different compilers and requires RTTI
const std::string getUserAgent() { return userAgent; }
int getHttpVer() { return httpVer; }
int getAutoProxyConf() { return autoProxyConf; }
u32 getConnectTimeout() { return connectTimeout; }
u32 getSendTimeout() { return sendTimeout; }
u32 getRecvTimeout() { return recvTimeout; }
u32 getResolveTimeout() { return resolveTimeout; }
int getResolveRetryCount() { return resolveRetryCount; }
void setUserAgent(const char* userAgent) { this->userAgent = userAgent ? userAgent : ""; }
void setConnectTimeout(u32 timeout) { this->connectTimeout = timeout; }
void setSendTimeout(u32 timeout) { this->sendTimeout = timeout; }
void setRecvTimeout(u32 timeout) { this->recvTimeout = timeout; }
void setResolveTimeout(u32 timeout) { this->resolveTimeout = timeout; }
void setResolveRetry(u32 retryCount) { this->resolveRetryCount = retryCount; }
int addRequestHeader(const char* name, const char* value, u32 mode);
int removeRequestHeader(const char* name);
};
class HTTPConnection : public HTTPTemplate {
protected:
int templateID = 0;
std::string hostString;
std::string scheme;
u16 port = 80;
int enableKeepalive = 0;
public:
HTTPConnection() {}
HTTPConnection(int templateID, const char* hostString, const char* scheme, u32 port, int enableKeepalive);
virtual ~HTTPConnection() = default;
virtual const char* className() override { return name_HTTPConnection; }
int getTemplateID() { return templateID; }
const std::string getHost() { return hostString; }
const std::string getScheme() { return scheme; }
u16 getPort() { return port; }
int getKeepAlive() { return enableKeepalive; }
};
class HTTPRequest : public HTTPConnection {
private:
int connectionID;
int method;
u64 contentLength;
std::string url;
u32 headerAddr_ = 0;
u32 headerSize_ = 0;
bool cancelled_ = false;
int responseCode_ = -1;
int entityLength_ = -1;
http::Client client;
//net::RequestProgress progress_(&cancelled_);
std::vector<std::string> responseHeaders_;
std::string httpLine_;
std::string responseContent_;
public:
HTTPRequest(int connectionID, int method, const char* url, u64 contentLength);
~HTTPRequest();
virtual const char* className() override { return name_HTTPRequest; }
void setInternalHeaderAddr(u32 addr) { headerAddr_ = addr; }
int getConnectionID() { return connectionID; }
int getResponseRemainingContentLength() { return (int)responseContent_.size(); }
int getResponseContentLength();
int abortRequest();
int getStatusCode();
int getAllResponseHeaders(u32 headerAddrPtr, u32 headerSizePtr);
int readData(u32 destDataPtr, u32 size);
int sendRequest(u32 postDataPtr, u32 postDataSize);
};
void __HttpInit();
void __HttpShutdown();
void Register_sceHttp();