JOIN command not sent to the IRC server #914

Open
opened 2026-10-05 04:52:27 +02:00 by adam · 5 comments
Owner

znc 1.7.2+deb1+bionic0

Let's imagine I have a channel where I already have an opped nick.

  1. Join the channel from znc. (Now you have two nicks inside, the original one and your znc.)

  2. Detach from the channel.

  3. From the opped nick, set a mode that makes it impossible for znc to rejoin (like +r).

  4. Reconnect znc.

  5. znc will keep trying to rejoin fruitlessly. Once it's done trying (10 attempts seems to be the default) you'll get a message saying the channel has been disabled.

  6. Join the channel manually from znc.

That last JOIN command will not go through to the IRC server.

znc 1.7.2+deb1+bionic0 Let's imagine I have a channel where I already have an opped nick. 1. Join the channel from znc. (Now you have two nicks inside, the original one and your znc.) 2. Detach from the channel. 3. From the opped nick, set a mode that makes it impossible for znc to rejoin (like +r). 4. Reconnect znc. 5. znc will keep trying to rejoin fruitlessly. Once it's done trying (10 attempts seems to be the default) you'll get a message saying the channel has been disabled. 6. Join the channel manually from znc. That last JOIN command will not go through to the IRC server. <!-- github-sync-id:456675601 -->
Author
Owner

While it's trying to join:

22:00:09 <*status> +---------------+----------+-----------+--------+-------+--------------+-------+---+---+---+
22:00:09 <*status> | Name          | Status   | In config | Buffer | Clear | Modes        | Users | . | @ | + |
22:00:09 <*status> +---------------+----------+-----------+--------+-------+--------------+-------+---+---+---+
22:00:09 <*status> | #hola         | Trying   | yes       | 0      |       |              | 0     | 0 | 0 | 0 |
22:00:09 <*status> +---------------+----------+-----------+--------+-------+--------------+-------+---+---+---+

After it's given up:

22:04:19 <*status> +---------------+----------+-----------+--------+-------+--------------+-------+---+---+---+
22:04:19 <*status> | Name          | Status   | In config | Buffer | Clear | Modes        | Users | . | @ | + |
22:04:19 <*status> +---------------+----------+-----------+--------+-------+--------------+-------+---+---+---+
22:04:19 <*status> | #hola         | Disabled | yes       | 0      |       |              | 0     | 0 | 0 | 0 |
22:04:19 <*status> +---------------+----------+-----------+--------+-------+--------------+-------+---+---+---+

