<feed xmlns='http://www.w3.org/2005/Atom'>
<title>gbos.git/usr/ircd.c, branch master</title>
<subtitle>gbos - a tiny Unix-flavored OS for the Game Boy Color (kernel, shell, coreutils in C, RAM filesystem)</subtitle>
<id>https://git.sl0p.foo/gbos.git/atom/usr/ircd.c?h=master</id>
<link rel='self' href='https://git.sl0p.foo/gbos.git/atom/usr/ircd.c?h=master'/>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/gbos.git/'/>
<updated>2026-09-24T11:09:34Z</updated>
<entry>
<title>ircd: enforce unique nicknames (433), announce renames, fold case</title>
<updated>2026-09-24T11:09:34Z</updated>
<author>
<name>user</name>
<email>user@clank</email>
</author>
<published>2026-09-24T11:09:34Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/gbos.git/commit/?id=a73911fcbc5d7d6910d1edcdca38230a519361ca'/>
<id>urn:sha1:a73911fcbc5d7d6910d1edcdca38230a519361ca</id>
<content type='text'>
NICK overwrote the nick with whatever was asked for, so two clients could
both be "alice": /NAMES listed her twice and a private message only ever
reached whichever slot came first in the table.

- A nick already held by another client is refused with 433
  ERR_NICKNAMEINUSE and the client keeps the one it had. Unregistered
  clients simply stay unregistered until they pick a free one, which is what
  every client already expects.
- A NICK from a registered client is a rename: it is announced to the client
  and to its channel, so nobody's user list goes stale.
- IRC names fold case, so "Alice" is "alice" - for the uniqueness check, for
  PRIVMSG by nick, and for channels ("#GB" is "#gb"). One irceq() replaces
  the exact-match compare that was used for all three.

gbos's own irc(1) already retries 433 by appending '_', so two Game Boys with
the default nick now sort themselves out: verified with a GB running ircd, a
laptop client holding "sl0pboy", and a second GB arriving as "sl0pboy_" -
both in #gbos, messages crossing both ways.
</content>
</entry>
<entry>
<title>usr: ircd - an IRC server running on the Game Boy</title>
<updated>2026-09-22T19:54:13Z</updated>
<author>
<name>user</name>
<email>user@clank</email>
</author>
<published>2026-09-22T19:54:13Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/gbos.git/commit/?id=0a7ff09a910eaf5bcb0dc76d08dc5a6c9c239495'/>
<id>urn:sha1:0a7ff09a910eaf5bcb0dc76d08dc5a6c9c239495</id>
<content type='text'>
    /# ircd &amp;
    host$ irssi -c 10.0.0.2       /join #gbos
    other GB$ irc 10.0.0.2 gb2    /join #gbos

Implements the subset a real client needs to get in and talk: NICK, USER,
PING/PONG, JOIN, PART, PRIVMSG/NOTICE (to a channel or to a nick), NAMES and
QUIT, with the 001/004/375/372/376 numerics clients wait for on registration,
353/366 on join, and 421 for anything else. One channel per client keeps the
bookkeeping in fixed-size tables; this is a handheld with 8 KiB of task RAM.

MAXCL is 3, bounded by the kernel socket table (listener + client each take a
slot, the rest left for other programs). A fourth client is refused and the
daemon keeps serving - which is how the ~30s close() stall turned up.

Every event is logged to the LCD, so the Game Boy shows its own server
traffic: "+ alice", "alice joined", "&lt;alice&gt; hello".

Verified with real clients over the hub: two and three simultaneous hosts
registering, joining, channel relay (sender not echoed to itself), private
messages by nick, PING/PONG, unknown-command numerics, QUIT propagation, the
overflow refusal, and a second Game Boy running gbos's own irc(1) in the same
channel as a laptop client - messages crossing both ways between them.
</content>
</entry>
</feed>
