Merge pull request #6742 from tannewt/c3_short_send

Retry send if only some bytes sent
This commit is contained in:
MicroDev 2022-08-13 15:22:27 +05:30 committed by GitHub
commit 28c93cad68
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 52 additions and 31 deletions

View File

@ -345,9 +345,6 @@ void reset_port(void) {
reset_all_pins(); reset_all_pins();
// A larger delay so the idle task can run and do any IDF cleanup needed.
vTaskDelay(4);
#if CIRCUITPY_ANALOGIO #if CIRCUITPY_ANALOGIO
analogout_reset(); analogout_reset();
#endif #endif
@ -402,6 +399,9 @@ void reset_port(void) {
#if CIRCUITPY_WATCHDOG #if CIRCUITPY_WATCHDOG
watchdog_reset(); watchdog_reset();
#endif #endif
// Yield so the idle task can run and do any IDF cleanup needed.
port_yield();
} }
void reset_to_bootloader(void) { void reset_to_bootloader(void) {
@ -492,6 +492,10 @@ void port_wake_main_task_from_isr() {
} }
} }
void port_yield() {
vTaskDelay(4);
}
void sleep_timer_cb(void *arg) { void sleep_timer_cb(void *arg) {
port_wake_main_task(); port_wake_main_task();
} }

View File

@ -109,6 +109,11 @@ void port_wake_main_task(void);
// default weak implementation is provided that does nothing. // default weak implementation is provided that does nothing.
void port_wake_main_task_from_isr(void); void port_wake_main_task_from_isr(void);
// Some ports may use real RTOS tasks besides the background task framework of
// CircuitPython. Calling this will yield to other tasks and then return to the
// CircuitPython task when others are done.
void port_yield(void);
// Some ports need special handling just after completing boot.py execution. // Some ports need special handling just after completing boot.py execution.
// This function is called once while boot.py's VM is still valid, and // This function is called once while boot.py's VM is still valid, and
// then a second time after the VM is finalized. // then a second time after the VM is finalized.

View File

