Commit graph

330 commits

Author SHA1 Message Date
Simon Ser abe5f362db Turn CHATHISTORY and backlog limits into constants 2021-11-03 18:29:21 +01:00
Simon Ser ce69f00e3f msgstore: add context to messageStore methods
This allows setting a hard timeout.
2021-11-03 18:21:05 +01:00
Simon Ser 2b4f0a870f msgstore: take Network as arg instead of network
The message stores don't need to access the internal network
struct, they just need network metadata such as ID and name.

This can ease moving message stores into a separate package in the
future.
2021-11-03 16:37:01 +01:00
delthas 03f8972305 Add support for draft/event-playback 2021-11-03 15:17:16 +01:00
Simon Ser a6aa7f0008 Make Network.Nick optional
Make Network.Nick optional, default to the user's username. This
will allow adding a global setting to set the nickname in the
future, just like we have for the real name.

References: https://todo.sr.ht/~emersion/soju/110
2021-11-02 23:33:17 +01:00
Simon Ser 07c962018d Add title config option
Closes: https://todo.sr.ht/~emersion/soju/146
2021-11-02 22:38:07 +01:00
Simon Ser 832d8b89a2 Mark bouncer users and BouncerServ as authenticated in WHOX/WHOIS 2021-11-02 18:32:39 +01:00
Simon Ser 241e27b00e Add support for WHOX
This adds support for WHOX, without bothering about flags and mask2
because Solanum and Ergo [1] don't support it either.

The motivation is to allow clients to reliably query account names.

It's not possible to use WHOX tokens to route replies to the right
client, because RPL_ENDOFWHO doesn't contain it.

[1]: https://github.com/ergochat/ergo/pull/1184

Closes: https://todo.sr.ht/~emersion/soju/135
2021-11-02 18:25:43 +01:00
Simon Ser 8c7c907d6f Fix operator flag in RPL_WHOREPLY
@ and + indicate channel privileges. * indicates that the user is
a server operator.
2021-11-01 18:36:21 +01:00
Simon Ser 62d92c660f Mark admins as server operators in self WHO/WHOIS replies 2021-11-01 18:32:01 +01:00
Simon Ser 3ab8ef17df Mark BouncerServ as server operator
That's what some widely used IRC servers do for their own services
(e.g. NickServ and ChanServ). This adds an additional level of
trust to make sure BouncerServ isn't typo'ed or impersonated.
2021-11-01 18:28:19 +01:00
Simon Ser aa407a46e6 Get rid of io.EOF errors in logs
Closes: https://todo.sr.ht/~emersion/soju/150
2021-10-29 16:03:04 +02:00
Simon Ser 0cd18a78db Unify BOUNCER ADDNETWORK and CHANGENETWORK 2021-10-29 15:51:13 +02:00
Simon Ser de38d93085 Always reply ERR_SASLABORTED on SASL abort
Some clients (Hexchat) always expect AUTHENTICATE * to succeed with
ERR_SASLABORTED even if SASL hasn't been started.
2021-10-28 11:29:34 +02:00
Simon Ser 9ec1f1a5b0 Add context args to Database interface
This is a mecanical change, which just lifts up the context.TODO()
calls from inside the DB implementations to the callers.

Future work involves properly wiring up the contexts when it makes
sense.
2021-10-18 19:15:15 +02:00
Simon Ser 4be6c4b19c Remove unnecessary downstream cap checks
downstreamConn.SendMessage already performs this cap checking.
2021-10-18 09:20:11 +02:00
Simon Ser 1507e88b36 Remove incorrect AWAY TODO in downstreamConn.SendMessage
PRIVMSG/NOTICE get RPL_AWAY, not AWAY.
2021-10-18 09:08:52 +02:00
Simon Ser 324d0fb0ac Unify away-notify and account-notify handling 2021-10-17 21:54:18 +02:00
Simon Ser 455fef2421 Add support for account-notify 2021-10-17 21:54:18 +02:00
Simon Ser 2f495e9768 Remove unused REGISTRATION_IS_COMPLETED in handleMessageUnregistered
downstreamConn.handleMessageUnregistered is only called when the
user isn't registered.
2021-10-16 11:42:32 +02:00
Simon Ser ade59beb8c Send BOUNCER REGISTRATION_IS_COMPLETED error 2021-10-16 11:41:37 +02:00
Alexey Yerin 3109340651 downstream: handle name=... in BOUNCER 2021-10-14 16:03:14 +02:00
Simon Ser a9a066faac Add bouncer MOTD
Closes: https://todo.sr.ht/~emersion/soju/137
2021-10-13 10:58:34 +02:00
Simon Ser e55d0d7552 Stop sending RPL_CREATED
There's no point in sending this numeric if it doesn't contain any
useful info.
2021-10-12 19:28:44 +02:00
Simon Ser 6e8b6fa153 Fix printf formatting in error message 2021-10-12 17:36:00 +02:00
Hubert Hirtz 3a171607e0 Correctly send back PRIVMSGs and NOTICEs to self 2021-10-10 12:05:41 +02:00
Hubert Hirtz d4b7bb02da Send back TAGMSGs to self 2021-10-10 12:05:41 +02:00
Hubert Hirtz 0fd81f38fa Dismiss TAGMSGs directed to BouncerServ 2021-10-10 12:05:40 +02:00
Simon Ser 1d56ef19e7 Add WHOIS reply for BouncerServ 2021-10-06 11:50:12 +02:00
Hubert Hirtz 2554c92df7 Allow CAP negotiation to happen with CAP REQ
See https://ircv3.net/specs/extensions/capability-negotiation

