Commit Graph

319 Commits

Author SHA1 Message Date
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
Simon Ser
fb8c6340c8
Allow '/' in nickname
This allows to specify a network name in the nickname.

Closes: https://todo.sr.ht/~emersion/soju/91
2020-08-25 11:49:22 +02:00
Simon Ser
92fece5cd4
Nuke in-memory ring buffer
Instead, always read chat history from logs. Unify the implicit chat
history (pushing history to clients) and explicit chat history
(via the CHATHISTORY command).

Instead of keeping track of ring buffer cursors for each client, use
message IDs.

If necessary, the ring buffer could be re-introduced behind a
common MessageStore interface (could be useful when on-disk logs are
disabled).

References: https://todo.sr.ht/~emersion/soju/80
2020-08-20 20:05:01 +02:00
Simon Ser
4dae0da59f
Replace networkHistory.offlineClients with clients
Keep the ring buffer alive even if all clients are connected. Keep the
ID of the latest delivered message even for online clients.

As-is, this is a net downgrade: memory usage increases because ring
buffers aren't free'd anymore. However upcoming commits will replace the
ring buffer with log files. This change makes reading from log files
easier.
2020-08-20 17:38:57 +02:00
Hubert Hirtz
e740d952ad
Reject downstream NICK with illegal characters
This should avoid confusion when mixing up nickname and user name.
Also it avoid breaking downstreams (since '@' and '!' are used for host
masks).
2020-08-20 10:00:58 +02:00
Hubert Hirtz
a27e5ea92e
More explicit error message on INVITE with the wrong network 2020-08-20 09:13:38 +02:00
Hubert Hirtz
a636b92a95
More explicit error message on KICK with the wrong network 2020-08-19 23:57:25 +02:00
Simon Ser
bdb132ad98
Implement rate limiting for upstream messages
Allow up to 10 outgoing messages in a burst, then throttle to 1 message
each 2 seconds.

Closes: https://todo.sr.ht/~emersion/soju/87
2020-08-19 19:42:33 +02:00
Simon Ser
745b3f67a0
Extract history loading into functions
These will get re-used for sending history to clients that don't support
the chathistory extension.
2020-08-11 15:58:50 +02:00
Simon Ser
cd3eacdbfc
go fmt 2020-07-22 12:16:01 +02:00
Simon Ser
dcfe206bda
Implement CHATHISTORY AFTER
References: https://todo.sr.ht/~emersion/soju/12
2020-07-15 17:47:57 +02:00
Simon Ser
1685ba23b3
Strip network name from nickname when auto-saving network 2020-07-06 18:13:40 +02:00