After the first /join command (which doesn't go through):

22:04:24 <*status> +---------------+----------+-----------+--------+-------+--------------+-------+---+---+---+
22:04:24 <*status> | Name          | Status   | In config | Buffer | Clear | Modes        | Users | . | @ | + |
22:04:24 <*status> +---------------+----------+-----------+--------+-------+--------------+-------+---+---+---+
22:04:24 <*status> | #hola         | Disabled | yes       | 0      |       | +R           | 0     | 0 | 0 | 0 |
22:04:24 <*status> +---------------+----------+-----------+--------+-------+--------------+-------+---+---+---+

(Notice how the last one shows +R because Irssi sends JOIN and MODE when I do /join and the ircd responds with MODE +R because I can see the mode of channels even if I'm not inside.)

While it's trying to join: 22:00:09 <*status> +---------------+----------+-----------+--------+-------+--------------+-------+---+---+---+ 22:00:09 <*status> | Name | Status | In config | Buffer | Clear | Modes | Users | . | @ | + | 22:00:09 <*status> +---------------+----------+-----------+--------+-------+--------------+-------+---+---+---+ 22:00:09 <*status> | #hola | Trying | yes | 0 | | | 0 | 0 | 0 | 0 | 22:00:09 <*status> +---------------+----------+-----------+--------+-------+--------------+-------+---+---+---+ After it's given up: 22:04:19 <*status> +---------------+----------+-----------+--------+-------+--------------+-------+---+---+---+ 22:04:19 <*status> | Name | Status | In config | Buffer | Clear | Modes | Users | . | @ | + | 22:04:19 <*status> +---------------+----------+-----------+--------+-------+--------------+-------+---+---+---+ 22:04:19 <*status> | #hola | Disabled | yes | 0 | | | 0 | 0 | 0 | 0 | 22:04:19 <*status> +---------------+----------+-----------+--------+-------+--------------+-------+---+---+---+ After the first /join command (which doesn't go through): 22:04:24 <*status> +---------------+----------+-----------+--------+-------+--------------+-------+---+---+---+ 22:04:24 <*status> | Name | Status | In config | Buffer | Clear | Modes | Users | . | @ | + | 22:04:24 <*status> +---------------+----------+-----------+--------+-------+--------------+-------+---+---+---+ 22:04:24 <*status> | #hola | Disabled | yes | 0 | | +R | 0 | 0 | 0 | 0 | 22:04:24 <*status> +---------------+----------+-----------+--------+-------+--------------+-------+---+---+---+ (Notice how the last one shows +R because Irssi sends JOIN and MODE when I do /join and the ircd responds with MODE +R because I can see the mode of channels even if I'm not inside.) <!-- github-comment-id:502481734 -->
Author
Owner

*raw of the failed /join:

22:04:21 <*raw> YOU -> [JOIN #hola]
22:04:21 <*raw> YOU -> [MODE #hola]
22:04:21 <*raw> IRC -> [:server.com 324 mynick #hola +R ]
22:04:21 <*raw> IRC -> [:server.com 329 mynick #hola 1560704009]
*raw of the failed /join: 22:04:21 <*raw> YOU -> [JOIN #hola] 22:04:21 <*raw> YOU -> [MODE #hola] 22:04:21 <*raw> IRC -> [:server.com 324 mynick #hola +R ] 22:04:21 <*raw> IRC -> [:server.com 329 mynick #hola 1560704009] <!-- github-comment-id:502481783 -->
Author
Owner

From a quick look:

  • CClient::OnJoinMessage goes through if (pChan->IsDetached()) pChan->AttachUser(this); else pChan->JoinUser(sKey);
  • Uhm.. the detached status gets lost? Perhaps due to something that happens during reconnection? Or alternatively, I am confused. But if AttachUser ends up being called, ZNC should just "invent" a JOIN reply, which obviously does not happen here.
  • CChan::JoinUser sends a JOIN message to the IRC server (that is pretty much all that the function does)
  • Somehow the reply is not forwarded?

Well, okay, I do not know what is going on. @wodim Could you load the raw module, try this again, and tell us what *raw reports when you try to /join?

Edit: Oh, whoops. Sorry for missing that you already used *raw. Somehow I read that as a raw log from your IRC client.

From a quick look: - `CClient::OnJoinMessage` goes through `if (pChan->IsDetached()) pChan->AttachUser(this); else pChan->JoinUser(sKey);` - Uhm.. the detached status gets lost? Perhaps due to something that happens during reconnection? Or alternatively, I am confused. But if `AttachUser` ends up being called, ZNC should just "invent" a JOIN reply, which obviously does not happen here. - `CChan::JoinUser` sends a `JOIN` message to the IRC server (that is pretty much all that the function does) - Somehow the reply is not forwarded? Well, okay, I do not know what is going on. @wodim Could you load the `raw` module, try this again, and tell us what `*raw` reports when you try to `/join`? Edit: Oh, whoops. Sorry for missing that you already used `*raw`. Somehow I read that as a raw log from your IRC client. <!-- github-comment-id:502741344 -->
Author
Owner

@psychon it’s in my last comment.

@psychon it’s in my last comment. <!-- github-comment-id:502745608 -->
Author
Owner

I've tried to reproduce this by following steps outlined in description without success on ZNC 1.8.1.

@wodim could you include a list of the loaded modules too? It might be a module could interfere with the behaviour, I've had a quick scan of the built in modules and notice stood out to me though.

Not all messages that originate from ZNC are outputted in *raw, I do see the same output in *raw as described, however using znc --foreground --debug I can confirm that the JOIN is actually sent:

C: PRIVMSG *status :loadmod raw
S: :*status!znc@znc.in PRIVMSG Guest27614 :Loaded module raw: [/usr/local/Cellar/znc/1.8.1/lib/znc/raw.so]
C: JOIN #test2
S: :*raw!znc@znc.in PRIVMSG Guest27614 :YOU -> [JOIN #test2]

vs znc:

[2020-08-02 16:32:34.226424] (kyle/darkscience) CLI -> ZNC [PRIVMSG *status :loadmod raw]
[2020-08-02 16:32:34.236524] (kyle/darkscience) ZNC -> CLI [:*status!znc@znc.in PRIVMSG Guest27614 :Loaded module raw: [/usr/local/Cellar/znc/1.8.1/lib/znc/raw.so]]
[2020-08-02 16:32:39.027452] (kyle/darkscience) CLI -> ZNC [JOIN #test2]
[2020-08-02 16:32:39.027481] (kyle/darkscience) ZNC -> CLI [:*raw!znc@znc.in PRIVMSG Guest27614 :YOU -> [JOIN #test2]]
[2020-08-02 16:32:39.027549] (kyle/darkscience) ZNC -> IRC [JOIN #test2]

It may be that the JOIN is sent to the upstream IRC server, and the IRC server is not responding to it with any reply. I have seen cases of that, such as if you send a JOIN when you are already in the channel. To demonstrate:

C: JOIN #test
S: :*raw!znc@znc.in PRIVMSG Guest27614 :YOU -> [JOIN #test]
// ^ - no response, ZNC actually does send JOIN to server, server ignores because I am already in #test

// querying NAMES provides that I (Guest27614) am there already:
C: NAMES #test
S: :*raw!znc@znc.in PRIVMSG Guest27614 :YOU -> [NAMES #test]
S: :*raw!znc@znc.in PRIVMSG Guest27614 :IRC -> [@time=2020-08-02T15:37:21.387Z :irc-eu-2.darkscience.net 353 Guest27614 = #test :SillyGoose!~SillyGoos@reid-ren.2un.207.91.IP Guest27614!~kyle@reid-j5c.ks3.36.89.IP]
S: :irc-eu-2.darkscience.net 353 Guest27614 = #test :SillyGoose Guest27614
S :*raw!znc@znc.in PRIVMSG Guest27614 :IRC -> [@time=2020-08-02T15:37:21.387Z S: :irc-eu-2.darkscience.net 366 Guest27614 #test :End of /NAMES list.]
S: :irc-eu-2.darkscience.net 366 Guest27614 #test :End of /NAMES list.
I've tried to reproduce this by following steps outlined in description without success on ZNC 1.8.1. @wodim could you include a list of the loaded modules too? It might be a module could interfere with the behaviour, I've had a quick scan of the built in modules and notice stood out to me though. Not all messages that originate from ZNC are outputted in `*raw`, I do see the same output in `*raw` as described, however using `znc --foreground --debug` I can confirm that the `JOIN` is actually sent: ``` C: PRIVMSG *status :loadmod raw S: :*status!znc@znc.in PRIVMSG Guest27614 :Loaded module raw: [/usr/local/Cellar/znc/1.8.1/lib/znc/raw.so] C: JOIN #test2 S: :*raw!znc@znc.in PRIVMSG Guest27614 :YOU -> [JOIN #test2] ``` vs znc: ``` [2020-08-02 16:32:34.226424] (kyle/darkscience) CLI -> ZNC [PRIVMSG *status :loadmod raw] [2020-08-02 16:32:34.236524] (kyle/darkscience) ZNC -> CLI [:*status!znc@znc.in PRIVMSG Guest27614 :Loaded module raw: [/usr/local/Cellar/znc/1.8.1/lib/znc/raw.so]] [2020-08-02 16:32:39.027452] (kyle/darkscience) CLI -> ZNC [JOIN #test2] [2020-08-02 16:32:39.027481] (kyle/darkscience) ZNC -> CLI [:*raw!znc@znc.in PRIVMSG Guest27614 :YOU -> [JOIN #test2]] [2020-08-02 16:32:39.027549] (kyle/darkscience) ZNC -> IRC [JOIN #test2] ``` It may be that the JOIN is sent to the upstream IRC server, and the IRC server is not responding to it with any reply. I have seen cases of that, such as if you send a JOIN when you are already in the channel. To demonstrate: ``` C: JOIN #test S: :*raw!znc@znc.in PRIVMSG Guest27614 :YOU -> [JOIN #test] // ^ - no response, ZNC actually does send JOIN to server, server ignores because I am already in #test // querying NAMES provides that I (Guest27614) am there already: C: NAMES #test S: :*raw!znc@znc.in PRIVMSG Guest27614 :YOU -> [NAMES #test] S: :*raw!znc@znc.in PRIVMSG Guest27614 :IRC -> [@time=2020-08-02T15:37:21.387Z :irc-eu-2.darkscience.net 353 Guest27614 = #test :SillyGoose!~SillyGoos@reid-ren.2un.207.91.IP Guest27614!~kyle@reid-j5c.ks3.36.89.IP] S: :irc-eu-2.darkscience.net 353 Guest27614 = #test :SillyGoose Guest27614 S :*raw!znc@znc.in PRIVMSG Guest27614 :IRC -> [@time=2020-08-02T15:37:21.387Z S: :irc-eu-2.darkscience.net 366 Guest27614 #test :End of /NAMES list.] S: :irc-eu-2.darkscience.net 366 Guest27614 #test :End of /NAMES list. ``` <!-- github-comment-id:667689473 -->
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: adam/znc#914