This commit is contained in:
libretroadmin 2023-08-17 15:13:19 +02:00
parent 7edbfaf17b
commit 05ad9b439f
4 changed files with 205 additions and 19 deletions

View file

@ -1833,6 +1833,22 @@ enum retro_mod
* input devices does not need to take any action on its own.
*/
#define RETRO_ENVIRONMENT_GET_DEVICE_POWER (77 | RETRO_ENVIRONMENT_EXPERIMENTAL)
/* struct retro_device_power * --
* Returns the device's current power state as reported by the frontend.
* This is useful for emulating the battery level in handheld consoles,
* or for reducing power consumption when on battery power.
*
* The return value indicates whether the frontend can provide this information,
* even if the parameter is NULL.
*
* If the frontend does not support this functionality,
* then the provided argument will remain unchanged.
*
* Note that this environment call describes the power state for the entire device,
* not for individual peripherals like controllers.
*/
/* VFS functionality */
/* File paths:
@ -3133,7 +3149,7 @@ typedef void (RETRO_CALLCONV *retro_netpacket_disconnected_t)(uint16_t client_id
/**
* A callback interface for giving a core the ability to send and receive custom
* network packets during a multiplayer session between two or more instances
* network packets during a multiplayer session between two or more instances
* of a libretro frontend.
*
* @see RETRO_ENVIRONMENT_SET_NETPACKET_INTERFACE
@ -4153,6 +4169,86 @@ struct retro_microphone_interface
retro_read_mic_t read_mic;
};
/**
* Describes how a device is being powered.
* @see RETRO_ENVIRONMENT_GET_DEVICE_POWER
*/
enum retro_power_state
{
/**
* Indicates that the frontend cannot report its power state at this time,
* most likely due to a lack of support.
*
* \c RETRO_ENVIRONMENT_GET_DEVICE_POWER will not return this value;
* instead, the environment callback will return \c false.
*/
RETRO_POWERSTATE_UNKNOWN = 0,
/**
* Indicates that the device is running on its battery.
* Usually applies to portable devices such as handhelds, laptops, and smartphones.
*/
RETRO_POWERSTATE_DISCHARGING,
/**
* Indicates that the device's battery is currently charging.
*/
RETRO_POWERSTATE_CHARGING,
/**
* Indicates that the device is connected to a power source
* and that its battery has finished charging.
*/
RETRO_POWERSTATE_CHARGED,
/**
* Indicates that the device is connected to a power source
* and that it does not have a battery.
* This usually suggests a desktop computer or a non-portable game console.
*/
RETRO_POWERSTATE_PLUGGED_IN
};
/**
* Indicates that an estimate is not available for the battery level or time remaining,
* even if the actual power state is known.
*/
#define RETRO_POWERSTATE_NO_ESTIMATE (-1)
/**
* Describes the power state of the device running the frontend.
* @see RETRO_ENVIRONMENT_GET_DEVICE_POWER
*/
struct retro_device_power
{
/**
* The current state of the frontend's power usage.
*/
enum retro_power_state state;
/**
* A rough estimate of the amount of time remaining (in seconds)
* before the device powers off.
* This value depends on a variety of factors,
* so it is not guaranteed to be accurate.
*
* Will be set to \c RETRO_POWERSTATE_NO_ESTIMATE if \c state does not equal \c RETRO_POWERSTATE_DISCHARGING.
* May still be set to \c RETRO_POWERSTATE_NO_ESTIMATE if the frontend is unable to provide an estimate.
*/
int seconds;
/**
* The approximate percentage of battery charge,
* ranging from 0 to 100 (inclusive).
* The device may power off before this reaches 0.
*
* The user might have configured their device
* to stop charging before the battery is full,
* so do not assume that this will be 100 in the \c RETRO_POWERSTATE_CHARGED state.
*/
int8_t percent;
};
/* Callbacks */
/* Environment callback. Gives implementations a way of performing

View file

@ -51,6 +51,9 @@ void net_http_connection_set_user_agent(struct http_connection_t *conn, const ch
void net_http_connection_set_headers(struct http_connection_t *conn, const char *headers);
void net_http_connection_set_content(struct http_connection_t *conn, const char *content_type,
size_t content_length, const void *content);
const char *net_http_connection_url(struct http_connection_t *conn);
const char* net_http_connection_method(struct http_connection_t* conn);
@ -93,6 +96,17 @@ int net_http_status(struct http_t *state);
**/
bool net_http_error(struct http_t *state);
/**
* net_http_headers:
*
* Leaf function.
*
* @return the response headers. The returned buffer is owned by the
* caller of net_http_new; it is not freed by net_http_delete.
* If the status is not 20x and accept_error is false, it returns NULL.
**/
struct string_list *net_http_headers(struct http_t *state);
/**
* net_http_data:
*

View file

@ -33,6 +33,7 @@
#include <compat/strl.h>
#include <string/stdstring.h>
#include <string.h>
#include <lists/string_list.h>
#include <retro_common_api.h>
#include <retro_miscellaneous.h>
@ -63,6 +64,7 @@ struct http_socket_state_t
struct http_t
{
char *data;
struct string_list *headers;
struct http_socket_state_t sock_state; /* ptr alignment */
size_t pos;
size_t len;
@ -81,10 +83,11 @@ struct http_connection_t
char *scan;
char *methodcopy;
char *contenttypecopy;
char *postdatacopy;
void *postdatacopy;
char *useragentcopy;
char *headerscopy;
struct http_socket_state_t sock_state; /* ptr alignment */
size_t contentlength;
int port;
};
@ -530,7 +533,10 @@ struct http_connection_t *net_http_connection_new(const char *url,
conn->methodcopy = strdup(method);
if (data)
{
conn->postdatacopy = strdup(data);
conn->contentlength = strlen(data);
}
if (!(conn->urlcopy = strdup(url)))
goto error;
@ -703,6 +709,25 @@ void net_http_connection_set_headers(
conn->headerscopy = headers ? strdup(headers) : NULL;
}
void net_http_connection_set_content(
struct http_connection_t *conn, const char *content_type,
size_t content_length, const void *content)
{
if (conn->contenttypecopy)
free(conn->contenttypecopy);
if (conn->postdatacopy)
free(conn->postdatacopy);
conn->contenttypecopy = content_type ? strdup(content_type) : NULL;
conn->contentlength = content_length;
if (content_length)
{
conn->postdatacopy = malloc(content_length);
memcpy(conn->postdatacopy, content, content_length);
}
}
const char *net_http_connection_url(struct http_connection_t *conn)
{
return conn->urlcopy;
@ -767,8 +792,7 @@ struct http_t *net_http_new(struct http_connection_t *conn)
if (conn->headerscopy)
net_http_send_str(&conn->sock_state, &error, conn->headerscopy,
strlen(conn->headerscopy));
/* This is not being set anywhere yet */
else if (conn->contenttypecopy)
if (conn->contenttypecopy)
{
net_http_send_str(&conn->sock_state, &error, "Content-Type: ",
STRLEN_CONST("Content-Type: "));
@ -778,12 +802,12 @@ struct http_t *net_http_new(struct http_connection_t *conn)
STRLEN_CONST("\r\n"));
}
if (conn->methodcopy && (string_is_equal(conn->methodcopy, "POST")))
if (conn->methodcopy && (string_is_equal(conn->methodcopy, "POST") || string_is_equal(conn->methodcopy, "PUT")))
{
size_t post_len, len;
char *len_str = NULL;
if (!conn->postdatacopy)
if (!conn->postdatacopy && !string_is_equal(conn->methodcopy, "PUT"))
goto err;
if (!conn->headerscopy)
@ -799,7 +823,7 @@ struct http_t *net_http_new(struct http_connection_t *conn)
net_http_send_str(&conn->sock_state, &error, "Content-Length: ",
STRLEN_CONST("Content-Length: "));
post_len = strlen(conn->postdatacopy);
post_len = conn->contentlength;
#ifdef _WIN32
len = snprintf(NULL, 0, "%" PRIuPTR, post_len);
len_str = (char*)malloc(len + 1);
@ -836,9 +860,9 @@ struct http_t *net_http_new(struct http_connection_t *conn)
net_http_send_str(&conn->sock_state, &error, "\r\n",
STRLEN_CONST("\r\n"));
if (conn->methodcopy && (string_is_equal(conn->methodcopy, "POST")))
if (conn->postdatacopy && conn->contentlength)
net_http_send_str(&conn->sock_state, &error, conn->postdatacopy,
strlen(conn->postdatacopy));
conn->contentlength);
if (!error)
{
@ -854,7 +878,12 @@ struct http_t *net_http_new(struct http_connection_t *conn)
state->buflen = 512;
if ((state->data = (char*)malloc(state->buflen)))
return state;
{
if ((state->headers = string_list_new()) &&
string_list_initialize(state->headers))
return state;
string_list_free(state->headers);
}
free(state);
}
@ -865,6 +894,8 @@ err:
free(conn->methodcopy);
if (conn->contenttypecopy)
free(conn->contenttypecopy);
if (conn->postdatacopy)
free(conn->postdatacopy);
conn->methodcopy = NULL;
conn->contenttypecopy = NULL;
conn->postdatacopy = NULL;
@ -981,12 +1012,24 @@ bool net_http_update(struct http_t *state, size_t* progress, size_t* total)
if (string_is_equal_case_insensitive(state->data, "Transfer-Encoding: chunked"))
state->bodytype = T_CHUNK;
/* TODO: save headers somewhere */
if (state->data[0]=='\0')
{
state->part = P_BODY;
if (state->bodytype == T_CHUNK)
state->part = P_BODY_CHUNKLEN;
if (state->status == 100)
{
state->part = P_HEADER_TOP;
}
else
{
state->part = P_BODY;
if (state->bodytype == T_CHUNK)
state->part = P_BODY_CHUNKLEN;
}
}
else
{
union string_list_elem_attr attr;
attr.i = 0;
string_list_append(state->headers, state->data, attr);
}
}
@ -1007,7 +1050,7 @@ bool net_http_update(struct http_t *state, size_t* progress, size_t* total)
{
if (state->error)
newlen = -1;
else
else if (state->len)
{
#ifdef HAVE_SSL
if (state->sock_state.ssl && state->sock_state.ssl_ctx)
@ -1158,6 +1201,26 @@ int net_http_status(struct http_t *state)
return state->status;
}
/**
* net_http_headers:
*
* Leaf function.
*
* @return the response headers. The returned buffer is owned by the
* caller of net_http_new; it is not freed by net_http_delete().
* If the status is not 20x and accept_error is false, it returns NULL.
**/
struct string_list *net_http_headers(struct http_t *state)
{
if (!state)
return NULL;
if (state->error)
return NULL;
return state->headers;
}
/**
* net_http_data:
*

View file

@ -234,11 +234,24 @@ int ssl_socket_send_all_blocking(void *state_data,
mbedtls_net_set_block(&state->net_ctx);
while ((ret = mbedtls_ssl_write(&state->ctx, data, size)) <= 0)
while (size)
{
if ( ret != MBEDTLS_ERR_SSL_WANT_READ &&
ret != MBEDTLS_ERR_SSL_WANT_WRITE)
return false;
ret = mbedtls_ssl_write(&state->ctx, data, size);
if (!ret)
continue;
if (ret < 0)
{
if ( ret != MBEDTLS_ERR_SSL_WANT_READ &&
ret != MBEDTLS_ERR_SSL_WANT_WRITE)
return false;
}
else
{
data += ret;
size -= ret;
}
}
return true;