static int rarch_main_data_http_iterate_transfer_parse(http_handle_t *http) { size_t len; char *data = (char*)net_http_data(http->handle, &len, false); if (data && http->cb) http->cb(data, len); net_http_delete(http->handle); http->handle = NULL; msg_queue_clear(http->msg_queue); return 0; }
static void rarch_task_http_transfer_handler(rarch_task_t *task) { http_handle_t *http = (http_handle_t*)task->state; http_transfer_data_t *data; switch (http->status) { case HTTP_STATUS_CONNECTION_TRANSFER_PARSE: rarch_main_data_http_conn_iterate_transfer_parse(http); http->status = HTTP_STATUS_TRANSFER; break; case HTTP_STATUS_CONNECTION_TRANSFER: if (!rarch_main_data_http_con_iterate_transfer(http)) http->status = HTTP_STATUS_CONNECTION_TRANSFER_PARSE; break; case HTTP_STATUS_TRANSFER: if (!rarch_main_data_http_iterate_transfer(task)) goto task_finished; break; case HTTP_STATUS_TRANSFER_PARSE: case HTTP_STATUS_POLL: goto task_finished; default: break; } if (task->cancelled || http->error) goto task_finished; return; task_finished: task->finished = true; if (http->handle) { size_t len = 0; char *tmp = (char*)net_http_data(http->handle, &len, false); if (tmp && http->cb) http->cb(tmp, len); if (net_http_error(http->handle) || task->cancelled) { tmp = (char*)net_http_data(http->handle, &len, true); if (tmp) free(tmp); if (task->cancelled) task->error = strdup("Task cancelled."); else task->error = strdup("Download failed."); } else { data = (http_transfer_data_t*)calloc(1, sizeof(*data)); data->data = tmp; data->len = len; task->task_data = data; } net_http_delete(http->handle); } else if (http->error) task->error = strdup("Internal error."); free(http); }
int net_http_get(const char **result, size_t *size, const char *url, retro_time_t *timeout) { size_t length; uint8_t* data = NULL; char* res = NULL; 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); *result = NULL; /* Error creating the connection descriptor. */ if (!conn) goto error; /* Don't bother with timeouts here, it's just a string scan. */ while (!net_http_connection_iterate(conn)) {} /* Error finishing the connection descriptor. */ if (!net_http_connection_done(conn)) { ret = NET_HTTP_GET_MALFORMED_URL; goto error; } http = net_http_new(conn); /* Error connecting to the endpoint. */ if (!http) { ret = NET_HTTP_GET_CONNECT_ERROR; goto error; } while (!net_http_update(http, NULL, NULL)) { /* Timeout error. */ if (timeout && (cpu_features_get_time_usec() - t0) > *timeout) { ret = NET_HTTP_GET_TIMEOUT; goto error; } } data = net_http_data(http, &length, false); if (data) { res = (char*)malloc(length + 1); /* Allocation error. */ if ( !res ) goto error; memcpy((void*)res, (void*)data, length); free(data); res[length] = 0; *result = res; } else { length = 0; *result = NULL; } if (size) *size = length; error: if ( http ) net_http_delete( http ); if ( conn ) net_http_connection_free( conn ); if (timeout) { t0 = cpu_features_get_time_usec() - t0; if (t0 < *timeout) *timeout -= t0; else *timeout = 0; } return ret; }