diff --git a/libretro-common/include/net/net_http.h b/libretro-common/include/net/net_http.h index 1ec56bbc3c2d..ccc53c2f93f5 100644 --- a/libretro-common/include/net/net_http.h +++ b/libretro-common/include/net/net_http.h @@ -34,7 +34,7 @@ RETRO_BEGIN_DECLS struct http_t; struct http_connection_t; -struct http_connection_t *net_http_connection_new(const char *url); +struct http_connection_t *net_http_connection_new(const char *url, const char *method, const char *data); bool net_http_connection_iterate(struct http_connection_t *conn); diff --git a/libretro-common/net/net_http.c b/libretro-common/net/net_http.c index 317d72438482..ca3ff0d66e9f 100644 --- a/libretro-common/net/net_http.c +++ b/libretro-common/net/net_http.c @@ -68,10 +68,12 @@ struct http_connection_t char *location; char *urlcopy; char *scan; + char *methodcopy; + char *contenttypecopy; + char *postdatacopy; int port; }; - static int net_http_new_socket(const char *domain, int port) { int ret; @@ -140,7 +142,7 @@ static char* urlencode(const char* url) return ret; } -struct http_connection_t *net_http_connection_new(const char *url) +struct http_connection_t *net_http_connection_new(const char *url, const char *method, const char *data) { char **domain = NULL; struct http_connection_t *conn = (struct http_connection_t*)calloc(1, @@ -151,6 +153,12 @@ struct http_connection_t *net_http_connection_new(const char *url) conn->urlcopy = urlencode(url); + if (method) + conn->methodcopy = strdup(method); + + if (data) + conn->postdatacopy = strdup(data); + if (!conn->urlcopy) goto error; @@ -166,7 +174,13 @@ struct http_connection_t *net_http_connection_new(const char *url) error: if (conn->urlcopy) free(conn->urlcopy); + if (conn->methodcopy) + free(conn->methodcopy); + if (conn->postdatacopy) + free(conn->postdatacopy); conn->urlcopy = NULL; + conn->methodcopy = NULL; + conn->postdatacopy = NULL; free(conn); return NULL; } @@ -221,6 +235,20 @@ void net_http_connection_free(struct http_connection_t *conn) if (conn->urlcopy) free(conn->urlcopy); + if (conn->methodcopy) + free(conn->methodcopy); + + if (conn->contenttypecopy) + free(conn->contenttypecopy); + + if (conn->postdatacopy) + free(conn->postdatacopy); + + conn->urlcopy = NULL; + conn->methodcopy = NULL; + conn->contenttypecopy = NULL; + conn->postdatacopy = NULL; + free(conn); } @@ -245,7 +273,16 @@ struct http_t *net_http_new(struct http_connection_t *conn) error = false; /* This is a bit lazy, but it works. */ - net_http_send_str(fd, &error, "GET /"); + if (conn->methodcopy) + { + net_http_send_str(fd, &error, conn->methodcopy); + net_http_send_str(fd, &error, " /"); + } + else + { + net_http_send_str(fd, &error, "GET /"); + } + net_http_send_str(fd, &error, conn->location); net_http_send_str(fd, &error, " HTTP/1.1\r\n"); @@ -263,9 +300,45 @@ struct http_t *net_http_new(struct http_connection_t *conn) } net_http_send_str(fd, &error, "\r\n"); + + /* this is not being set anywhere yet */ + if (conn->contenttypecopy) + { + net_http_send_str(fd, &error, "Content-Type: "); + net_http_send_str(fd, &error, conn->contenttypecopy); + net_http_send_str(fd, &error, "\r\n"); + } + + if (conn->methodcopy && string_is_equal(conn->methodcopy, "POST")) + { + size_t post_len, len; + char *len_str; + + if (!conn->postdatacopy) + goto error; + + if (!conn->contenttypecopy) + net_http_send_str(fd, &error, "Content-Type: application/x-www-form-urlencoded\r\n"); + + net_http_send_str(fd, &error, "Content-Length: "); + + post_len = strlen(conn->postdatacopy); + len = snprintf(NULL, 0, "%lu", post_len); + len_str = (char*)malloc(len); + + snprintf(len_str, len, "%lu", post_len); + + len_str[len - 1] = '\0'; + + net_http_send_str(fd, &error, len_str); + } + net_http_send_str(fd, &error, "Connection: close\r\n"); net_http_send_str(fd, &error, "\r\n"); + if (conn->methodcopy && string_is_equal(conn->methodcopy, "POST")) + net_http_send_str(fd, &error, conn->postdatacopy); + if (error) goto error; @@ -287,6 +360,13 @@ struct http_t *net_http_new(struct http_connection_t *conn) return state; error: + if (conn->methodcopy) + free(conn->methodcopy); + if (conn->contenttypecopy) + free(conn->contenttypecopy); + conn->methodcopy = NULL; + conn->contenttypecopy = NULL; + conn->postdatacopy = NULL; if (fd >= 0) socket_close(fd); if (state) diff --git a/network/net_http_special.c b/network/net_http_special.c index 567095f0f02f..20fb53d87f03 100644 --- a/network/net_http_special.c +++ b/network/net_http_special.c @@ -30,7 +30,7 @@ int net_http_get(const char **result, size_t *size, const char *url, retro_time_ int ret = NET_HTTP_GET_OK; struct http_t* http = NULL; retro_time_t t0 = cpu_features_get_time_usec(); - struct http_connection_t *conn = net_http_connection_new(url); + struct http_connection_t *conn = net_http_connection_new(url, "GET", NULL); *result = NULL; diff --git a/tasks/task_http.c b/tasks/task_http.c index 9413e9718ff9..d37186acf828 100644 --- a/tasks/task_http.c +++ b/tasks/task_http.c @@ -235,12 +235,11 @@ static bool task_http_retriever(retro_task_t *task, void *data) return true; } -void *task_push_http_transfer(const char *url, bool mute, const char *type, +static void* task_push_http_transfer_generic(struct http_connection_t *conn, const char *url, bool mute, const char *type, retro_task_callback_t cb, void *user_data) { task_finder_data_t find_data; char tmp[255]; - struct http_connection_t *conn = NULL; retro_task_t *t = NULL; http_handle_t *http = NULL; @@ -259,8 +258,6 @@ void *task_push_http_transfer(const char *url, bool mute, const char *type, return NULL; } - conn = net_http_connection_new(url); - if (!conn) return NULL; @@ -308,6 +305,26 @@ void *task_push_http_transfer(const char *url, bool mute, const char *type, return NULL; } +void* task_push_http_transfer(const char *url, bool mute, const char *type, + retro_task_callback_t cb, void *user_data) +{ + struct http_connection_t *conn; + + conn = net_http_connection_new(url, "GET", NULL); + + return task_push_http_transfer_generic(conn, url, mute, type, cb, user_data); +} + +void* task_push_http_post_transfer(const char *url, const char *post_data, bool mute, + const char *type, retro_task_callback_t cb, void *user_data) +{ + struct http_connection_t *conn; + + conn = net_http_connection_new(url, "POST", post_data); + + return task_push_http_transfer_generic(conn, url, mute, type, cb, user_data); +} + task_retriever_info_t *http_task_get_transfer_list(void) { task_retriever_data_t retrieve_data; diff --git a/tasks/tasks_internal.h b/tasks/tasks_internal.h index e70bfbf4fb71..5dbeeaec6b8e 100644 --- a/tasks/tasks_internal.h +++ b/tasks/tasks_internal.h @@ -86,6 +86,9 @@ typedef struct void *task_push_http_transfer(const char *url, bool mute, const char *type, retro_task_callback_t cb, void *userdata); +void *task_push_http_post_transfer(const char *url, const char *post_data, bool mute, const char *type, + retro_task_callback_t cb, void *userdata); + task_retriever_info_t *http_task_get_transfer_list(void); bool task_push_wifi_scan(void);