Files
MeshCore/src/helpers/ethernet/SerialEthernetInterface.h
T
mikecarper 114a0d98c5 Keep RAK Companion Ethernet waits off the mesh loop
Run DHCP and renewal in a cooperative worker, bound socket commands, and retain SPI ownership until cleanup is safe. Preserve framing deadlines, response ownership and whole-frame replay, including pending-ACK queue pinning.

Budget the worker additively and retain all OTA names with an exact-checked Full-only compact index. Add full-driver, sanitizer, queue, shutdown, storage and memory regression coverage.
2026-10-16 02:23:03 -07:00

118 lines
3.8 KiB
C++

#pragma once
#include "../BaseSerialInterface.h"
#include "../UsbLogging.h"
#ifndef ETHERNET_TCP_PORT
#define ETHERNET_TCP_PORT 5000
#endif
// define ETHERNET_RAW_LINE=1 to use raw line-based CLI instead of framed packets
class SerialEthernetInterface : public BaseSerialInterface {
bool _isEnabled;
unsigned long _last_write;
uint8_t _state;
uint16_t _frame_len;
uint16_t _rx_len;
uint8_t _rx_buf[MAX_FRAME_SIZE];
uint32_t _rx_started = 0;
uint32_t _io_paused_at = 0;
bool _io_paused = false;
size_t send_offset = 0;
bool session_active = false;
bool queue_has_ip = false;
uint32_t queue_ip = 0;
void (*session_changed)(void*) = nullptr;
void* session_context = nullptr;
struct Frame {
uint8_t len;
uint8_t buf[MAX_FRAME_SIZE];
};
#define FRAME_QUEUE_SIZE 4
int send_queue_len;
Frame send_queue[FRAME_QUEUE_SIZE];
void clearBuffers() {
send_queue_len = 0;
queue_has_ip = false;
resetInput();
send_offset = 0;
}
void resetInput() {
_state = 0;
_frame_len = 0;
_rx_len = 0;
_rx_started = 0;
_io_paused_at = 0;
_io_paused = false;
}
void rejectInput();
bool updateIOPause(uint32_t now);
protected:
virtual void disconnectClient() = 0;
// A worker may own the hardware temporarily without ending the logical
// client session. Do not poll sockets or expire input while it does.
virtual bool isIOUnavailable() const { return false; }
// A backend can have transmitted bytes before returning their ACKed count.
// Keep that frame pinned even while send_offset still reads zero.
virtual bool hasInFlightFrame() const { return false; }
// Main-loop ownership handoffs must also service the timeout when another
// transport's locked response route keeps checkRecvFrame() from running.
// Workers must not call this: framing and session state remain main-only.
void serviceIOAvailability() { (void)updateIOPause((uint32_t)millis()); }
public:
SerialEthernetInterface() {
_isEnabled = false;
_last_write = 0;
send_queue_len = 0;
_state = 0;
_frame_len = 0;
_rx_len = 0;
}
bool begin();
// Drivers call this while isConnected() is false and BEFORE exposing the
// new socket. Same-IP live replacement retains the existing logical owner.
void onClientConnected(uint32_t remote_ip);
void onClientDisconnected();
void setSessionChangedCallback(void (*callback)(void*), void* context) {
session_changed = callback;
session_context = context;
}
// BaseSerialInterface methods
void enable() override;
void disable() override;
bool isEnabled() const override { return _isEnabled; }
bool isConnected() const override;
bool isReadBusy() const override;
bool isWriteBusy() const override;
bool hasPendingIO() const override;
size_t writeFrame(const uint8_t src[], size_t len) override;
size_t checkRecvFrame(uint8_t dest[]) override;
virtual int available() = 0;
virtual int read() = 0;
virtual size_t write(const uint8_t *buf, size_t size) = 0;
};
#if ETHERNET_DEBUG_LOGGING && ARDUINO
#include <Arduino.h>
#define ETHERNET_DEBUG_PRINT(F, ...) do { if (mesh::isUsbDebugLoggingEnabled()) { mesh::usbLoggingPort().printf("ETH: " F, ##__VA_ARGS__); } } while(0)
#define ETHERNET_DEBUG_PRINTLN(F, ...) do { if (mesh::isUsbDebugLoggingEnabled()) { mesh::usbLoggingPort().printf("ETH: " F "\n", ##__VA_ARGS__); } } while(0)
#define ETHERNET_DEBUG_PRINT_IP(name, ip) do { if (mesh::isUsbDebugLoggingEnabled()) { mesh::usbLoggingPort().printf("ETH: " name ": %u.%u.%u.%u" "\n", ip[0], ip[1], ip[2], ip[3]); } } while(0)
#else
#define ETHERNET_DEBUG_PRINT(...) {}
#define ETHERNET_DEBUG_PRINTLN(...) {}
#define ETHERNET_DEBUG_PRINT_IP(...) {}
#endif