<feed xmlns='http://www.w3.org/2005/Atom'>
<title>~irc/github.com/solanum-ircd/solanum.git/include, branch amdj/modules</title>
<subtitle>https://github.com/solanum-ircd/solanum</subtitle>
<id>https://cgit.space/~irc/github.com/solanum-ircd/solanum.git/atom/include?h=amdj%2Fmodules</id>
<link rel='self' href='https://cgit.space/~irc/github.com/solanum-ircd/solanum.git/atom/include?h=amdj%2Fmodules'/>
<link rel='alternate' type='text/html' href='https://cgit.space/~irc/github.com/solanum-ircd/solanum.git/'/>
<updated>2026-03-11T08:57:36Z</updated>
<entry>
<title>Tidy up module loading code</title>
<updated>2026-03-11T08:57:36Z</updated>
<author>
<name>Aaron Jones</name>
</author>
<published>2026-03-11T03:57:11Z</published>
<link rel='alternate' type='text/html' href='https://cgit.space/~irc/github.com/solanum-ircd/solanum.git/commit/?id=f5dcfe9a95d236d2041f5bbbceeb54128d851299'/>
<id>urn:sha1:f5dcfe9a95d236d2041f5bbbceeb54128d851299</id>
<content type='text'>
The existing code had several defects:

- Core module file names were hardcoded, while autoloaded non-
  core module filenames were not.  Code that loaded core modules
  had a different but in some places duplicated structure to the
  code that loaded autoloaded modules.

- Module loading for autoloaded modules happened in dentry
  order, making it unpredictable from one server to the next, or
  even across instances of `make install` on the same server.

- Module loading for autoloaded modules did not verify that the
  dentry was a file before trying to load it.

- An IRCd start (or a conftest) only printed lines about loading
  modules mentioned in the configuration file.

- The configuration file was parsed before loading core and
  autoloaded modules, meaning any modules specified in the
  configuration file would be loaded first.

- Once a module was loaded, it was added to the head of the
  module list, making MODLIST show them in reverse loaded order
  (newest (re)loaded modules at the top of the list).

These are addressed as follows:

- We now scan the core and autoload module directories and use
  this to determine which modules to load.

- We now sort the dentries according to their filename before
  iterating them to load them, making module load order finally
  deterministic.

- We now test if a dentry is actually a file before trying to
  load it.

- We now print a message to the console (if running in
  foreground or conftest mode) when loading any module,
  including core and autoloaded modules.

- The message printed to the console now has the IRCd module
  directory prefix stripped from it if it matches.

- The configuration file is now parsed after loading core and
  autoload modules.

- The modules are added to the module list in the order that
  they are loaded. This now makes MODLIST show the order that
  modules were (re)loaded in.

Modifications to two modules are part of this effort:

- The autoload module `m_alias` relied upon the alias dict not
  being NULL when loaded, but this is only the case after the
  configuration file has been parsed.

  The module already had a "rehash" hook to destroy all existing
  aliases and create new ones, so we can just make the module do
  nothing on load (remove its modinit function) and change it to
  use the "conf_read_end" hook instead of the "rehash" hook, and
  it will still create aliases after the configuration file is
  subsequently parsed.

  With this modification, there are now no in-tree consumers of
  the "rehash" hook.

- The autoload module `m_services` iterated `service_list` upon
  loading it, which will now be empty (a no-op) since the module
  is loaded before configuration file is parsed.

  This module too handles the configuration file being parsed
  with a "conf_read_end" hook and takes the appropriate action,
  so we can just remove this code from its modinit function.

All other modules' modinit functions have been audited for
behaviour like this; there was nothing of note.
</content>
</entry>
<entry>
<title>Pass msgbuf to PART's privmsg_channel hook and propagate PART tags</title>
<updated>2026-01-22T00:42:01Z</updated>
<author>
<name>Ryan Schmidt</name>
</author>
<published>2026-01-21T22:08:55Z</published>
<link rel='alternate' type='text/html' href='https://cgit.space/~irc/github.com/solanum-ircd/solanum.git/commit/?id=6a1cd5ec8650ea4a8f47db64f8a4032cc4827c11'/>
<id>urn:sha1:6a1cd5ec8650ea4a8f47db64f8a4032cc4827c11</id>
<content type='text'>
The privmsg_channel hook gained a new msgbuf member which was
uninitialized in m_part. Properly pass the msgbuf to that parameter and
propagate any tags set by the hook to downstream servers.

