mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-12 09:06:55 -04:00
Http client: Use better error codes, fix Host headers for webservers not running on port 80, use as the http backend for 3DS/PSP consoles
This commit is contained in:
parent
6cd0dae2a8
commit
42c3b6acfc
@ -241,13 +241,13 @@ typedef cc_uint8 cc_bool;
|
|||||||
#define CC_BUILD_MINFILES
|
#define CC_BUILD_MINFILES
|
||||||
#undef CC_BUILD_FREETYPE
|
#undef CC_BUILD_FREETYPE
|
||||||
#elif defined __psp__
|
#elif defined __psp__
|
||||||
#define CC_BUILD_CURL
|
#define CC_BUILD_HTTPCLIENT
|
||||||
#define CC_BUILD_OPENAL
|
#define CC_BUILD_OPENAL
|
||||||
#define CC_BUILD_PSP
|
#define CC_BUILD_PSP
|
||||||
#undef CC_BUILD_FREETYPE
|
#undef CC_BUILD_FREETYPE
|
||||||
#undef EXTENDED_BLOCKS
|
#undef EXTENDED_BLOCKS
|
||||||
#elif defined __3DS__
|
#elif defined __3DS__
|
||||||
#define CC_BUILD_CURL
|
#define CC_BUILD_HTTPCLIENT
|
||||||
#define CC_BUILD_OPENAL
|
#define CC_BUILD_OPENAL
|
||||||
#define CC_BUILD_3DS
|
#define CC_BUILD_3DS
|
||||||
#undef CC_BUILD_FREETYPE
|
#undef CC_BUILD_FREETYPE
|
||||||
|
@ -124,5 +124,11 @@ enum CC_ERRORS {
|
|||||||
NBT_ERR_EXPECTED_STR = 0xCCDED064UL, /* Expected String NBT tag */
|
NBT_ERR_EXPECTED_STR = 0xCCDED064UL, /* Expected String NBT tag */
|
||||||
NBT_ERR_EXPECTED_ARR = 0xCCDED065UL, /* Expected Byte Array NBT tag */
|
NBT_ERR_EXPECTED_ARR = 0xCCDED065UL, /* Expected Byte Array NBT tag */
|
||||||
NBT_ERR_ARR_TOO_SMALL= 0xCCDED066UL, /* Byte Array NBT tag length is < expected length */
|
NBT_ERR_ARR_TOO_SMALL= 0xCCDED066UL, /* Byte Array NBT tag length is < expected length */
|
||||||
|
|
||||||
|
HTTP_ERR_NO_SSL = 0xCCDED067UL, /* HTTP backend doesn't support SSL */
|
||||||
|
HTTP_ERR_REDIRECTS = 0xCCDED068UL, /* Too many attempted HTTP redirects */
|
||||||
|
HTTP_ERR_RELATIVE = 0xCCDED069UL, /* Unsupported relative URL format */
|
||||||
|
HTTP_ERR_INVALID_BODY= 0xCCDED06AUL, /* HTTP message doesn't have Content-Length or use Chunked transfer encoding */
|
||||||
|
HTTP_ERR_CHUNK_SIZE = 0xCCDED06BUL, /* HTTP message chunk has negative size/length */
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
@ -421,18 +421,17 @@ static cc_result HttpBackend_Do(struct HttpRequest* req, cc_string* url) {
|
|||||||
#include "PackedCol.h"
|
#include "PackedCol.h"
|
||||||
|
|
||||||
static void HttpBackend_Init(void) {
|
static void HttpBackend_Init(void) {
|
||||||
httpOnly = true; // TODO: insecure
|
//httpOnly = true; // TODO: insecure
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Components of a URL */
|
/* Components of a URL */
|
||||||
struct HttpUrl {
|
struct HttpUrl {
|
||||||
cc_string address; /* Address of server (e.g. "classicube.net") */
|
|
||||||
cc_uint16 port; /* Port server is listening on (e.g 80) */
|
|
||||||
cc_bool https; /* Whether HTTPS or just HTTP protocol */
|
cc_bool https; /* Whether HTTPS or just HTTP protocol */
|
||||||
|
cc_string address; /* Address of server (e.g. "classicube.net:8080") */
|
||||||
cc_string resource; /* Path being accessed (and query string) */
|
cc_string resource; /* Path being accessed (and query string) */
|
||||||
char _addressBuffer[STRING_SIZE + 1];
|
char _addressBuffer[STRING_SIZE + 8];
|
||||||
char _resourceBuffer[STRING_SIZE * 4 + 1];
|
char _resourceBuffer[STRING_SIZE * 4];
|
||||||
};
|
};
|
||||||
|
|
||||||
static void HttpUrl_EncodeUrl(cc_string* dst, const cc_string* src) {
|
static void HttpUrl_EncodeUrl(cc_string* dst, const cc_string* src) {
|
||||||
@ -455,30 +454,24 @@ static void HttpUrl_EncodeUrl(cc_string* dst, const cc_string* src) {
|
|||||||
|
|
||||||
/* Splits up the components of a URL */
|
/* Splits up the components of a URL */
|
||||||
static void HttpUrl_Parse(const cc_string* src, struct HttpUrl* url) {
|
static void HttpUrl_Parse(const cc_string* src, struct HttpUrl* url) {
|
||||||
cc_string scheme, path, addr, host, port, resource;
|
cc_string scheme, path, addr, resource;
|
||||||
/* URL is of form [scheme]://[server host]:[server port]/[resource] */
|
/* URL is of form [scheme]://[server host]:[server port]/[resource] */
|
||||||
|
/* For simplicity, parsed as [scheme]://[server address]/[resource] */
|
||||||
int idx = String_IndexOfConst(src, "://");
|
int idx = String_IndexOfConst(src, "://");
|
||||||
|
|
||||||
scheme = idx == -1 ? String_Empty : String_UNSAFE_Substring(src, 0, idx);
|
scheme = idx == -1 ? String_Empty : String_UNSAFE_Substring(src, 0, idx);
|
||||||
path = idx == -1 ? *src : String_UNSAFE_SubstringAt(src, idx + 3);
|
path = idx == -1 ? *src : String_UNSAFE_SubstringAt(src, idx + 3);
|
||||||
|
|
||||||
url->https = String_CaselessEqualsConst(&scheme, "https");
|
url->https = String_CaselessEqualsConst(&scheme, "https");
|
||||||
|
|
||||||
String_UNSAFE_Separate(&path, '/', &addr, &resource);
|
String_UNSAFE_Separate(&path, '/', &addr, &resource);
|
||||||
String_UNSAFE_Separate(&addr, ':', &host, &port);
|
|
||||||
|
|
||||||
String_InitArray_NT(url->address, url->_addressBuffer);
|
String_InitArray(url->address, url->_addressBuffer);
|
||||||
String_Copy(&url->address, &host);
|
String_Copy(&url->address, &addr);
|
||||||
url->_addressBuffer[url->address.length] = '\0';
|
|
||||||
|
|
||||||
if (!Convert_ParseUInt16(&port, &url->port)) {
|
String_InitArray(url->resource, url->_resourceBuffer);
|
||||||
url->port = url->https ? 443 : 80;
|
|
||||||
}
|
|
||||||
|
|
||||||
String_InitArray_NT(url->resource, url->_resourceBuffer);
|
|
||||||
String_Append(&url->resource, '/');
|
String_Append(&url->resource, '/');
|
||||||
/* Address may have unicode characters - need to percent encode them */
|
/* Address may have unicode characters - need to percent encode them */
|
||||||
HttpUrl_EncodeUrl(&url->resource, &resource);
|
HttpUrl_EncodeUrl(&url->resource, &resource);
|
||||||
url->_resourceBuffer[url->resource.length] = '\0';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -487,8 +480,18 @@ struct HttpConnection {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static cc_result HttpConnection_Open(struct HttpConnection* conn, const struct HttpUrl* url) {
|
static cc_result HttpConnection_Open(struct HttpConnection* conn, const struct HttpUrl* url) {
|
||||||
|
cc_string host, port;
|
||||||
|
cc_uint16 portNum;
|
||||||
|
|
||||||
|
/* address can be either "host" or "host:port" */
|
||||||
|
String_UNSAFE_Separate(&url->address, ':', &host, &port);
|
||||||
|
if (!Convert_ParseUInt16(&port, &portNum)) {
|
||||||
|
portNum = url->https ? 443 : 80;
|
||||||
|
}
|
||||||
|
|
||||||
conn->socket = 0;
|
conn->socket = 0;
|
||||||
return Socket_Connect(&conn->socket, &url->address, url->port, false);
|
if (url->https) return HTTP_ERR_NO_SSL;
|
||||||
|
return Socket_Connect(&conn->socket, &host, portNum, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HttpConnection_Close(struct HttpConnection* conn) {
|
static void HttpConnection_Close(struct HttpConnection* conn) {
|
||||||
@ -545,7 +548,7 @@ static void HttpClient_Serialise(struct HttpClientState* state) {
|
|||||||
String_Format2(buffer, "%c %s HTTP/1.1\r\n",
|
String_Format2(buffer, "%c %s HTTP/1.1\r\n",
|
||||||
verbs[req->requestType], &state->url.resource);
|
verbs[req->requestType], &state->url.resource);
|
||||||
|
|
||||||
Http_AddHeader(req, "Host", &state->url.address); /* TODO port for non-standard*/
|
Http_AddHeader(req, "Host", &state->url.address);
|
||||||
Http_AddHeader(req, "User-Agent", &userAgent);
|
Http_AddHeader(req, "User-Agent", &userAgent);
|
||||||
if (req->data) String_Format1(buffer, "Content-Length: %i\r\n", &req->size);
|
if (req->data) String_Format1(buffer, "Content-Length: %i\r\n", &req->size);
|
||||||
|
|
||||||
@ -569,7 +572,7 @@ static cc_result HttpClient_SendRequest(struct HttpClientState* state) {
|
|||||||
http_curProgress = HTTP_PROGRESS_FETCHING_DATA;
|
http_curProgress = HTTP_PROGRESS_FETCHING_DATA;
|
||||||
HttpClient_Serialise(state);
|
HttpClient_Serialise(state);
|
||||||
|
|
||||||
/* TODO check wrote is >= inputMsg.length */
|
/* TODO check that wrote is >= inputMsg.length */
|
||||||
return Socket_Write(state->conn.socket, inputBuffer, inputMsg.length, &wrote);
|
return Socket_Write(state->conn.socket, inputBuffer, inputMsg.length, &wrote);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -653,8 +656,7 @@ static cc_result HttpClient_Process(struct HttpClientState* state, char* buffer,
|
|||||||
Http_BufferInit(req);
|
Http_BufferInit(req);
|
||||||
state->state = HTTP_RESPONSE_STATE_BODY_DATA;
|
state->state = HTTP_RESPONSE_STATE_BODY_DATA;
|
||||||
} else {
|
} else {
|
||||||
/* Chunked encoding not supported yet */
|
return HTTP_ERR_INVALID_BODY;
|
||||||
return ERR_NOT_SUPPORTED;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -685,7 +687,7 @@ static cc_result HttpClient_Process(struct HttpClientState* state, char* buffer,
|
|||||||
if (c != '\n') { String_Append(&state->header, c); continue; }
|
if (c != '\n') { String_Append(&state->header, c); continue; }
|
||||||
|
|
||||||
state->chunkLength = HttpClient_GetChunkLength(&state->header);
|
state->chunkLength = HttpClient_GetChunkLength(&state->header);
|
||||||
if (state->chunkLength < 0) return ERR_INVALID_ARGUMENT;
|
if (state->chunkLength < 0) return HTTP_ERR_CHUNK_SIZE;
|
||||||
state->header.length = 0;
|
state->header.length = 0;
|
||||||
|
|
||||||
if (state->chunkLength == 0) {
|
if (state->chunkLength == 0) {
|
||||||
@ -787,7 +789,7 @@ static cc_result HttpClient_HandleRedirect(struct HttpClientState* state) {
|
|||||||
state->req->contentLength = 0; /* TODO */
|
state->req->contentLength = 0; /* TODO */
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return ERR_INVALID_ARGUMENT;
|
return HTTP_ERR_RELATIVE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -816,8 +818,7 @@ static cc_result HttpBackend_Do(struct HttpRequest* req, cc_string* urlStr) {
|
|||||||
HttpConnection_Close(&state.conn);
|
HttpConnection_Close(&state.conn);
|
||||||
|
|
||||||
if (res || !HttpClient_IsRedirect(req)) break;
|
if (res || !HttpClient_IsRedirect(req)) break;
|
||||||
/* TODO BETTER ERROR CODE */
|
if (redirects >= 20) return HTTP_ERR_REDIRECTS;
|
||||||
if (redirects >= 20) return ERR_DOWNLOAD_INVALID;
|
|
||||||
|
|
||||||
/* TODO FOLLOW LOCATION PROPERLY */
|
/* TODO FOLLOW LOCATION PROPERLY */
|
||||||
redirects++;
|
redirects++;
|
||||||
|
@ -98,6 +98,8 @@ static const char* GetCCErrorDesc(cc_result res) {
|
|||||||
case NBT_ERR_EXPECTED_STR: return "Expected String NBT tag";
|
case NBT_ERR_EXPECTED_STR: return "Expected String NBT tag";
|
||||||
case NBT_ERR_EXPECTED_ARR: return "Expected ByteArray NBT tag";
|
case NBT_ERR_EXPECTED_ARR: return "Expected ByteArray NBT tag";
|
||||||
case NBT_ERR_ARR_TOO_SMALL:return "ByteArray NBT tag too small";
|
case NBT_ERR_ARR_TOO_SMALL:return "ByteArray NBT tag too small";
|
||||||
|
|
||||||
|
case HTTP_ERR_NO_SSL: return "HTTPS URLs are not currently supported";
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user