| Commit message (Expand) | Author | Age | Files | Lines |
| * | Call the channel_lowerts hook on SJOIN too•••Previously this hook was called only when a remote join outside of a
netjoin burst to an existing channel happens, which is a fairly odd set
of criteria. By making it run for SJOIN too, it now covers every case
where a channel's TS is lowered, making the hook more reliable for use.
| Ryan Schmidt | 13 days | 1 | -0/+6 |
| * | Expand doing_whois/doing_whois_global hook data•••Use hook_data_client_approval instead of hook_data_client so that we can
pass whether operspy WHOIS is being performed as part of the hook data.
hook_data_client_approval is backwards compatible by having the same
beginning layout as hook_data_client, so modules compiled against the
old hook data should have no issues.
Unlike most hooks where an approval struct is passed, the approved field
is meant to be read-only here. The approval struct was simply used out
of convenience vs having to define a custom struct with identical layout
for the case of WHOIS.
| Ryan Schmidt | 13 days | 1 | -1/+2 |
| * | Expand monitor•••- new is_monitoring function that modules can use to determine if a
particular client is monitoring a particular nickname
- new hook that is fired when a user adds a nick to their monitor list
| Ryan Schmidt | 13 days | 1 | -1/+16 |
| * | Clean up outgoing_response_info on parse end•••Failing to set outgoing_response_info to NULL after finishing parsing a
command means any future commands that do *not* have a label tag will
incorrectly inherit that labeled response context. This can cause, among
other things, crashes when sending an unlabeled remote command after a
labeled remote command.
Also add a regression test for this behaviour.
| Ryan Schmidt | 2026-07-04 | 1 | -21/+23 |
| * | Fix narrowing conversion for caps in m_message | Ryan Schmidt | 2026-07-03 | 1 | -7/+7 |
| * | Fix memory leak in /LIST processing•••The error path was not freeing memory allocated during earlier
loop invocations.
| Aaron Jones | 2026-06-23 | 1 | -0/+2 |
| * | Update labeled-response code•••The previous API was too error-prone, as evidenced by the large amount
of crash bugs discovered with it. New functions were added to response.h
to more easily manage labeled-response state, and some state tracking
was moved into core (such as CLICAP_RECEIVE_LABEL, which must only ever
be on one client at a time). Because this tracking is now in core,
cap_labeled_response needs to be a core module as having that bit
unloaded will cause issues. m_batch was also moved into being a core
module as more and more core things have depended on batch support
existing (and more will depend on it in the future).
m_list no longer re-uses remote response batches for SAFELIST, instead
making use of new APIs to suspend a labeled-response batch and more
easily resume it.
Batch resumption was made more focused as well, to ensure that we don't
accidentally lose batches due to setting outgoing_response_info to NULL.
The free_response_batch takes a resumption pointer to avoid cases where
we could introduce use-after-free by combining
free+resume_response_batch.
struct ResponseInfo now takes strduped pointers instead of directly
holding the buffers, and some fields were merged into a flags field or
omitted entirely due to new suspension/resumption support. This will
have a minor positive impact on memory usage as we no longer need to
allocate buffers for maximum-sized strings for every labeled-response.
Finally, shorten the dictionary label for pending responses. It was
overflowing its spot in STATS B, making the data after it misaligned.
| Ryan Schmidt | 2026-06-04 | 7 | -204/+93 |
| * | Fix null dereference in LIST•••Introduced in 66a8049e700c5c55ddd32cf211c1ceef06992ff3
| Valentin Lorentz | 2026-05-24 | 1 | -1/+2 |
| * | Prevent users from running CAPAB pre-registration•••We now disconnect the client if they attempt to run CAPAB before running
PASS (introducing themselves as a TS6 server with an SID) or if they've
already sent USER/NICK info. USER/NICK already has the other half of the
requisite checks by disconnecting the user if they have an SID. As such,
the logic flow of requiring an SID before CAPAB means users can never
have server caps set on them.
This prevents various issues such as a client sending CAPAB STAG
receiving all message tags, including those designed to be s2s-only.
| Ryan Schmidt | 2026-05-23 | 1 | -1/+10 |
| * | Fix missing send_multiline_reset in clicap_generate•••This commit adds a missing send_multiline_reset call
before a return in clicap_generate in m_cap.c.
Without this, if running CAP LIST, the send_multiline_init call
just above it would not be cleaned up.
It assumes that send_multiline_reset is always safe to call,
which is true at the time of this commit.
| daemoness | 2026-05-23 | 1 | -1/+4 |
| * | Don't auto-expire SAFELIST batches•••Avoids use-after-free if the client takes more than 10 seconds to fully
receive the LIST output.
| Ryan Schmidt | 2026-05-21 | 1 | -1/+2 |
| * | Fix timing of free_response_batch on cliexit•••free_response_batch will no-op if MyConnect(client_p) is false. This
would always be the case with the former timing, as it was called after
exit_local_client which clears the MyConnect flag. Do it before instead
so we can properly clean up the tracking vars (namely, the
pending_responses dict, which otherwise had a use after free when firing
the event to clean up a response for an exited client).
While we're at it, change the previous fix in cap_labeled_response from
IsIOError to IsAnyDead to catch more cases where a client cannot
receive data. This has not caused any crashes, but the expanded check
includes IOError so is safe to use, and all of the statuses checked by
IsAnyDead preclude the ability to send data to the client.
| Ryan Schmidt | 2026-05-21 | 1 | -1/+1 |
| * | Adjust order of operations•••Compare pointer values and set to NULL before freeing the pointer. Also
set outgoing_response_info to NULL as well (this is pointless at the
moment since it will always be followed by a call that resets it to the
orig_response_info pointer, but future-proofs it in the event that
future code doesn't do that)
| Ryan Schmidt | 2026-05-20 | 1 | -2/+4 |
| * | Fix use after free in LIST with labeled-response•••In the event that LIST output is small enough to complete without
invoking SAFELIST code (i.e. the buffer doesn't exceed half of the
client's SendQ), the stashed outgoing_response_info in struct ListClient
is the same pointer as the outgoing_response_info for the LIST command.
When we finish sending the LIST, we free the stashed struct ListClient's
outgoing_response_info and then restore the outgoing_response_info from
the LIST command, and attempt to do things with it. However, that memory
has already been freed. Detect the case when the pointers are the same
value and properly wipe them both so we no longer attempt to read from
it.
| Ryan Schmidt | 2026-05-20 | 1 | -7/+10 |
| * | Fix crash on labeled QUIT•••Trying to send things to disconnected clients turns out to be a bad
idea. This change effectively ignores any labels on QUIT.
| Ryan Schmidt | 2026-05-18 | 1 | -13/+17 |
| * | Remove some legacy cruft•••- The hurt extension doesn't work well and is now supplanted by
m_quarantine
- ip_cloaking_old has been broken (causes segfaults) for years now,
remove it
- ip_cloaking_3.0 has hardcoded keys that require .c file edits to be
secure. Anyone using it will probably maintain their fork of this file
anyway, but it's not good for new people to use. Remove that too
- Remove LOCOPS and umode +l entirely; they serve no useful purpose on
unified networks. This also removes the no_locops extension since it
is now useless
| Ryan Schmidt | 2026-05-13 | 1 | -2/+0 |
| * | Fix s2s labeled-response batches•••Previously, batches would end prematurely if they traveled through an
intermediate server before reaching their destination because the
intermediate server would send ENCAP ACK multiple times, causing the
pending server count to go down way too fast. Solve this by introducing
two things:
- Check that the direction of the incoming command matches the direction
we'd be sending the ACK to (avoids sending additional ACKs for replies
from remote servers that we pass along)
- Add a mask parameter to the tracking metadata for remote responses and
only send an ACK if we match the mask. this way things like remote
WHOIS don't generate ACKs from intermediate servers
Additionally, fix our manipulation of outgoing_response_info in m_list
to properly set CLICAP_RECEIVE_LABEL during SAFELIST buffering. The
logic here largely matches that in m_batch.
| Ryan Schmidt | 2026-05-13 | 8 | -26/+101 |
| * | Add labeled-response support to m_message•••While base cases already worked fine with just cap_labeled_response, a
handful of special cases need batched responses, such as multi-target
messages. The module also needed updating to work properly with
echo-message, as the spec says that the echo is the one that needs the
label if the client messages themselves, rather than the main message,
and the echo is always sent last. This logic is also applied to mass
messages that include the oper sending it.
The handle_special method was broken up and made less special, treating
the various cases as additional target types rather than processing them
right away. The opers@server hack was also removed entirely since it is
obviated by other means of messaging opers on a server such as LOCOPS in
the event such is even necessary. Or, you know, just use the staff
channel.
| Ryan Schmidt | 2026-05-13 | 1 | -171/+245 |
| * | Add labeled-response support to LIST•••With SAFELIST, the labeled-response batch does not necessarily finish
right away. As such, save off the context for the client's LIST command
and restore it each time we send them more data.
| Ryan Schmidt | 2026-05-13 | 1 | -0/+21 |
| * | Add labeled-response support to BATCH•••This concerns client-initiated batches only. Save the labeled-response
context as part of the Batch so that we can restore that context later
once the batch is complete. The label is added to the batch start
message, but we only process batches once we receive the batch complete
message (which lacks a label tag), and we could potentially be finishing
a batch due to it timing out if the client never sends a batch complete
message. By restoring context, we ensure that hooks such as
outbound_msgbuf are operating with all of the state they would expect to
have in order to properly attach tags to outgoing messages.
| Ryan Schmidt | 2026-05-13 | 1 | -0/+55 |
| * | Batch labeled-response multiline responses•••Add calls to generate local or remote labeled-response batches to all
modules which generate multiple lines of response. In general, this is
only done once we've confirmed we will be sending multiple lines, to
avoid spurious batches which only contain single lines inside of the
batch, however some cases will always generate a batch regardless due to
ease of implementation.
This patch covers all of the "easy" cases; future patches will cover the
complicated ones: m_batch, m_message, and m_list.
| Ryan Schmidt | 2026-05-13 | 32 | -37/+169 |
| * | Add cap_labeled_response•••This module provides the labeled-response capability as well as an
internal non-propagated ?receive_label capability that is dynamically
added/removed from the client which should receive a labeled-response.
By using a second dummy capability, I don't need to rewrite our msgbuf
caching layer which is keyed entirely off the capmasks of the client in
order to vary who receives the label/batch tags.
It also introduces a s2s-only message tag solanum.chat/response which is
used to inform remote servers that their replies should be labelled.
Remote responses are always batched, and the batch is generated by the
local server to ensure that 100% of incoming labelled commands receive a
labeled-response. The solanum.chat/response tag is passed back in
replies so the local server can add the appropriate batch tag to the
response passed to the client. Remote servers will also send an ENCAP
ACK command to indicate they are done responding in the event that they
received an incoming s2s command with the solanum.chat/response tag.
The module keeps track of outgoing responses and if, by the end of
command processing (parse_end hook), it hasn't attached a label to
anything it will send a labelled ACK to the client. If it has begun a
labeled-response batch, it will also automatically close that batch,
reducing the likelihood of programming errors forgetting to close
batches.
| Ryan Schmidt | 2026-05-13 | 3 | -0/+232 |
| * | Expand `STATS t` to include batch info•••Two new lines were added at the end of STATS t output to list the number
of pending client-initiated batches (and pending lines in those batches)
as well as the number of pending remote labeled-response batches.
| Ryan Schmidt | 2026-05-13 | 1 | -0/+8 |
| * | Change outbound_msgbuf to use its own data struct•••The new struct is ABI-compatible with hook_data for the first 3 fields
so that modules compiled using the old hook definition will continue to
work. The new data enables much richer evaluation during outbound_msgbuf
hook functions by exposing the target or channel the message is being
sent to (if known) as well as whether the message source is a recipient
of the message being sent.
| Ryan Schmidt | 2026-05-13 | 2 | -7/+7 |
| * | Add m_quarantine•••This extension module provides a new usermode (+q) and two commands that
allow opers to set/unset that mode. The mode can be set either via
ircd.conf (general::default_umodes or auth::umodes) or via the
QUARANTINE command. When using the command, a reason is required which
will be broadcast to all other opers via the snote.
The quarantine will be automatically removed if the target opers up or
logs into a services account, and opers and logged in users cannot be
quarantined. The UNQUARNTINE command may additionally be used to remove
the quarantine status from a user. Users cannot otherwise set or remove
this usermode from themselves.
The QUARANTINE and UNQUARANTINE commands require a new priv
oper:quarantine.
To support this, a new account_change hook was added to m_services and
m_signon. This hook is fired whenever a user's services account changes
(via logging in or logging out) from the SVSLOGIN, SIGNON, LOGIN, or SU
services commands. It is **not** fired for SVSLOGIN on unknown
(pre-registration) users.
Documentation was updated for the new usermode, hook, and commands.
Usermode help was alphabetized for consistency, a missing entry for
helpops was added, and cloaking was moved to +x (since all modern
cloaking modules use that mode instead) since I was touching the file
anyway.
| Ryan Schmidt | 2026-04-29 | 2 | -2/+28 |
| * | Unify the preprocessor macro for OpenSSL support•••Commit 9a1ee1b64ed660164197 introduced support for building IRCd
with Meson. It defines the "HAVE_OPENSSL" preprocessor macro
for both IRCd and librb. While librb does use that macro, IRCd
unfortunately uses only the "HAVE_LIBCRYPTO" macro instead, set
implicitly by AC_CHECK_LIB from autotools.
Make the autotools build system define HAVE_OPENSSL (to unify
IRCd with librb) and change IRCd to use that.
| Aaron Jones | 2026-03-22 | 1 | -3/+3 |
| * | Tidy up module loading code•••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.
| Aaron Jones | 2026-03-22 | 2 | -11/+2 |
| * | Add no-implicit-names client capability•••This has been recently ratified and suppresses NAMES output during
channel joins when enabled, providing for a decent chunk of bandwidth
savings.
| Ryan Schmidt | 2026-03-19 | 1 | -1/+2 |
| * | build: add Meson buildsystem | Valentin Lorentz | 2026-03-17 | 1 | -0/+114 |
| * | modules: drop unnecessary link flag | Valentin Lorentz | 2026-03-17 | 1 | -1/+0 |
| * | Remove channel::kick_on_split_riding•••This feature had numerous pitfalls (such as not checking +beI) and
services does it better than we can. Remove it and alert opers that the
feature no longer exists if they had it configured.
| Ryan Schmidt | 2026-03-17 | 2 | -46/+0 |
| * | Adjust unsigned int -> uint64_t for all caps•••The previous commit addressed the issue with (most) function signatures,
but forgot to update the caps themselves to be 64-bit. This fixes that,
and finishes the remaining overlooked function signatures.
| Ryan Schmidt | 2026-03-17 | 6 | -6/+6 |
| * | Apply review suggestions•••Also made full use of the Set/Clear macros across the codebase so
there's fewer places to touch in the future if changes are needed.
| Ryan Schmidt | 2026-03-17 | 3 | -9/+9 |
| * | Separate client vs server caps•••Instead of overloading the same field in a LocalUser, have separate
fields for client caps vs server caps. While only one of these will ever
be nonzero, it reduces error by making it explicit which set of caps is
being checked. IsCapable and friends have been split as well, to
IsClientCapable and IsServerCapable. Finally, both fields have been
updated to uint64_t (server caps were approaching the current limit) and
all APIs that reference caps updated to uint64_t as well (no more
signed/unsigned mismatches).
| Ryan Schmidt | 2026-03-17 | 9 | -34/+37 |
| * | Make TAGMSG behave like NOTICE for errors•••We explicitly do not send error numerics to clients for NOTICE in most
cases, instead silently discarding the command. Give this treatment to
TAGMSG across the board as well. Previously, this was the case for
TAGMSG without tags but was not applied for TAGMSG that had tags but
otherwise had issues (e.g. +m channel and the user is not +ov). This
prevents spamming users whose clients send automatic TAGMSG with errors
they can do nothing about.
| Ryan Schmidt | 2026-02-12 | 1 | -17/+17 |
| * | Add doing_version_confopts hook•••This hook allows modification of the confopts portion of a VERSION
response (i.e. the set of flags representing how the ircd was
configured).
Extension modules can use this hook to display additional confopts
without needing to edit m_version or add things to core in order to
share state with m_version.
| Ryan Schmidt | 2026-01-22 | 1 | -16/+37 |
| * | Pass msgbuf to PART's privmsg_channel hook and propagate PART tags•••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
| Ryan Schmidt | 2026-01-22 | 1 | -19/+19 |
| * | Add doing_info_conf hook and cleanup unused hooks•••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.
| Ryan Schmidt | 2026-01-21 | 4 | -18/+7 |
| * | Fix msgid tags with echo-message•••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.
| Ryan Schmidt | 2026-01-21 | 1 | -51/+56 |
| * | Batch updates•••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.
| Ryan Schmidt | 2026-01-21 | 1 | -26/+20 |
| * | Avoid making spurious netjoin batches•••If a server being netjoined to us is introducing additional downstream
servers from it, those servers won't themselves be sending us bursts. As
such, we can safely suppress sending a BATCH to clients for those
additional servers.
| Ryan Schmidt | 2026-01-21 | 1 | -0/+6 |
| * | Include AWAY and status MODEs in netjoin batches•••AWAY is burst to away-notify clients and status MODEs (+o and +v) are
burst to all clients on the channel. Excluding these from the batch
means that clients may opt to process these before the batch completes,
then get confused because they have no records of those nicknames
existing or being members of the channel. Including both in the netjoin
batch solves these concerns, although the netjoin batch spec is silent
on whether we're allowed to put non-JOIN commands in that batch.
| Ryan Schmidt | 2026-01-21 | 1 | -18/+16 |
| * | Add batch support•••- 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
| Ryan Schmidt | 2026-01-21 | 3 | -2/+508 |
| * | Stop sending ERR_NOTEXTTOSEND on empty TAGMSG (#476)•••Per the message-tags spec, clients are allowed to send tags blocked by
CLIENTTAGDENY, and some clients make use of this allowance to send tags
that are otherwise stripped out (e.g. +typing if that module is not
loaded). If a TAGMSG did not have any client tags after processing, we
previously returned ERR_NOTEXTTOSEND (412) however this results in a
fair amount of spam in the server buffer of such clients. Make the
command silently fail instead.
An open question remains on how this interacts with echo-message, as the
spec is not well-written to cover what happens during failure/error
cases. A strict reading of the spec would require an echo-message on
every received PRIVMSG/NOTICE/TAGMSG, including cases where we are
already sending an error numeric. This does not seem intended, and would
complicate labeled-response by requiring a batch in error cases.
A looser reading of the spec seems to permit not sending any
echo-message in the case that messages are filtered out (as the portion
of the spec allowing "fake messages" is a MAY). Since we currently do
not send any echo-message for empty NOTICE (and do not send any numerics
either), apply the same treatment for empty TAGMSG: the server silently
drops the command and does not echo anything back to the client. | Ryan Schmidt | 2026-01-11 | 1 | -3/+0 |
| * | Remove duplicate definition message-tags CAP•••It is defined in s_serv.c so it doesn't need to additionally be defined
in modules/core/m_message.c. Support for receiving client tags is baked
into parse.c and other core files, so the definition in s_serv.c is the
right place for it.
| Ryan Schmidt | 2025-10-10 | 1 | -1/+0 |
| * | m_message: Implement message-tags and TAGMSG•••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.
| Ryan Schmidt | 2025-10-10 | 1 | -83/+190 |
| * | Refactor message_tag hook•••The original hook was defined in the (now-removed) cap_message_tag
module. This new hook lives deeper down in parse.c so that it fires on
all incoming tags for all incoming messages. The hook was renamed from
client_tag_accept to message_tag to denote that it is used for all tags,
including tags coming from server connections, and not just tags with a
client-only prefix.
The hook data contains two non-const fields for the capmask and approval
status. Since incoming tags lack a capmask entirely, this allows hook
functions that wish to keep the tag around to specify the capmask used
for propagating the tag to other clients and servers. The approval
status can take one of three forms: approve the tag, drop the tag from
the message (but still process other tags and run the command handler),
or drop the entire message (not processing any other tags and not
running any command handlers). It is expected when a hook function drops
the message that they'll send appropriate feedback to the client,
however the nature of that feedback will likely vary by hook function so
no default message is given to a client if their message is dropped.
The incoming_message global defined previously with cap_server_time now
holds the MsgBuf with the updated/sanitized list of tags rather than the
raw values specified by the client. Additionally, cap_server_time makes
use of this new hook to propagate the time tag into function callbacks
that support tag propagation. The implicit propagation still exists
since the majority of function callbacks do not support explicit tag
propagation, and that fact will not change in the course of this
patchset.
| Ryan Schmidt | 2025-10-10 | 1 | -1/+17 |
| * | Remove cap_message_tags and reorganize Makefile•••Message tags support is being rolled into core rather than as a loadable
module because of the sweeping changes it requires, including at the s2s
protocol level for sending since the spec increased the size of the tags
portion from 512 bytes to 8191 bytes.
Also alphabetized the extensions Makefile to make subsequent patches
that add new tags cleaner.
| Ryan Schmidt | 2025-10-10 | 2 | -85/+0 |
| * | message-tags: facility to manipulate client-tags•••It provides for hook facilities to client-only tags:
- messages can be dropped silently ;
- messages can be edited ;
- messages can be stripped from a client-only tag
| Raito Bezarius | 2025-10-10 | 3 | -12/+86 |
| * | m_message: proper tag propagation•••This introduces an handler to accept or not the propagation of a tag.
Basic sketch API is provided for modules to hook for providing their own
policy for specific tag propagation.
| Raito Bezarius | 2025-10-10 | 1 | -9/+38 |