This requires introducing sendto_server_tags(), and I refactored
sendto_server() to call the same helper internal method as
sendto_server_tags(). I took the opportunity to update the method to use
msgbuf instead of linebuf directly (meaning sendto_server() now calls
outbound_msgbuf).

Fixes #484
</content>
</entry>
<entry>
<title>Add doing_info_conf hook and cleanup unused hooks</title>
<updated>2026-01-21T17:09:43Z</updated>
<author>
<name>Ryan Schmidt</name>
</author>
<published>2026-01-13T00:59:37Z</published>
<link rel='alternate' type='text/html' href='https://cgit.space/~irc/github.com/solanum-ircd/solanum.git/commit/?id=1b44c4de4d955156bc010fa8223031a14ab69202'/>
<id>urn:sha1:1b44c4de4d955156bc010fa8223031a14ab69202</id>
<content type='text'>
doing_info_conf is called during INFO commands after all conf options
have been sent to opers. Modules can use this hook to expose any conf
options they define by sending relevant RPL_INFO replies to the oper.
This addition removes the final barrier to defining new ircd.conf
options inside of extension modules rather than requiring core changes
for extension configuration.

Additionally, some cleanup has been performed for hook definitions that
are not called anywhere inside of solanum. Three hooks were declared in
hook.h as extern int but were not defined or referenced in any other
file: iosend_id, iorecv_id, and iorecvctrl_id. The doing_admin,
doing_info, doing_motd, and doing_trace "spy" hooks were defined in the
module headers for those modules, however the modules never actually
invoked those hooks. All of the lingering declarations for these hooks
have now been removed as they weren't doing anything anyway.
</content>
</entry>
<entry>
<title>Fix msgid tags with echo-message</title>
<updated>2026-01-21T17:09:09Z</updated>
<author>
<name>Ryan Schmidt</name>
</author>
<published>2025-12-01T16:54:56Z</published>
<link rel='alternate' type='text/html' href='https://cgit.space/~irc/github.com/solanum-ircd/solanum.git/commit/?id=0aac79db9d8747facb0fd59b673a437fa6f5696c'/>
<id>urn:sha1:0aac79db9d8747facb0fd59b673a437fa6f5696c</id>
<content type='text'>
msgid generation has been moved to the privmsg_user and privmsg_channel
hooks, which are called on every normal PRIVMSG/NOTICE/TAGMSG. They are
not called when messaging user@server, opers@server, or mass-messages
and as such none of those things will have msgid attached. This seems
fine as user@server is rejected by solanum and exists solely for
messaging pseudoservers, opers@server is turned into a snote, and
mass-messages are oper-only and thus unlikely to need anything that keys
off msgid in the future.

Moving this solves the interaction with msgid and echo-message. Now, we
ensure that an echoed message always has a msgid, and that msgid is
always the same as the msgid shown to other clients.

This requires expanding the hook_data structures for those two hooks.
While a core restart is not needed, attempting to reload tag_message_id
before reloading m_message may cause crashes. When updating your
servers, please reload m_message first.
</content>
</entry>
<entry>
<title>Batch updates</title>
<updated>2026-01-21T16:10:44Z</updated>
<author>
<name>Ryan Schmidt</name>
</author>
<published>2026-01-13T17:12:32Z</published>
<link rel='alternate' type='text/html' href='https://cgit.space/~irc/github.com/solanum-ircd/solanum.git/commit/?id=8162cbe9d4f350da87a6eff02d06c804889b0d5f'/>
<id>urn:sha1:8162cbe9d4f350da87a6eff02d06c804889b0d5f</id>
<content type='text'>
The extension example_module was extended to introduce a new
client-initiated batch type named test. This is primarily done to ease
testing of the client-initiated portions of m_batch, but also serves as
a useful sketch for how a module can register its own client-initiated
batch types.

