mirror of
https://github.com/libretro/RetroArch.git
synced 2024-10-07 14:23:29 +00:00
Make HTTP connection info code non-blocking
This commit is contained in:
parent
3c2d6020ed
commit
5fb591ecf9
@ -609,6 +609,12 @@ struct global
|
||||
#ifdef HAVE_NETWORKING
|
||||
struct
|
||||
{
|
||||
struct
|
||||
{
|
||||
struct http_connection_t *handle;
|
||||
transfer_cb_t cb;
|
||||
char elem1[PATH_MAX_LENGTH];
|
||||
} connection;
|
||||
msg_queue_t *msg_queue;
|
||||
struct http_t *handle;
|
||||
transfer_cb_t cb;
|
||||
|
156
net_http.c
156
net_http.c
@ -53,42 +53,15 @@ struct http_t
|
||||
char * data;
|
||||
};
|
||||
|
||||
static bool net_http_parse_url(char *url, char **domain,
|
||||
int *port, char **location)
|
||||
struct http_connection_t
|
||||
{
|
||||
char *domain;
|
||||
char *location;
|
||||
char *urlcopy;
|
||||
char* scan;
|
||||
int port;
|
||||
};
|
||||
|
||||
if (strncmp(url, "http://", strlen("http://")) != 0)
|
||||
return false;
|
||||
|
||||
scan = url + strlen("http://");
|
||||
*domain = scan;
|
||||
|
||||
while (*scan != '/' && *scan != ':' && *scan != '\0')
|
||||
scan++;
|
||||
|
||||
if (*scan == '\0')
|
||||
return false;
|
||||
|
||||
*scan = '\0';
|
||||
*port = 80;
|
||||
|
||||
if (*scan == ':')
|
||||
{
|
||||
|
||||
if (!isdigit(scan[1]))
|
||||
return false;
|
||||
|
||||
*port = strtoul(scan + 1, &scan, 10);
|
||||
|
||||
if (*scan != '/')
|
||||
return false;
|
||||
}
|
||||
|
||||
*location = scan + 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int net_http_new_socket(const char * domain, int port)
|
||||
{
|
||||
@ -189,38 +162,118 @@ static ssize_t net_http_recv(int fd, bool *error,
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct http_t *net_http_new(const char * url)
|
||||
struct http_connection_t *net_http_connection_new(const char *url)
|
||||
{
|
||||
char **domain = NULL;
|
||||
struct http_connection_t *conn = (struct http_connection_t*)calloc(1,
|
||||
sizeof(struct http_connection_t));
|
||||
|
||||
if (!conn)
|
||||
return NULL;
|
||||
|
||||
conn->urlcopy = (char*)malloc(strlen(url) + 1);
|
||||
|
||||
if (!conn->urlcopy)
|
||||
goto error;
|
||||
|
||||
strcpy(conn->urlcopy, url);
|
||||
|
||||
if (strncmp(url, "http://", strlen("http://")) != 0)
|
||||
goto error;
|
||||
|
||||
conn->scan = conn->urlcopy + strlen("http://");
|
||||
|
||||
domain = &conn->domain;
|
||||
|
||||
*domain = conn->scan;
|
||||
|
||||
return conn;
|
||||
|
||||
error:
|
||||
if (conn->urlcopy)
|
||||
free(conn->urlcopy);
|
||||
conn->urlcopy = NULL;
|
||||
if (conn)
|
||||
free(conn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool net_http_connection_iterate(struct http_connection_t *conn)
|
||||
{
|
||||
if (*conn->scan != '/' && *conn->scan != ':' && *conn->scan != '\0')
|
||||
{
|
||||
conn->scan++;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool net_http_connection_done(struct http_connection_t *conn)
|
||||
{
|
||||
char **location = NULL;
|
||||
|
||||
if (!conn)
|
||||
return false;
|
||||
|
||||
location = &conn->location;
|
||||
|
||||
if (*conn->scan == '\0')
|
||||
return false;
|
||||
|
||||
*conn->scan = '\0';
|
||||
conn->port = 80;
|
||||
|
||||
if (*conn->scan == ':')
|
||||
{
|
||||
|
||||
if (!isdigit(conn->scan[1]))
|
||||
return false;
|
||||
|
||||
conn->port = strtoul(conn->scan + 1, &conn->scan, 10);
|
||||
|
||||
if (*conn->scan != '/')
|
||||
return false;
|
||||
}
|
||||
|
||||
*location = conn->scan + 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void net_http_connection_free(struct http_connection_t *conn)
|
||||
{
|
||||
if (conn->urlcopy)
|
||||
free(conn->urlcopy);
|
||||
}
|
||||
|
||||
struct http_t *net_http_new(struct http_connection_t *conn)
|
||||
{
|
||||
bool error;
|
||||
char *domain = NULL, *location = NULL;
|
||||
int port = 0, fd = -1;
|
||||
int fd = -1;
|
||||
struct http_t *state = NULL;
|
||||
char *urlcopy =(char*)malloc(strlen(url)+1);
|
||||
|
||||
strcpy(urlcopy, url);
|
||||
if (!conn)
|
||||
goto error;
|
||||
|
||||
if (!net_http_parse_url(urlcopy, &domain, &port, &location))
|
||||
goto fail;
|
||||
|
||||
fd = net_http_new_socket(domain, port);
|
||||
fd = net_http_new_socket(conn->domain, conn->port);
|
||||
if (fd == -1)
|
||||
goto fail;
|
||||
goto error;
|
||||
|
||||
error=false;
|
||||
|
||||
/* This is a bit lazy, but it works. */
|
||||
net_http_send_str(fd, &error, "GET /");
|
||||
net_http_send_str(fd, &error, location);
|
||||
net_http_send_str(fd, &error, conn->location);
|
||||
net_http_send_str(fd, &error, " HTTP/1.1\r\n");
|
||||
|
||||
net_http_send_str(fd, &error, "Host: ");
|
||||
net_http_send_str(fd, &error, domain);
|
||||
net_http_send_str(fd, &error, conn->domain);
|
||||
|
||||
if (port!=80)
|
||||
if (conn->port != 80)
|
||||
{
|
||||
char portstr[16];
|
||||
|
||||
snprintf(portstr, sizeof(portstr), ":%i", port);
|
||||
snprintf(portstr, sizeof(portstr), ":%i", conn->port);
|
||||
net_http_send_str(fd, &error, portstr);
|
||||
}
|
||||
|
||||
@ -229,9 +282,7 @@ struct http_t *net_http_new(const char * url)
|
||||
net_http_send_str(fd, &error, "\r\n");
|
||||
|
||||
if (error)
|
||||
goto fail;
|
||||
|
||||
free(urlcopy);
|
||||
goto error;
|
||||
|
||||
state = (struct http_t*)malloc(sizeof(struct http_t));
|
||||
state->fd = fd;
|
||||
@ -246,14 +297,13 @@ struct http_t *net_http_new(const char * url)
|
||||
state->data = (char*)malloc(state->buflen);
|
||||
|
||||
if (!state->data)
|
||||
goto fail;
|
||||
goto error;
|
||||
|
||||
return state;
|
||||
|
||||
fail:
|
||||
error:
|
||||
if (fd != -1)
|
||||
socket_close(fd);
|
||||
free(urlcopy);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
11
net_http.h
11
net_http.h
@ -26,8 +26,17 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
struct http_t;
|
||||
struct http_connection_t;
|
||||
|
||||
struct http_t *net_http_new(const char * url);
|
||||
struct http_connection_t *net_http_connection_new(const char *url);
|
||||
|
||||
bool net_http_connection_iterate(struct http_connection_t *conn);
|
||||
|
||||
bool net_http_connection_done(struct http_connection_t *conn);
|
||||
|
||||
void net_http_connection_free(struct http_connection_t *conn);
|
||||
|
||||
struct http_t *net_http_new(struct http_connection_t *conn);
|
||||
|
||||
/* You can use this to call net_http_update
|
||||
* only when something will happen; select() it for reading. */
|
||||
|
@ -50,6 +50,28 @@ static int rarch_main_iterate_http_transfer(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rarch_main_iterate_http_conn_transfer(void)
|
||||
{
|
||||
if (!net_http_connection_iterate(g_extern.http.connection.handle))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rarch_main_iterate_http_conn_parse(void)
|
||||
{
|
||||
if (net_http_connection_done(g_extern.http.connection.handle))
|
||||
{
|
||||
if (g_extern.http.connection.handle && g_extern.http.connection.cb)
|
||||
g_extern.http.connection.cb(g_extern.http.connection.handle, 0);
|
||||
}
|
||||
|
||||
net_http_connection_free(g_extern.http.connection.handle);
|
||||
|
||||
g_extern.http.connection.handle = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rarch_main_iterate_http_parse(void)
|
||||
{
|
||||
size_t len;
|
||||
@ -66,6 +88,29 @@ static int rarch_main_iterate_http_parse(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cb_http_conn_default(void *data_, size_t len)
|
||||
{
|
||||
g_extern.http.handle = net_http_new(g_extern.http.connection.handle);
|
||||
|
||||
if (!g_extern.http.handle)
|
||||
{
|
||||
RARCH_ERR("Could not create new HTTP session handle.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
g_extern.http.cb = NULL;
|
||||
|
||||
if (g_extern.http.connection.elem1[0] != '\0')
|
||||
{
|
||||
if (!strcmp(g_extern.http.connection.elem1, "cb_core_updater_download"))
|
||||
g_extern.http.cb = &cb_core_updater_download;
|
||||
if (!strcmp(g_extern.http.connection.elem1, "cb_core_updater_list"))
|
||||
g_extern.http.cb = &cb_core_updater_list;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* rarch_main_iterate_http_transfer:
|
||||
*
|
||||
@ -81,7 +126,7 @@ static int rarch_main_iterate_http_parse(void)
|
||||
**/
|
||||
static int rarch_main_iterate_http_poll(void)
|
||||
{
|
||||
char elem0[PATH_MAX_LENGTH], elem1[PATH_MAX_LENGTH];
|
||||
char elem0[PATH_MAX_LENGTH];
|
||||
struct string_list *str_list = NULL;
|
||||
const char *url = msg_queue_pull(g_extern.http.msg_queue);
|
||||
|
||||
@ -99,27 +144,18 @@ static int rarch_main_iterate_http_poll(void)
|
||||
|
||||
if (str_list->size > 0)
|
||||
strlcpy(elem0, str_list->elems[0].data, sizeof(elem0));
|
||||
if (str_list->size > 1)
|
||||
strlcpy(elem1, str_list->elems[1].data, sizeof(elem1));
|
||||
|
||||
g_extern.http.handle = net_http_new(elem0);
|
||||
g_extern.http.connection.handle = net_http_connection_new(elem0);
|
||||
|
||||
if (!g_extern.http.handle)
|
||||
{
|
||||
RARCH_ERR("Could not create new HTTP session handle.\n");
|
||||
string_list_free(str_list);
|
||||
if (!g_extern.http.connection.handle)
|
||||
return -1;
|
||||
}
|
||||
|
||||
g_extern.http.cb = NULL;
|
||||
g_extern.http.connection.cb = &cb_http_conn_default;
|
||||
|
||||
if (elem1[0] != '\0')
|
||||
{
|
||||
if (!strcmp(elem1, "cb_core_updater_download"))
|
||||
g_extern.http.cb = &cb_core_updater_download;
|
||||
if (!strcmp(elem1, "cb_core_updater_list"))
|
||||
g_extern.http.cb = &cb_core_updater_list;
|
||||
}
|
||||
if (str_list->size > 1)
|
||||
strlcpy(g_extern.http.connection.elem1,
|
||||
str_list->elems[1].data,
|
||||
sizeof(g_extern.http.connection.elem1));
|
||||
|
||||
string_list_free(str_list);
|
||||
|
||||
@ -500,6 +536,12 @@ void do_data_state_checks(void)
|
||||
do_data_nbio_state_checks(&g_extern.nbio);
|
||||
|
||||
#ifdef HAVE_NETWORKING
|
||||
if (g_extern.http.connection.handle)
|
||||
{
|
||||
if (!rarch_main_iterate_http_conn_transfer())
|
||||
rarch_main_iterate_http_conn_parse();
|
||||
}
|
||||
|
||||
if (g_extern.http.handle)
|
||||
{
|
||||
if (!rarch_main_iterate_http_transfer())
|
||||
|
Loading…
Reference in New Issue
Block a user