@ -31,3 +31,6 @@ MP_WEAK void port_wake_main_task(void) {
MP_WEAK void port_wake_main_task_from_isr(void) { MP_WEAK void port_wake_main_task_from_isr(void) {
} }
MP_WEAK void port_yield(void) {
}

View File

@ -37,6 +37,7 @@
#include "shared/timeutils/timeutils.h" #include "shared/timeutils/timeutils.h"
#include "supervisor/fatfs_port.h" #include "supervisor/fatfs_port.h"
#include "supervisor/filesystem.h" #include "supervisor/filesystem.h"
#include "supervisor/port.h"
#include "supervisor/shared/reload.h" #include "supervisor/shared/reload.h"
#include "supervisor/shared/translate/translate.h" #include "supervisor/shared/translate/translate.h"
#include "supervisor/shared/web_workflow/web_workflow.h" #include "supervisor/shared/web_workflow/web_workflow.h"
@ -323,22 +324,31 @@ void supervisor_start_web_workflow(void) {
#endif #endif
} }
static void _send_raw(socketpool_socket_obj_t *socket, const uint8_t *buf, int len) { void web_workflow_send_raw(socketpool_socket_obj_t *socket, const uint8_t *buf, int len) {
int total_sent = 0;
int sent = -EAGAIN; int sent = -EAGAIN;
while (sent == -EAGAIN && common_hal_socketpool_socket_get_connected(socket)) { while ((sent == -EAGAIN || (sent > 0 && total_sent < len)) &&
sent = socketpool_socket_send(socket, buf, len); common_hal_socketpool_socket_get_connected(socket)) {
sent = socketpool_socket_send(socket, buf + total_sent, len - total_sent);
if (sent > 0) {
total_sent += sent;
if (total_sent < len) {
// Yield so that network code can run.
port_yield();
}
}
} }
if (sent < len) { if (total_sent < len) {
ESP_LOGE(TAG, "short send %d %d", sent, len); ESP_LOGE(TAG, "short send %d %d", sent, len);
} }
} }
STATIC void _print_raw(void *env, const char *str, size_t len) { 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); web_workflow_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)); web_workflow_send_raw(socket, (const uint8_t *)str, strlen(str));
} }
// The last argument must be NULL! Otherwise, it won't stop. // The last argument must be NULL! Otherwise, it won't stop.
@ -357,15 +367,15 @@ 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) {
mp_print_t _socket_print = {socket, _print_raw}; mp_print_t _socket_print = {socket, _print_raw};
mp_printf(&_socket_print, "%X\r\n", strlen(chunk)); mp_printf(&_socket_print, "%X\r\n", strlen(chunk));
_send_raw(socket, (const uint8_t *)chunk, strlen(chunk)); web_workflow_send_raw(socket, (const uint8_t *)chunk, strlen(chunk));
_send_raw(socket, (const uint8_t *)"\r\n", 2); web_workflow_send_raw(socket, (const uint8_t *)"\r\n", 2);
} }
STATIC void _print_chunk(void *env, const char *str, size_t len) { STATIC void _print_chunk(void *env, const char *str, size_t len) {
mp_print_t _socket_print = {env, _print_raw}; mp_print_t _socket_print = {env, _print_raw};
mp_printf(&_socket_print, "%X\r\n", len); mp_printf(&_socket_print, "%X\r\n", len);
_send_raw((socketpool_socket_obj_t *)env, (const uint8_t *)str, len); web_workflow_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); web_workflow_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.
@ -938,7 +948,7 @@ static void _reply_static(socketpool_socket_obj_t *socket, _request *request, co
"Content-Length: ", encoded_len, "\r\n", "Content-Length: ", encoded_len, "\r\n",
"Content-Type: ", content_type, "\r\n", "Content-Type: ", content_type, "\r\n",
"\r\n", NULL); "\r\n", NULL);
_send_raw(socket, response, response_len); web_workflow_send_raw(socket, response, response_len);
} }
#define _REPLY_STATIC(socket, request, filename) _reply_static(socket, request, filename, filename##_length, filename##_content_type) #define _REPLY_STATIC(socket, request, filename) _reply_static(socket, request, filename, filename##_length, filename##_content_type)

View File

@ -28,6 +28,8 @@
#include <stdbool.h> #include <stdbool.h>
#include "shared-bindings/socketpool/Socket.h"
// This background function should be called repeatedly. It cannot be done based // This background function should be called repeatedly. It cannot be done based
// on events. // on events.
void supervisor_web_workflow_background(void); void supervisor_web_workflow_background(void);
@ -35,3 +37,6 @@ bool supervisor_web_workflow_status_dirty(void);
void supervisor_web_workflow_status(void); void supervisor_web_workflow_status(void);
void supervisor_start_web_workflow(void); void supervisor_start_web_workflow(void);
void supervisor_stop_web_workflow(void); void supervisor_stop_web_workflow(void);
// To share with websocket.
void web_workflow_send_raw(socketpool_socket_obj_t *socket, const uint8_t *buf, int len);

View File