> Upon receiving either a CAP LS or CAP REQ command during connection
> registration, the server MUST not complete registration until the
> client sends a CAP END command to indicate that capability negotiation
> has ended.

This commit should prevent soju from trying to authenticate the user
prior to having received AUTHENTICATE messages, when the client eagerly
requests capabilities with CAP REQ seeing available capabilities
beforehand with CAP LS.
2021-09-19 16:50:47 +02:00
Simon Ser 0f2f4de275 Send empty history for service
Fixes error when fetching chat history for BouncerServ.
2021-09-13 11:36:25 +02:00
Simon Ser fba1fdb31e Don't require upstream to be connected for CHATHISTORY
Closes: https://todo.sr.ht/~emersion/soju/127
2021-09-13 11:25:38 +02:00
Simon Ser cd64a7ffda Split unmarshalEntity into two functions
Some command handlers need to unmarshal without requiring the
upstream to be connected.
2021-09-13 11:14:47 +02:00
Simon Ser c5d5259243 Pass-through CLIENTTAGDENY in ISUPPORT 2021-07-09 22:48:58 +02:00
Simon Ser a14f646135 Add per-user realname setting
This allows users to set a default realname used if the per-network
realname isn't set.

A new "user update" command is introduced and can be extended to edit
other user properties and other users in the future.
2021-06-25 20:33:13 +02:00
Simon Ser f3f864dddc Disallow '$' in nicks 2021-06-23 19:54:22 +02:00
Simon Ser d7b1c5a9a2 Allow admins to broadcast message to all bouncer users
Typically done via:

    /notice $<bouncer> <message>

Or, for a connection not bound to a specific network:

    /notice $* <message>

