Skip to content

Commit 3247834

Browse files
committed
more tweaks
1 parent 0882cbf commit 3247834

File tree

2 files changed

+161
-0
lines changed

2 files changed

+161
-0
lines changed

ports/espressif/common-hal/socketpool/Socket.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,9 @@ int socketpool_socket_send(socketpool_socket_obj_t *self, const uint8_t *buf, ui
322322
}
323323

324324
if (sent < 0) {
325+
if (errno == ECONNRESET || errno == ENOTCONN) {
326+
self->connected = false;
327+
}
325328
return -errno;
326329
}
327330

supervisor/shared/web_workflow/web_workflow.c

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@
2626

2727
#include <string.h>
2828

29+
#include "extmod/vfs.h"
30+
#include "extmod/vfs_fat.h"
31+
32+
#include "py/mpstate.h"
33+
2934
#include "shared-bindings/wifi/Radio.h"
3035
#include "supervisor/shared/translate/translate.h"
3136
#include "supervisor/shared/web_workflow/web_workflow.h"
@@ -180,6 +185,8 @@ void supervisor_start_web_workflow(void) {
180185
// - JSON list of MDNS results
181186
// GET /cp/version.json
182187
// - JSON version info
188+
// GET /cp/serial.txt
189+
// - Most recent 1k of serial output.
183190
// GET /
184191
// - Super basic editor
185192
// GET /ws/circuitpython
@@ -188,6 +195,44 @@ void supervisor_start_web_workflow(void) {
188195
#endif
189196
}
190197

198+
static void _send_chunk(socketpool_socket_obj_t *socket, const char *chunk) {
199+
char encoded_len[sizeof(size_t) * 2 + 1];
200+
int len = snprintf(encoded_len, sizeof(encoded_len), "%X", strlen(chunk));
201+
int sent = socketpool_socket_send(socket, (const uint8_t *)encoded_len, len);
202+
if (sent < len) {
203+
ESP_LOGE(TAG, "short send %d %d", sent, len);
204+
}
205+
sent = socketpool_socket_send(socket, (const uint8_t *)"\r\n", 2);
206+
if (sent < 2) {
207+
ESP_LOGE(TAG, "short send %d %d", sent, 2);
208+
}
209+
sent = socketpool_socket_send(socket, (const uint8_t *)chunk, strlen(chunk));
210+
if (sent < (int)strlen(chunk)) {
211+
ESP_LOGE(TAG, "short send %d %d", sent, strlen(chunk));
212+
}
213+
sent = socketpool_socket_send(socket, (const uint8_t *)"\r\n", 2);
214+
if (sent < 2) {
215+
ESP_LOGE(TAG, "short send %d %d", sent, 2);
216+
}
217+
}
218+
219+
static void _send_str(socketpool_socket_obj_t *socket, const char *str) {
220+
int sent = socketpool_socket_send(socket, (const uint8_t *)str, strlen(str));
221+
if (sent < (int)strlen(str)) {
222+
ESP_LOGE(TAG, "short send %d %d", sent, strlen(str));
223+
}
224+
}
225+
226+
static bool _endswith(const char *str, const char *suffix) {
227+
if (str == NULL || suffix == NULL) {
228+
return false;
229+
}
230+
if (strlen(suffix) > strlen(str)) {
231+
return false;
232+
}
233+
return strcmp(str + (strlen(str) - strlen(suffix)), suffix) == 0;
234+
}
235+
191236
static void _process_request(socketpool_socket_obj_t *socket, _request *request) {
192237
bool more = true;
193238
bool error = false;
@@ -284,7 +329,9 @@ static void _process_request(socketpool_socket_obj_t *socket, _request *request)
284329
break;
285330
}
286331
case STATE_BODY:
332+
ESP_LOGW(TAG, "BODY %c", c);
287333
request->done = true;
334+
request->state = STATE_METHOD;
288335
more = false;
289336
break;
290337
}
@@ -312,6 +359,117 @@ static void _process_request(socketpool_socket_obj_t *socket, _request *request)
312359
const char *two_lines = "\r\n\r\n";
313360
sent += socketpool_socket_send(socket, (const uint8_t *)two_lines, strlen(two_lines));
314361
ESP_LOGW(TAG, "sent %d %d", sent, err);
362+
} else if (memcmp(request->path, "/fs/", 4) == 0) {
363+
ESP_LOGW(TAG, "filesystem %s %s", request->method, request->path + 3);
364+
const char *path = request->path + 3;
365+
size_t pathlen = strlen(path);
366+
FATFS *fs = &((fs_user_mount_t *)MP_STATE_VM(vfs_mount_table)->obj)->fatfs;
367+
// Trailing / is a directory.
368+
if (path[pathlen - 1] == '/') {
369+
if (strcmp(request->method, "GET") == 0) {
370+
FF_DIR dir;
371+
FRESULT res = f_opendir(fs, &dir, path);
372+
if (res != FR_OK) {
373+
// TODO: Send 404
374+
}
375+
const char *ok_response = "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n"
376+
"Content-Type: text/html\r\n\r\n";
377+
socketpool_socket_send(socket, (const uint8_t *)ok_response, strlen(ok_response));
378+
_send_chunk(socket, "<!DOCTYPE html><html><head><title>");
379+
_send_chunk(socket, path);
380+
_send_chunk(socket, "</title><meta charset=\"UTF-8\"></head><body><h1>");
381+
_send_chunk(socket, path);
382+
_send_chunk(socket, "</h1><pre>");
383+
if (strlen(path) > 1) {
384+
_send_chunk(socket, "🗀\t<a href=\"..\">..</a><br/>");
385+
}
386+
387+
FILINFO file_info;
388+
char *fn = file_info.fname;
389+
res = f_readdir(&dir, &file_info);
390+
while (res == FR_OK && fn[0] != 0) {
391+
// uint64_t truncated_time = timeutils_mktime(1980 + (file_info.fdate >> 9),
392+
// (file_info.fdate >> 5) & 0xf,
393+
// file_info.fdate & 0x1f,
394+
// file_info.ftime >> 11,
395+
// (file_info.ftime >> 5) & 0x1f,
396+
// (file_info.ftime & 0x1f) * 2) * 1000000000ULL;
397+
// entry->truncated_time = truncated_time;
398+
// if ((file_info.fattrib & AM_DIR) != 0) {
399+
// entry->flags = 1; // Directory
400+
// entry->file_size = 0;
401+
// } else {
402+
// entry->flags = 0;
403+
// entry->file_size = file_info.fsize;
404+
// }
405+
// _send_chunk(socket, "<li>");
406+
if ((file_info.fattrib & AM_DIR) != 0) {
407+
_send_chunk(socket, "🗀\t");
408+
} else if (_endswith(path, ".txt") || _endswith(path, ".py")) {
409+
_send_chunk(socket, "🖹\t");
410+
} else {
411+
_send_chunk(socket, "⭳\t");
412+
}
413+
_send_chunk(socket, "<a href=\"");
414+
_send_chunk(socket, request->path);
415+
_send_chunk(socket, file_info.fname);
416+
if ((file_info.fattrib & AM_DIR) != 0) {
417+
_send_chunk(socket, "/");
418+
}
419+
_send_chunk(socket, "\">");
420+
421+
_send_chunk(socket, file_info.fname);
422+
_send_chunk(socket, "</a><a>✏️</a><a>🗑️</a><br/>");
423+
res = f_readdir(&dir, &file_info);
424+
}
425+
_send_chunk(socket, "</pre>Upload:<input type=\"file\" multiple></body></html>");
426+
_send_chunk(socket, "");
427+
f_closedir(&dir);
428+
}
429+
430+
} else { // Dealing with a file.
431+
if (strcmp(request->method, "GET") == 0) {
432+
FIL active_file;
433+
FRESULT result = f_open(fs, &active_file, path, FA_READ);
434+
435+
if (result != FR_OK) {
436+
// TODO: 404
437+
}
438+
uint32_t total_length = f_size(&active_file);
439+
char encoded_len[10];
440+
snprintf(encoded_len, sizeof(encoded_len), "%d", total_length);
441+
442+
_send_str(socket, "HTTP/1.1 200 OK\r\nContent-Length: ");
443+
_send_str(socket, encoded_len);
444+
_send_str(socket, "\r\n");
445+
if (_endswith(path, ".txt") || _endswith(path, ".py")) {
446+
_send_str(socket, "Content-Type: text/plain\r\n");
447+
} else {
448+
_send_str(socket, "Content-Type: application/octet-stream\r\n");
449+
}
450+
_send_str(socket, "\r\n");
451+
452+
uint32_t total_read = 0;
453+
while (total_read < total_length) {
454+
uint8_t data_buffer[64];
455+
size_t quantity_read;
456+
f_read(&active_file, data_buffer, 64, &quantity_read);
457+
total_read += quantity_read;
458+
uint32_t send_offset = 0;
459+
while (send_offset < quantity_read) {
460+
int sent = socketpool_socket_send(socket, data_buffer + send_offset, quantity_read - send_offset);
461+
if (sent < 0) {
462+
ESP_LOGE(TAG, "file send error %d", sent);
463+
break;
464+
}
465+
send_offset += sent;
466+
}
467+
}
468+
ESP_LOGW(TAG, "file return done");
469+
470+
f_close(&active_file);
471+
}
472+
}
315473
} else {
316474
const char *ok_response = "HTTP/1.1 200 OK\r\nContent-Length: 11\r\nContent-Type: text/plain\r\n\r\nHello World";
317475
int sent = socketpool_socket_send(socket, (const uint8_t *)ok_response, strlen(ok_response));

0 commit comments

Comments
 (0)