The definition of struct BatchHandler was slightly modified to use a
callback function to determine if nesting is allowed. The callback can
additionally set a custom error message if desired when returning false.

The len and messages list in struct Batch no longer include the start
message, so a len of 0 indicates an empty batch. Because the start
message is still allocated and saved off, adjust anything that impacts a
client's pending_batch_lines by 1 to account for the implicit additional
message.

Empty batches now trigger the relevant batch handler. If a handler wants
to no-op on empty batches, it can do so but this allows additional
flexibility for handlers to still do something upon receiving empty
client-initiated batches.
</content>
</entry>
<entry>
<title>Add batch support</title>
<updated>2026-01-21T16:10:44Z</updated>
<author>
<name>Ryan Schmidt</name>
</author>
<published>2025-10-25T00:59:22Z</published>
<link rel='alternate' type='text/html' href='https://cgit.space/~irc/github.com/solanum-ircd/solanum.git/commit/?id=4cc9be1ddf1e14fc76bf433e23a3d528424b60ca'/>
<id>urn:sha1:4cc9be1ddf1e14fc76bf433e23a3d528424b60ca</id>
<content type='text'>
- Add "batch" client capability
- Support sending netsplit/netjoin batches
- Support receiving BATCH from clients and remote servers
- Support for modules to define supported batch types for incoming
  batches
- Add "message_handler" hook to override the handler for a particular
  incoming message
- Add technical and user-facing documentation for batches
- Add some more sendto_* overloads that support tags which were missing
  from the initial message-tags implementation but turned out to be
  needed
