Use mp_printf instead of snprintf

This commit is contained in:
Scott Shawcroft 2022-07-25 16:58:54 -07:00
parent 66d5fa9a55
commit f4927dd2d6
No known key found for this signature in database
GPG Key ID: 0DFD512649C052DA

View File

@ -306,6 +306,10 @@ static void _send_raw(socketpool_socket_obj_t *socket, const uint8_t *buf, int l
} }
} }
STATIC void _print_raw(void *env, const char *str, size_t len) {
_send_raw((socketpool_socket_obj_t *)env, (const uint8_t *)str, (size_t)len);
}
static void _send_str(socketpool_socket_obj_t *socket, const char *str) { static void _send_str(socketpool_socket_obj_t *socket, const char *str) {
_send_raw(socket, (const uint8_t *)str, strlen(str)); _send_raw(socket, (const uint8_t *)str, strlen(str));
} }
@ -324,14 +328,19 @@ static void _send_strs(socketpool_socket_obj_t *socket, ...) {
} }
static void _send_chunk(socketpool_socket_obj_t *socket, const char *chunk) { static void _send_chunk(socketpool_socket_obj_t *socket, const char *chunk) {
char encoded_len[sizeof(size_t) * 2 + 1]; mp_print_t _socket_print = {socket, _print_raw};
int len = snprintf(encoded_len, sizeof(encoded_len), "%X", strlen(chunk)); mp_printf(&_socket_print, "%X\r\n", strlen(chunk));
_send_raw(socket, (const uint8_t *)encoded_len, len);
_send_raw(socket, (const uint8_t *)"\r\n", 2);
_send_raw(socket, (const uint8_t *)chunk, strlen(chunk)); _send_raw(socket, (const uint8_t *)chunk, strlen(chunk));
_send_raw(socket, (const uint8_t *)"\r\n", 2); _send_raw(socket, (const uint8_t *)"\r\n", 2);
} }
STATIC void _print_chunk(void *env, const char *str, size_t len) {
mp_print_t _socket_print = {socket, _print_raw};
mp_printf(&_socket_print, "%X\r\n", len);
_send_raw((socketpool_socket_obj_t *)env, (const uint8_t *)str, len);
_send_raw((socketpool_socket_obj_t *)env, (const uint8_t *)"\r\n", 2);
}
// A bit of a misnomer because it sends all arguments as one chunk. // A bit of a misnomer because it sends all arguments as one chunk.
// The last argument must be NULL! Otherwise, it won't stop. // The last argument must be NULL! Otherwise, it won't stop.
static void _send_chunks(socketpool_socket_obj_t *socket, ...) { static void _send_chunks(socketpool_socket_obj_t *socket, ...) {
@ -349,9 +358,9 @@ static void _send_chunks(socketpool_socket_obj_t *socket, ...) {
} }
va_end(strs_to_count); va_end(strs_to_count);
char encoded_len[sizeof(size_t) * 2 + 1];
snprintf(encoded_len, sizeof(encoded_len), "%X", chunk_len); mp_print_t _socket_print = {socket, _print_raw};
_send_strs(socket, encoded_len, "\r\n", NULL); mp_printf(&_socket_print, "%X\r\n", chunk_len);
str = va_arg(strs_to_send, const char *); str = va_arg(strs_to_send, const char *);
while (str != NULL) { while (str != NULL) {
@ -556,9 +565,8 @@ static void _reply_redirect(socketpool_socket_obj_t *socket, _request *request,
_send_strs(socket, "://", hostname, ".local", NULL); _send_strs(socket, "://", hostname, ".local", NULL);
if (web_api_port != 80) { if (web_api_port != 80) {
char encoded_port[6]; mp_print_t _socket_print = {socket, _print_raw};
snprintf(encoded_port, sizeof(encoded_port), "%d", web_api_port); mp_printf(&_socket_print, ":%d", web_api_port);
_send_strs(socket, ":", encoded_port, NULL);
} }
_send_strs(socket, path, "\r\n", NULL); _send_strs(socket, path, "\r\n", NULL);
_cors_header(socket, request); _cors_header(socket, request);
@ -569,6 +577,7 @@ static void _reply_directory_json(socketpool_socket_obj_t *socket, _request *req
socketpool_socket_send(socket, (const uint8_t *)OK_JSON, strlen(OK_JSON)); socketpool_socket_send(socket, (const uint8_t *)OK_JSON, strlen(OK_JSON));
_cors_header(socket, request); _cors_header(socket, request);
_send_str(socket, "\r\n"); _send_str(socket, "\r\n");
mp_print_t _socket_print = {socket, _print_chunk};
_send_chunk(socket, "["); _send_chunk(socket, "[");
bool first = true; bool first = true;
@ -589,7 +598,7 @@ static void _reply_directory_json(socketpool_socket_obj_t *socket, _request *req
} }
// We use nanoseconds past Jan 1, 1970 for consistency with BLE API and // We use nanoseconds past Jan 1, 1970 for consistency with BLE API and
// LittleFS. // LittleFS.
_send_chunk(socket, ", \"modified_ns\": "); _send_chunk(socket, ", ");
uint64_t truncated_time = timeutils_mktime(1980 + (file_info.fdate >> 9), uint64_t truncated_time = timeutils_mktime(1980 + (file_info.fdate >> 9),
(file_info.fdate >> 5) & 0xf, (file_info.fdate >> 5) & 0xf,
@ -598,15 +607,13 @@ static void _reply_directory_json(socketpool_socket_obj_t *socket, _request *req
(file_info.ftime >> 5) & 0x1f, (file_info.ftime >> 5) & 0x1f,
(file_info.ftime & 0x1f) * 2) * 1000000000ULL; (file_info.ftime & 0x1f) * 2) * 1000000000ULL;
char encoded_number[32]; mp_printf(&_socket_print, "\"modified_ns\": %lld, ", truncated_time);
snprintf(encoded_number, sizeof(encoded_number), "%lld", truncated_time);
_send_chunks(socket, encoded_number, ", \"file_size\": ", NULL);
size_t file_size = 0; size_t file_size = 0;
if ((file_info.fattrib & AM_DIR) == 0) { if ((file_info.fattrib & AM_DIR) == 0) {
file_size = file_info.fsize; file_size = file_info.fsize;
} }
snprintf(encoded_number, sizeof(encoded_number), "%d", file_size); mp_printf(&_socket_print, "\"file_size\": %d }", file_size);
_send_chunks(socket, encoded_number, "}", NULL);
first = false; first = false;
res = f_readdir(dir, &file_info); res = f_readdir(dir, &file_info);
} }
@ -619,9 +626,9 @@ static void _reply_with_file(socketpool_socket_obj_t *socket, _request *request,
char encoded_len[10]; char encoded_len[10];
snprintf(encoded_len, sizeof(encoded_len), "%d", total_length); snprintf(encoded_len, sizeof(encoded_len), "%d", total_length);
_send_strs(socket, _send_str(socket, "HTTP/1.1 200 OK\r\n");
"HTTP/1.1 200 OK\r\n", mp_print_t _socket_print = {socket, _print_raw};
"Content-Length: ", encoded_len, "\r\n", NULL); mp_printf(&_socket_print, "Content-Length: %d\r\n", total_length);
// TODO: Make this a table to save space. // TODO: Make this a table to save space.
if (_endswith(filename, ".txt") || _endswith(filename, ".py")) { if (_endswith(filename, ".txt") || _endswith(filename, ".py")) {
_send_str(socket, "Content-Type: text/plain\r\n"); _send_str(socket, "Content-Type: text/plain\r\n");
@ -669,27 +676,23 @@ static void _reply_with_devices_json(socketpool_socket_obj_t *socket, _request *
socketpool_socket_send(socket, (const uint8_t *)OK_JSON, strlen(OK_JSON)); socketpool_socket_send(socket, (const uint8_t *)OK_JSON, strlen(OK_JSON));
_cors_header(socket, request); _cors_header(socket, request);
_send_str(socket, "\r\n"); _send_str(socket, "\r\n");
char total_encoded[4]; mp_print_t _socket_print = {socket, _print_chunk};
snprintf(total_encoded, sizeof(total_encoded), "%d", total_results);
_send_chunks(socket, "{\"total\": ", total_encoded, ", \"devices\": [", NULL); mp_printf(&_socket_print, "{\"total\": %d, \"devices\": [", total_results);
for (size_t i = 0; i < count; i++) { for (size_t i = 0; i < count; i++) {
if (i > 0) { if (i > 0) {
_send_chunk(socket, ","); _send_chunk(socket, ",");
} }
const char *hostname = common_hal_mdns_remoteservice_get_hostname(&found_devices[i]); const char *hostname = common_hal_mdns_remoteservice_get_hostname(&found_devices[i]);
const char *instance_name = common_hal_mdns_remoteservice_get_instance_name(&found_devices[i]); const char *instance_name = common_hal_mdns_remoteservice_get_instance_name(&found_devices[i]);
char port_encoded[6];
int port = common_hal_mdns_remoteservice_get_port(&found_devices[i]); int port = common_hal_mdns_remoteservice_get_port(&found_devices[i]);
snprintf(port_encoded, sizeof(port_encoded), "%d", port);
char ip_encoded[4 * 4];
uint32_t ipv4_address = mdns_remoteservice_get_ipv4_address(&found_devices[i]); uint32_t ipv4_address = mdns_remoteservice_get_ipv4_address(&found_devices[i]);
uint8_t *octets = (uint8_t *)&ipv4_address; uint8_t *octets = (uint8_t *)&ipv4_address;
snprintf(ip_encoded, sizeof(ip_encoded), "%d.%d.%d.%d", octets[0], octets[1], octets[2], octets[3]); mp_printf(&_socket_print,
_send_chunks(socket, "{\"hostname\": \"%s\", "
"{\"hostname\": \"", hostname, "\", ", "\"instance_name\": \"%s\", "
"\"instance_name\": \"", instance_name, "\", ", "\"port\": %d, "
"\"port\": ", port_encoded, ", ", "\"ip\": \"%d.%d.%d.%d\"}", hostname, instance_name, port, octets[0], octets[1], octets[2], octets[3]);
"\"ip\": \"", ip_encoded, "\"}", NULL);
common_hal_mdns_remoteservice_deinit(&found_devices[i]); common_hal_mdns_remoteservice_deinit(&found_devices[i]);
} }
_send_chunk(socket, "]}"); _send_chunk(socket, "]}");
@ -701,26 +704,22 @@ static void _reply_with_version_json(socketpool_socket_obj_t *socket, _request *
_send_str(socket, OK_JSON); _send_str(socket, OK_JSON);
_cors_header(socket, request); _cors_header(socket, request);
_send_str(socket, "\r\n"); _send_str(socket, "\r\n");
char encoded_creator_id[11]; // 2 ** 32 is 10 decimal digits plus one for \0 mp_print_t _socket_print = {socket, _print_chunk};
snprintf(encoded_creator_id, sizeof(encoded_creator_id), "%u", CIRCUITPY_CREATOR_ID);
char encoded_creation_id[11]; // 2 ** 32 is 10 decimal digits plus one for \0
snprintf(encoded_creation_id, sizeof(encoded_creation_id), "%u", CIRCUITPY_CREATION_ID);
const char *hostname = common_hal_mdns_server_get_hostname(&mdns); const char *hostname = common_hal_mdns_server_get_hostname(&mdns);
char encoded_port[6]; // Note: this leverages the fact that C concats consecutive string literals together.
snprintf(encoded_port, sizeof(encoded_port), "%d", web_api_port); mp_printf(&_socket_print,
_send_chunks(socket, "{\"web_api_version\": 1, "
"{\"web_api_version\": 1, ", "\"version\": \"" MICROPY_GIT_TAG "\", "
"\"version\": \"", MICROPY_GIT_TAG, "\", ", "\"build_date\": \"" MICROPY_BUILD_DATE "\", "
"\"build_date\": \"", MICROPY_BUILD_DATE, "\", ", "\"board_name\": \"" MICROPY_HW_BOARD_NAME "\", "
"\"board_name\": \"", MICROPY_HW_BOARD_NAME, "\", ", "\"mcu_name\": \"" MICROPY_HW_MCU_NAME "\", "
"\"mcu_name\": \"", MICROPY_HW_MCU_NAME, "\", ", "\"board_id\": \"" CIRCUITPY_BOARD_ID "\", "
"\"board_id\": \"", CIRCUITPY_BOARD_ID, "\", ", "\"creator_id\": %u, "
"\"creator_id\": ", encoded_creator_id, ", ", "\"creation_id\": %u, "
"\"creation_id\": ", encoded_creation_id, ", ", "\"hostname\": \"%s\", "
"\"hostname\": \"", hostname, "\", ", "\"port\": %d, "
"\"port\": ", encoded_port, ", ", "\"ip\": \"%s\"}", CIRCUITPY_CREATOR_ID, CIRCUITPY_CREATION_ID, hostname, web_api_port, _our_ip_encoded);
"\"ip\": \"", _our_ip_encoded,
"\"}", NULL);
// Empty chunk signals the end of the response. // Empty chunk signals the end of the response.
_send_chunk(socket, ""); _send_chunk(socket, "");
} }