M1 step 4b: IRC Service on the device; 8-bit frame buffer

- IrcService: networking on its own task, TLS with the built-in CA
  bundle (or trust-on-first-use pinning when self-signed is allowed),
  plain TCP when TLS is off; connects only while Wi-Fi is Connected,
  marks pauses for Monitoring, reconnects with backoff, pings a quiet
  server, writes Logs, raises Notifications for Mentions
- Session: forget /quit once disconnected (it was handled every loop);
  the server Buffer never counts as unread (MOTD showed as [4])
- Status Bar: unread count
- Frame buffer 16 -> 8-bit colour (M1 Q46): min free heap with IRC on
  TLS went from 51 KB to 79 KB
- Serial: irc start / say / dump

Verified on the device against irc.libera.chat:6697: certificate
checked, joined #roro9stack-test, sent a message, quit cleanly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EhqxQ49eCju4CzKYNjZzwT
This commit is contained in:
2026-10-02 15:10:03 +02:00
co-authored by Claude Opus 5.5
parent 311eb38723
commit 74a341418e
11 changed files with 357 additions and 4 deletions
@@ -316,6 +316,23 @@ void test_buffer_keeps_only_recent_lines() {
TEST_ASSERT_EQUAL(IrcSession::kLinesPerBuffer, f.session->buffer(f.buffer("#roro")).lines.size());
}
void test_quit_is_forgotten_once_disconnected() {
Fixture f;
f.registerNow();
f.session->input(0, "/quit", 0);
f.session->disconnected(0, "disconnected");
TEST_ASSERT_FALSE(f.session->quitRequested());
}
void test_server_buffer_never_counts_as_unread() {
Fixture f;
f.session->connected(0);
f.recv(":srv NOTICE * :*** Looking up your hostname...");
f.recv(":srv 372 roro :- Message of the day");
f.recv(":srv 001 roro :Welcome");
TEST_ASSERT_EQUAL(0, f.session->totalUnread());
}
int main() {
UNITY_BEGIN();
RUN_TEST(test_plain_registration_sends_nick_and_user);
@@ -341,5 +358,7 @@ int main() {
RUN_TEST(test_names_reply_only_shown_when_asked);
RUN_TEST(test_disconnect_marks_a_gap_and_reconnect_rejoins);
RUN_TEST(test_buffer_keeps_only_recent_lines);
RUN_TEST(test_quit_is_forgotten_once_disconnected);
RUN_TEST(test_server_buffer_never_counts_as_unread);
return UNITY_END();
}