core(M0): монорепо-каркас — CMake (posix+esp-idf), платслой, лог, мини-httpd
- CMakeLists в корне: ветвление ESP_PLATFORM (idf_component_register, lwip/esp_timer/esp_hw_support/pthread) / POSIX (статическая библиотека fgl-aircon, C++20, -fno-exceptions -fno-rtti, -Werror). - src/ayla/platform: сокеты/потоки/CSPRNG/время; posix (getrandom, poll, pthread_join) и esp-idf (lwip_select, esp_fill_random, pthread-слой IDF); tcp_shutdown/tcp_local_port/thread_join для управляемой остановки. - src/ayla: log (sink, без printf); мини-httpd/1.1 (keep-alive, Content-Length, лимиты заголовков/тела, ephemeral-порт, жизненный цикл с гарантией завершения потока: shutdown(active)→join→close). - tests/ayla: platform (join, loopback+shutdown) и httpd (404, keep-alive, обработчик/парсинг, oversize-400, stop при живом соединении, стрим заголовков). doctest через FetchContent. - scripts/ci.sh: сборка+ctest. ESP-IDF v5.5.5 esp32: смоук-сборка с ядром как компонентом — Project build complete. Ревью под-агентом: 3 круга, все блокеры (жизненный цикл httpd) закрыты, APPROVED.
This commit is contained in:
57
src/ayla/platform/platform.hpp
Normal file
57
src/ayla/platform/platform.hpp
Normal file
@@ -0,0 +1,57 @@
|
||||
// Платформенный слой: сокеты, таймеры, CSPRNG, потоки.
|
||||
// Одна реализация на платформу: platform/posix (Linux) и platform/esp-idf.
|
||||
// Все функции — блокирующие; коды ошибок через возвращаемое значение (-1),
|
||||
// без исключений. IP-адреса — uint32_t в host byte order.
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
namespace fgl::plat {
|
||||
|
||||
// ---- время ----
|
||||
// Монотонные миллисекунды с неопределённой точки отсчёта.
|
||||
uint64_t now_ms();
|
||||
|
||||
// ---- CSPRNG ----
|
||||
// Заполняет buf cryptographically-secure случайными байтами.
|
||||
bool random(uint8_t* buf, size_t len);
|
||||
|
||||
// ---- потоки ----
|
||||
// Идентификатор потока (непрозрачный). Валиден между thread_create и
|
||||
// завершением thread_join.
|
||||
using ThreadId = void*;
|
||||
// Создаёт поток с именем name (для отладки) и стеком stack_bytes (0 — по
|
||||
// умолчанию платформы; для ESP-IDF задавать явно, >= 4096).
|
||||
// out_id может быть nullptr (тогда присоединиться нельзя).
|
||||
bool thread_create(void (*fn)(void*), void* ctx, const char* name,
|
||||
uint32_t stack_bytes, ThreadId* out_id);
|
||||
// Блокирующе ждёт завершения потока. Гарантирует, что код потока больше не
|
||||
// исполняется (объекты потока можно освобождать после возврата).
|
||||
void thread_join(ThreadId id);
|
||||
// Мягкая блокирующая задержка текущего потока.
|
||||
void sleep_ms(uint32_t ms);
|
||||
|
||||
// ---- TCP (клиент и сервер) ----
|
||||
// Создаёт слушающий сокет; возвращает fd или -1. port==0 — любой свободный
|
||||
// (узнать выбранный: tcp_local_port).
|
||||
int tcp_listen(uint16_t port);
|
||||
// Локальный порт сокета (для ephemeral-слушателем).
|
||||
uint16_t tcp_local_port(int fd);
|
||||
// Принимает соединение (блокирующе); возвращает fd клиента или -1.
|
||||
// peer_ip (host byte order) / peer_port могут быть nullptr.
|
||||
int tcp_accept(int listen_fd, uint32_t* peer_ip, uint16_t* peer_port);
|
||||
// Подключается к host:port (host — DNS-имя или dotted-quad) с таймаутом.
|
||||
int tcp_connect(const char* host, uint16_t port, uint32_t timeout_ms);
|
||||
long tcp_send(int fd, const void* buf, size_t len); // >0 / -1
|
||||
// Блокирующее чтение; 0 — EOF, -1 — ошибка/таймаут.
|
||||
long tcp_recv(int fd, void* buf, size_t len);
|
||||
// Таймауты на последующие recv/send (0 — без таймаута).
|
||||
bool tcp_set_timeout(int fd, uint32_t rx_ms, uint32_t tx_ms);
|
||||
// Ожидание читаемости fd (для выходa из блокирующего accept). Таймаут в мс.
|
||||
bool tcp_poll_readable(int fd, uint32_t timeout_ms);
|
||||
// Прерывает блокированные recv/send на сокете (для остановки сервера).
|
||||
bool tcp_shutdown(int fd);
|
||||
void tcp_close(int fd);
|
||||
|
||||
} // namespace fgl::plat
|
||||
Reference in New Issue
Block a user