</content>
</entry>
<entry>
<title>Revert "msgbuf: duplicate the string during partial parse and constify line" (#463)</title>
<updated>2025-10-11T09:58:50Z</updated>
<author>
<name>Val Lorentz</name>
</author>
<published>2025-10-11T09:58:50Z</published>
<link rel='alternate' type='text/html' href='https://cgit.space/~irc/github.com/solanum-ircd/solanum.git/commit/?id=97b0c37744c4bfab3fae77a796fe3f4aa9dc07ba'/>
<id>urn:sha1:97b0c37744c4bfab3fae77a796fe3f4aa9dc07ba</id>
<content type='text'>
This reverts commit 5b253939da8f6b0a44ce6787ed12e26450ac6a63 to fix a
memory leak:

```
==825564== 818 bytes in 4 blocks are definitely lost in loss record 616 of 648
==825564==    at 0x4844818: malloc (vg_replace_malloc.c:446)
==825564==    by 0x49CD7A9: strdup (strdup.c:42)
==825564==    by 0x4888A2E: msgbuf_partial_parse (msgbuf.c:143)
==825564==    by 0x489DA84: build_msgbuf (send.c:276)
==825564==    by 0x489DA84: sendto_one_numeric (send.c:431)
==825564==    by 0x48A3CD7: show_isupport (supported.c:181)
==825564==    by 0x489A9F2: user_welcome (s_user.c:1433)
==825564==    by 0x489B114: register_local_user (s_user.c:718)
==825564==    by 0x488FC08: handle_command (parse.c:310)
==825564==    by 0x488FC08: parse (parse.c:224)
==825564==    by 0x488EEF8: parse_client_queued.part.0 (packet.c:67)
==825564==    by 0x488F084: parse_client_queued (packet.c:49)
==825564==    by 0x488F084: read_packet (packet.c:306)
==825564==    by 0x4B3C47B: rb_select_epoll (epoll.c:199)
==825564==    by 0x4B3716F: rb_select (commio.c:2038)
==825564==
[...]
==825564==
==825564== 3,012 bytes in 15 blocks are definitely lost in loss record 627 of 648
==825564==    at 0x4844818: malloc (vg_replace_malloc.c:446)
==825564==    by 0x49CD7A9: strdup (strdup.c:42)
==825564==    by 0x4888A2E: msgbuf_partial_parse (msgbuf.c:143)
==825564==    by 0x489D3CE: build_msgbuf (send.c:276)
==825564==    by 0x489D3CE: sendto_realops_snomask (send.c:1431)
==825564==    by 0x4887C0D: load_a_module (modules.c:712)
==825564==    by 0x488801D: load_core_modules (modules.c:257)
==825564==    by 0x488124A: solanum_main (ircd.c:664)
==825564==    by 0x494DCA7: (below main) (libc_start_call_main.h:58)
```</content>
</entry>
<entry>
<title>Fix typing module decl and send 417 in more cases</title>
<updated>2025-10-10T19:09:40Z</updated>
<author>
<name>Ryan Schmidt</name>
</author>
<published>2025-08-31T05:44:43Z</published>
<link rel='alternate' type='text/html' href='https://cgit.space/~irc/github.com/solanum-ircd/solanum.git/commit/?id=49e739e9318d8a6b96946e5125f9cc2c48b2b787'/>
<id>urn:sha1:49e739e9318d8a6b96946e5125f9cc2c48b2b787</id>
<content type='text'>
The typing module declaration had a copy/paste error that has now been
corrected, and we now send 417 ERR_INPUTTOOLONG in cases where parsing
the line into a MsgBuf fails because it overflowed the 8191+512 byte
buffer while processing tags or the message origin.
</content>
</entry>
<entry>
<title>Address review comments</title>
<updated>2025-10-10T19:09:40Z</updated>
<author>
<name>Ryan Schmidt</name>
</author>
<published>2025-08-19T18:56:29Z</published>
<link rel='alternate' type='text/html' href='https://cgit.space/~irc/github.com/solanum-ircd/solanum.git/commit/?id=8d22050d753c56d37013c5af3276054a2503413b'/>
<id>urn:sha1:8d22050d753c56d37013c5af3276054a2503413b</id>
<content type='text'>
Correctly sent ERR_INPUTTOOLONG if the incoming tags portion from a
client is too long. The previous calculation did not take into account
the fact we added null terminators after every tag key and value. Since
msgbuf_parse is used for both server and client input, we expose the
length of the original tags portion of the buffer in the MsgBuf struct
rather than abort msgbuf_parse if it is too long, since the only time
truncation is explicitly not allowed is for incoming tags from client
messages.

Additionally, make join_sep functional in format_client_tags().
</content>
</entry>
<entry>
<title>m_message: Implement message-tags and TAGMSG</title>
<updated>2025-10-10T19:09:40Z</updated>
<author>
<name>Ryan Schmidt</name>
</author>
<published>2025-08-18T22:20:58Z</published>
<link rel='alternate' type='text/html' href='https://cgit.space/~irc/github.com/solanum-ircd/solanum.git/commit/?id=17f5ad5427a99c473ef21850f466ac5840d29220'/>
<id>urn:sha1:17f5ad5427a99c473ef21850f466ac5840d29220</id>
<content type='text'>
The CAP_STAG server capability and the CAP_TAGS server capability
introduced by m_message are redundant, so get rid of CAP_TAGS and update
the comment for CAP_STAG to indicate what it is for. Additionally,
define the message-tags client capability in m_message.

A lot of new sendto_* functions were introduced that take an explicit
array of tags to attach to the outgoing message. New functions were
preferred over updating existing functions in order to maintain
compatibility with non-tags-aware code in both the API and ABI layers.
The updated definitions of these functions will be provided in a
subsequent patch in this PR; however I felt the declarations would be
useful in reviewing the changes to m_message.

A TAGMSG with zero client-only tags is rejected with 412
ERR_NOTEXTTOSEND. While the precise message of that numeric is a little
bit misleading, it was the closest existing thing and matches what we
send off when a PRIVMSG contains no text. The message-tags spec does not
specify any particular error when a TAGMSG contains no tags (indeed it
has a non-normative example where such a TAGMSG is propgated). The spec
also allows for server-side moderation of tags, however, and not
propagating completely useless messages is a valid use of those
moderation powers.

General cleanup of the file was performed as part of this patch.
</content>
</entry>
</feed>
