It has become clear that there are two situations that occur in which a client becomes out of synch with the server. Unfortunately, I believe that this is the fault of the ircd, because the connection between the two was over 127.0.0.1 (so not a connection problem ). Allow me to explain:
Desynch #1: User Mode Flags
Problem: User Bob, connected to my.irc.net with services at services.irc.net, registers to NickServ. In response, NickServ sends the command :NickServ SVSMODE Bob +r 123456780. Unfortunately, Bob never hears about the Mode change because UnrealIRCd neglected to update him with a :NickServ MODE Bob +r or similar. Bob is now out of synch with the server.
Cause: UnrealIRCd is not properly updating the affected client of the mode change that was invoked via SVSMODE.
Remedy: Bob can type '/mode Bob' to receive an RPL_UMODEIS showing that he has the +r usermode. This shouldn't be necessary.
Solution: When UnrealIRCd finds (and accepts) an SVSMODE command, it should distribute an appropriate MODE command not only to all servers, but to the affected client.
Desynch #2: Channel User Status Desynchs
Problem: Users Bob and Joe, connected to my.irc.net running services at services.irc.net, are on #Test. Bob decides to register the channel. ChanServ, in response, sets Bob +q. He then SOP's Joe and asks him to hop to affect the changes. Joe does so and gets set +ao on join by ChanServ. Now Bob decides to go afk and sets -q on himself. But now a problem appears:
Bob's name list: @Bob, &Joe
Joe's name list: &Joe, Bob
Not only is Joe desynched with Bob, he is desynched with the server, which will become evident as soon as Bob performs a chanop only command (we'll assume neither is an SA). The reason for the desynch? Joe relied on the NAME list when he hopped to get Bob's state. Since his client wouldn't know what happened during the hop, it can't use prior information.
Cause: UnrealIRCd's NAME list doesn't properly handle users with multiple channel statuses.
Remedy: Joe can fix the desynch by hopping or re-requesting the NAMES list. But what if the server could make this unnecessary...
Solution: A technique I like to call 'OpSynch' which works like this:
When Joe rejoins from the hop to check the SOP, the following appears on Joe's client:
Code: Select all
#Test Joe Bob
#Test End of /NAMES list.
* Now talking in #Test...
* ChanServ sets mode: +ao Joe Joe
* OpSynch ([email protected]) has joined #Test.
* OpSynch sets mode: +qo Bob Bob
* OpSynch ([email protected]) has left #Test.
All Bob saw, however, was:
Code: Select all
* Joe ([email protected]) has joined #Test.
* ChanServ sets mode: +ao Joe Joe
1) In the NAMES reply, report the user as having no status at all.
2) After the RPL_ENDOFNAMES, make OpSynch join the channel. Send a JOIN command for OpSynch only to the user that is requesting the NAMES list. Then send MODE commands updating the users modes.
3) After the job is done, send a PART for OpSynch.
This could be enabled via set::options::enable-opsynch; which would automatically Q-Line OpSynch.