@ -30,6 +30,7 @@
#include "py/runtime.h" #include "py/runtime.h"
#include "shared/runtime/interrupt_char.h" #include "shared/runtime/interrupt_char.h"
#include "supervisor/shared/title_bar.h" #include "supervisor/shared/title_bar.h"
#include "supervisor/shared/web_workflow/web_workflow.h"
// TODO: Remove ESP specific stuff. For now, it is useful as we refine the server. // TODO: Remove ESP specific stuff. For now, it is useful as we refine the server.
#include "esp_log.h" #include "esp_log.h"
@ -91,16 +92,6 @@ static bool _read_byte(uint8_t *c) {
return true; return true;
} }
static void _send_raw(socketpool_socket_obj_t *socket, const uint8_t *buf, int len) {
int sent = -EAGAIN;
while (sent == -EAGAIN) {
sent = socketpool_socket_send(socket, buf, len);
}
if (sent < len) {
ESP_LOGE(TAG, "short send on %d err %d len %d", socket->num, sent, len);
}
}
static void _read_next_frame_header(void) { static void _read_next_frame_header(void) {
uint8_t h; uint8_t h;
if (cp_serial.frame_index == 0 && _read_byte(&h)) { if (cp_serial.frame_index == 0 && _read_byte(&h)) {
@ -159,14 +150,14 @@ static void _read_next_frame_header(void) {
ESP_LOGE(TAG, "CLOSE or PING has long payload"); ESP_LOGE(TAG, "CLOSE or PING has long payload");
} }
frame_header[1] = cp_serial.payload_remaining; frame_header[1] = cp_serial.payload_remaining;
_send_raw(&cp_serial.socket, (const uint8_t *)frame_header, 2); web_workflow_send_raw(&cp_serial.socket, (const uint8_t *)frame_header, 2);
} }
if (cp_serial.payload_remaining > 0 && _read_byte(&h)) { if (cp_serial.payload_remaining > 0 && _read_byte(&h)) {
// Send the payload back to the client. // Send the payload back to the client.
cp_serial.frame_index++; cp_serial.frame_index++;
cp_serial.payload_remaining--; cp_serial.payload_remaining--;
_send_raw(&cp_serial.socket, &h, 1); web_workflow_send_raw(&cp_serial.socket, &h, 1);
} }
if (cp_serial.payload_remaining == 0) { if (cp_serial.payload_remaining == 0) {
@ -231,23 +222,23 @@ static void _websocket_send(_websocket *ws, const char *text, size_t len) {
payload_len = 127; payload_len = 127;
} }
frame_header[1] = payload_len; frame_header[1] = payload_len;
_send_raw(&ws->socket, (const uint8_t *)frame_header, 2); web_workflow_send_raw(&ws->socket, (const uint8_t *)frame_header, 2);
uint8_t extended_len[4]; uint8_t extended_len[4];
if (payload_len == 126) { if (payload_len == 126) {
extended_len[0] = (len >> 8) & 0xff; extended_len[0] = (len >> 8) & 0xff;
extended_len[1] = len & 0xff; extended_len[1] = len & 0xff;
_send_raw(&ws->socket, extended_len, 2); web_workflow_send_raw(&ws->socket, extended_len, 2);
} else if (payload_len == 127) { } else if (payload_len == 127) {
uint32_t zero = 0; uint32_t zero = 0;
// 64 bits where top four bytes are zero. // 64 bits where top four bytes are zero.
_send_raw(&ws->socket, (const uint8_t *)&zero, 4); web_workflow_send_raw(&ws->socket, (const uint8_t *)&zero, 4);
extended_len[0] = (len >> 24) & 0xff; extended_len[0] = (len >> 24) & 0xff;
extended_len[1] = (len >> 16) & 0xff; extended_len[1] = (len >> 16) & 0xff;
extended_len[2] = (len >> 8) & 0xff; extended_len[2] = (len >> 8) & 0xff;
extended_len[3] = len & 0xff; extended_len[3] = len & 0xff;
_send_raw(&ws->socket, extended_len, 4); web_workflow_send_raw(&ws->socket, extended_len, 4);
} }
_send_raw(&ws->socket, (const uint8_t *)text, len); web_workflow_send_raw(&ws->socket, (const uint8_t *)text, len);
} }
void websocket_write(const char *text, size_t len) { void websocket_write(const char *text, size_t len) {
@ -255,6 +246,9 @@ void websocket_write(const char *text, size_t len) {
} }
void websocket_background(void) { void websocket_background(void) {
if (!websocket_connected()) {
return;
}
uint8_t c; uint8_t c;
while (ringbuf_num_empty(&_incoming_ringbuf) > 0 && while (ringbuf_num_empty(&_incoming_ringbuf) > 0 &&
_read_next_payload_byte(&c)) { _read_next_payload_byte(&c)) {