The message is broadcast as BouncerServ, because that's the only
user that can be trusted to belong to the bouncer by users. Any
other prefix would conflict with the upstream network.
2021-06-23 19:23:09 +02:00
Simon Ser eca4c41223 Unify downstream PRIVMSG and NOTICE handling
We were doing some things wrong here, e.g. not sending echo messages
for NOTICE.
2021-06-23 18:17:30 +02:00
Simon Ser faa89333bf Add support for utf8-only 2021-06-15 15:48:10 +02:00
Simon Ser b609b86f97 Add support for account-tag 2021-06-14 21:44:38 +02:00
Simon Ser 0557ca5871 Don't suggest users to /motd in multi-upstream mode 2021-06-10 12:16:33 +02:00
Simon Ser 2b3782a507 Make user MODE commands fail in multi-upstream mode
References: https://todo.sr.ht/~emersion/soju/20
2021-06-10 11:24:10 +02:00
Gregory Anders 0e9ef1f97c Forward user mode changes in single-upstream mode
References: https://todo.sr.ht/~emersion/soju/20
2021-06-10 11:17:00 +02:00
Gregory Anders 2fe0a57e43 Forward MOTD messages downstream
The first MOTD upon connection is ignored, but subsequent MOTD messages
(requested by the "MOTD" message from the client, typically using a
/motd command) are forwarded.
2021-06-09 21:29:36 +02:00
Simon Ser 0081c96ec0 Add downstreamConn.SendBatch helper 2021-06-05 12:38:52 +02:00
Simon Ser bd41e3bd2b Prune detached channels from CHATHISTORY TARGETS 2021-06-04 11:27:59 +02:00
Simon Ser 18439f0de5 Implement CHATHISTORY TARGETS
References: https://github.com/ircv3/ircv3-specifications/pull/450
2021-06-02 20:32:11 +02:00
Simon Ser 0f3dd2f2b1 Forward unknown commands to upstream in single-upstream mode 2021-05-28 11:15:15 +02:00
Simon Ser 517be78868 Reject JOIN with invalid channel names
This prevents us from storing typo'ed channel names in the DB.
2021-05-26 11:23:09 +02:00
Simon Ser 7d648f702e Allow networks to be disabled 2021-05-26 10:51:02 +02:00
Simon Ser 47c514a9cf Add support for IRCv3 setname
References: https://todo.sr.ht/~emersion/soju/41
2021-05-25 20:24:45 +02:00
Simon Ser 4cf9804e89 Vendor BATCH bouncer-networks type
And add the prefix throughout the spec, to make it clear the unprefixed
version is not to be used.
2021-05-25 16:56:38 +02:00
Simon Ser 31f2d28508 Introduce the soju.im/bouncer-networks-notify capability 2021-05-25 16:42:51 +02:00
Simon Ser 29ad541ac7 Send network settings in LISTNETWORKS 2021-05-25 16:42:51 +02:00
Simon Ser 60c566e721 Add pass to bouncer network attributes 2021-05-25 16:42:51 +02:00
Simon Ser db0f745193 Implement the soju.im/bouncer-networks extension 2021-05-25 16:42:51 +02:00
Philip K b3bc9614f8 Directly return self-messages to user in multi-upstream mode 2021-05-24 13:31:24 +02:00
Simon Ser 68463d3e8b Pass-through the BOT ISUPPORT token
References: https://github.com/ircv3/ircv3-specifications/pull/439
2021-05-24 11:41:04 +02:00
Hubert Hirtz 3b41c87a41 Fix CAP LIST listing disabled capabilities 2021-05-21 10:03:39 +02:00
Simon Ser ec26117c08 Relay self-WHO/WHOIS in single-upstream mode
In multi-upstream mode, we can't relay WHO/WHOIS messages for the
current user, because we can't decide which upstream server the
message should be relayed to.

In single-upstream server, we do know which upstream server to use,
so we can just blindly relay the message.

This allows users to send a self-WHO/WHOIS to check their cloak and
other information.
2021-05-20 11:13:14 +02:00
Hubert Hirtz b078ccaf7a Implement CHATHISTORY BETWEEN 2021-05-18 10:44:10 +02:00
Simon Ser bede274f32 Add more context to chathistory errors 2021-05-11 12:42:12 +02:00
Hubert Hirtz 9e04b3899b Don't directly reply to network-specific NICK
The NICK must only apply to the specific network, not to the downstream
connection.
2021-04-30 12:17:23 +02:00
Hubert Hirtz e84fad3eda Handle casemapping on BouncerServ 2021-04-30 12:10:49 +02:00
Simon Ser a2c207d357 Relay detached channel backlog as BouncerServ NOTICE if necessary
Instead of ignoring detached channels wehn replaying backlog,
process them as usual and relay messages as BouncerServ NOTICEs
if necessary. Advance the delivery receipts as if the channel was
attached.

Closes: https://todo.sr.ht/~emersion/soju/98
2021-04-13 19:11:05 +02:00
Simon Ser 45e2c0023a Skip backlog logic in downstreamConn.welcome on chathistory 2021-04-13 17:50:03 +02:00
Simon Ser 65c58adbd9 Take msg ID in sendTargetBacklog 2021-04-13 17:49:37 +02:00
Simon Ser 5b4469fcb7 Use BARE for internal message IDs
This allows to have shorter and more future-proof IDs. This also
guarantees the IDs will only use reasonable ASCII characters (no
spaces), removing the need to encode them for PING/PONG tokens.
2021-03-31 17:57:24 +02:00
Simon Ser ecf35187fa Make NickServ detection casemapping-aware 2021-03-30 12:28:45 +02:00
Simon Ser 3237bde9f3 Introduce deliveredStore
This hides the double-map complexity behind a dedicated type.
2021-03-29 17:49:50 +02:00
Simon Ser 07519da768 Ensure targets are case-mapped before being passed to messageStore
messageStore isn't aware of the network's case-mapping. We need
to canonicalize the names before passing them to messageStore.
2021-03-29 17:07:39 +02:00
Simon Ser 5a899abaab Simplify network.offlineClients
Replace it with a list of all clients (online or offline).
2021-03-29 16:55:57 +02:00
Simon Ser 6e5a307dc7 Introduce deliveredClientMap
Adds more semantics to map[string]string. Simplifies the complicated
mapStringStringCasemapMap type.
2021-03-26 11:21:14 +01:00
Hubert Hirtz 5014673aae Fix CHATHISTORY target not being casemapped 2021-03-26 10:39:52 +01:00
Hubert Hirtz bdd0c7bc06
Implement casemapping
TL;DR: supports for casemapping, now logs are saved in
casemapped/canonical/tolower form
(eg. in the #channel directory instead of #Channel... or something)

== What is casemapping? ==

see <https://modern.ircdocs.horse/#casemapping-parameter>

== Casemapping and multi-upstream ==

Since each upstream does not necessarily use the same casemapping, and
since casemappings cannot coexist [0],

1. soju must also update the database accordingly to upstreams'
   casemapping, otherwise it will end up inconsistent,
2. soju must "normalize" entity names and expose only one casemapping
   that is a subset of all supported casemappings (here, ascii).

[0] On some upstreams, "emersion[m]" and "emersion{m}" refer to the same
user (upstreams that advertise rfc1459 for example), while on others
(upstreams that advertise ascii) they don't.

Once upstream's casemapping is known (default to rfc1459), entity names
in map keys are made into casemapped form, for upstreamConn,
upstreamChannel and network.

downstreamConn advertises "CASEMAPPING=ascii", and always casemap map
keys with ascii.

Some functions require the caller to casemap their argument (to avoid
needless calls to casemapping functions).

== Message forwarding and casemapping ==

downstream message handling (joins and parts basically):
When relaying entity names from downstreams to upstreams, soju uses the
upstream casemapping, in order to not get in the way of the user.  This
does not brings any issue, as long as soju replies with the ascii
casemapping in mind (solves point 1.).

marshalEntity/marshalUserPrefix:
When relaying entity names from upstreams with non-ascii casemappings,
soju *partially* casemap them: it only change the case of characters
which are not ascii letters.  ASCII case is thus kept intact, while
special symbols like []{} are the same every time soju sends them to
downstreams (solves point 2.).

== Casemapping changes ==

Casemapping changes are not fully supported by this patch and will
result in loss of history.  This is a limitation of the protocol and
should be solved by the RENAME spec.
2021-03-24 18:15:52 +01:00
Simon Ser 26c5c11caf Improve ERR_NOSUCHCHANNEL error messages
References: https://todo.sr.ht/~emersion/soju/63
2021-03-16 09:13:46 +01:00
Simon Ser fa047123b9 Passthrough some ISUPPORT tokens 2021-03-15 23:41:37 +01:00
Simon Ser 62d4bf2813 Use upstream ISUPPORT map for NETWORK 2021-03-15 23:08:19 +01:00
Hubert Hirtz 1645371276 Send correct CHATHISTORY error messages 2021-03-05 09:53:59 +01:00
Simon Ser 26473ed60d Introduce downstreamConn.sendTargetBacklog 2021-02-10 13:48:41 +01:00
Simon Ser 7e39f6d663 Rename network.history to network.delivered
"History" is over-loaded with e.g. CHATHISTORY support.
2021-02-10 11:31:34 +01:00
Simon Ser c14118f7f9 Rename sendNetworkHistory to sendNetworkBacklog
"History" is a little bit over-loaded with CHATHISTORY support.
2021-02-10 10:23:51 +01:00
Hubert Hirtz 5aa15d5628 Request invite-notify to upstreams
... and do not forward INVITEs to downstreams that do not support the
capability.

The downstream capability can be permanent because there is no way for a
client to get the list of people invited to a channel, thus no state can
be corrupted.
2021-01-31 22:18:51 +01:00
Simon Ser 62f1207437 Forward ISUPPORT NETWORK token 2021-01-22 12:00:38 +01:00
Simon Ser c4d9e6822d Send RPL_ISUPPORT CHATHISTORY token 2021-01-22 11:55:06 +01:00
Simon Ser ac3431ef76
Make chat history operations optional in messageStore
Some stores may want not to implement chat history operations.
2021-01-04 17:17:35 +01:00
Simon Ser 83a4590acc
Add store-agnostic message ID format
Allow to query the network ID and entity from the message ID regardless
of the underlying store used.
2021-01-04 16:26:30 +01:00
Hubert Hirtz 943182de2f
Improve dc.authenticate()'s error messages 2020-12-25 13:37:15 +01:00
Hubert Hirtz 7bfa4dafef
Advertise all caps, CAP DEL them on registration
... so that the JOIN/history batch takes into account all capabilities.
Without this commit for example, enabling multi-prefix after the batch
makes the client send NAMES requests for all channels, which generate
needless traffic.
2020-12-25 13:35:20 +01:00
delthas a76b22bf29 Add customizable auto-detaching, auto-reattaching, relaying.
This uses the fields added previously to the Channel struct to implement
the actual detaching/reattaching/relaying logic.

The `FilterDefault` values of the messages filters are currently
hardcoded.

The values of the message filters are not currently user-settable.

This introduces a new user event, eventChannelDetach, which stores an
upstreamConn (which might become invalid at the time of processing), and
a channel name, used for auto-detaching. Every time the channel detach
timer is refreshed (by receveing a message, etc.), a new timer is
created on the upstreamChannel, which will dispatch this event after the
duration (and discards the previous timer, if any).
2020-12-14 20:54:02 +01:00
Hubert Hirtz cab0fc2b7d
Uphold echo-message even with BouncerServ
Fixes <https://todo.sr.ht/~emersion/soju/74>
2020-11-24 14:25:19 +01:00
Simon Ser 473a0f018b
Fix nickname in ERR_ERRONEOUSNICKNAME 2020-11-24 14:22:39 +01:00
Hubert Hirtz 16c68b21b5
Prevent downstreams from changing their nick to service's
This commit prevents downstream from sending those commands:
- NICK BouncerServ
- NICK BouncerServ/<network>

The later is necessary because soju would otherwise save the nick change
and, in the event that the downstream connects in single-upstream mode
to <network>, it will end up with the nickname "BouncerServ".
2020-11-24 14:22:18 +01:00
Simon Ser e797d90c59
Implement delivery receipts via PING messages
This patch implements basic message delivery receipts via PING and PONG.

When a PRIVMSG or NOTICE message is sent, a PING message with a token is
also sent. The history cursor isn't immediately advanced, instead the
bouncer will wait for a PONG message before doing so.

Self-messages trigger a PING for simplicity's sake. We can't immediately
advance the history cursor in this case, because a prior message might
still have an outstanding PING.

Future work may include optimizations such as removing the need to send
a PING after a self-message, or groupping multiple PING messages
together.

Closes: https://todo.sr.ht/~emersion/soju/11
2020-11-24 14:13:24 +01:00
Hubert Hirtz e4d2ddb377
Don't send TAGMSG to upstreams that don't support it
TAGMSG are (in current specs and drafts from IRCv3) only used for
client tags. These are optional information by design (since they are
not distributed to all users), therefore it is preferable to discard
them accordingly to upstream, instead of waiting for all upstreams to
support the capability to advertise it.
2020-11-20 11:37:43 +01:00
Simon Ser 05aafb5edf
Add message store abstraction
Introduce a messageStore type, which will allow for multiple
implementations (e.g. in the DB or in-memory instead of on-disk).

The message store is per-user so that we don't need to deal with locking
and it's easier to implement per-user limits.
2020-10-25 17:47:38 +01:00
Simon Ser fa16337d97
Switch DB API to user IDs
This commit changes the Network schema to use user IDs instead of
usernames. While at it, a new UNIQUE(user, name) constraint ensures
there is no conflict with custom network names.

Closes: https://todo.sr.ht/~emersion/soju/86
References: https://todo.sr.ht/~emersion/soju/29
2020-10-24 15:14:23 +02:00
delthas 28cf1147e8 Add support for the extended-join capability
This simple implementation only advertises extended-join to downstreams
when all upstreams support it.

In the future, it could be modified so that soju buffers incoming
upstream JOINs, sends a WHO, waits for the reply, and sends an extended
join to the downstream; so that soju could advertise that capability
even when some or all upstreams do not support it. This is not the case
in this commit.
2020-09-11 00:10:58 +02:00
Simon Ser 480d771a67
Fix panic in downstreamConn.sendNetworkHistory
This panic happens when sending history to a multi-upstream client.
sendNetworkHistory is called on each network, but dc.network is nil.

Closes: https://todo.sr.ht/~emersion/soju/93
2020-08-26 15:28:10 +02:00
Simon Ser 43aa3e5529
Fix downstream PING argument handling
The PONG message should have these arguments:

- Our server name
- The PING message's source name

Closes: https://todo.sr.ht/~emersion/soju/92
2020-08-26 15:18:57 +02:00