Skip to content

Instantly share code, notes, and snippets.

@vjt
Created April 21, 2026 09:28
Show Gist options
  • Select an option

  • Save vjt/0b2ad7eeb661da1274053ad19dc26655 to your computer and use it in GitHub Desktop.

Select an option

Save vjt/0b2ad7eeb661da1274053ad19dc26655 to your computer and use it in GitHub Desktop.
azzurra/services PR #13 test evidence — issue #1 (TOPIC doubling on netsplit heal)
09:20:02 Cfounder >>> OPER testoper testoperpass
09:20:02 Cfounder >>> PRIVMSG NickServ :REGISTER secretpw x@x.com
09:20:04 Cleaf >>> OPER testoper testoperpass
09:20:04 Cleaf >>> JOIN #test
09:20:05 Cleaf >>> SAMODE #test +o Cleaf
09:20:05 Cfounder >>> JOIN #test
09:20:06 Cfounder >>> SAMODE #test +o Cfounder
09:20:06 Cfounder >>> PRIVMSG ChanServ :REGISTER #test chanpw Test channel
09:20:08 Cfounder >>> PRIVMSG ChanServ :SET #test TOPICLOCK ON
09:20:08 Cfounder >>> PRIVMSG ChanServ :SET #test KEEPTOPIC ON
09:20:08 Cfounder >>> TOPIC #test :T1-initial-from-Cfounder
09:20:11 Cfounder >>> PRIVMSG #test :MARKER_SCENARIO_START_1
09:20:12 Cfounder >>> SQUIT leaf4.azzurra.chat :test-split
09:20:17 Cfounder >>> CONNECT leaf4.azzurra.chat 7000 hub.azzurra.chat
09:21:17 Cfounder >>> PRIVMSG #test :MARKER_SCENARIO_END_1
09:21:19 Cfounder >>> TOPIC #test
09:17:30 Cfounder >>> OPER testoper testoperpass
09:17:30 Cfounder >>> PRIVMSG NickServ :REGISTER secretpw x@x.com
09:17:32 Cleaf >>> OPER testoper testoperpass
09:17:32 Cleaf >>> JOIN #test
09:17:33 Cleaf >>> SAMODE #test +o Cleaf
09:17:33 Cfounder >>> JOIN #test
09:17:34 Cfounder >>> SAMODE #test +o Cfounder
09:17:34 Cfounder >>> PRIVMSG ChanServ :REGISTER #test chanpw Test channel
09:17:35 Cfounder >>> PRIVMSG ChanServ :SET #test TOPICLOCK ON
09:17:36 Cfounder >>> PRIVMSG ChanServ :SET #test KEEPTOPIC ON
09:17:36 Cfounder >>> TOPIC #test :T1-initial-from-Cfounder
09:17:39 Cfounder >>> PRIVMSG #test :MARKER_SCENARIO_START_2
09:17:40 Cfounder >>> SQUIT leaf4.azzurra.chat :test-split
09:17:43 Cleaf >>> TOPIC #test :T2-changed-during-split
09:17:45 Cleaf >>> TOPIC #test
09:17:51 Cfounder >>> CONNECT leaf4.azzurra.chat 7000 hub.azzurra.chat
09:18:06 Cfounder >>> PRIVMSG #test :MARKER_SCENARIO_END_2
09:18:08 Cfounder >>> TOPIC #test
09:22:15 Cfounder >>> OPER testoper testoperpass
09:22:16 Cfounder >>> PRIVMSG NickServ :REGISTER secretpw x@x.com
09:22:17 Cleaf >>> OPER testoper testoperpass
09:22:17 Cleaf >>> JOIN #test
09:22:18 Cleaf >>> SAMODE #test +o Cleaf
09:22:19 Cfounder >>> JOIN #test
09:22:19 Cfounder >>> SAMODE #test +o Cfounder
09:22:19 Cfounder >>> PRIVMSG ChanServ :REGISTER #test chanpw Test channel
09:22:21 Cfounder >>> PRIVMSG ChanServ :SET #test TOPICLOCK ON
09:22:21 Cfounder >>> PRIVMSG ChanServ :SET #test KEEPTOPIC ON
09:22:21 Cfounder >>> TOPIC #test :T1-initial-from-Cfounder
09:22:24 Cfounder >>> PRIVMSG #test :MARKER_SCENARIO_START_3
09:22:25 Cleaf >>> TOPIC #test :T3-attempted-change-during-normal-ops
09:22:30 Cfounder >>> PRIVMSG #test :MARKER_SCENARIO_END_3
09:22:32 Cfounder >>> TOPIC #test
09:24:11 Cfounder >>> OPER testoper testoperpass
09:24:11 Cfounder >>> PRIVMSG NickServ :REGISTER secretpw x@x.com
09:24:13 Cleaf >>> OPER testoper testoperpass
09:24:13 Cleaf >>> JOIN #test
09:24:14 Cleaf >>> SAMODE #test +o Cleaf
09:24:14 Cfounder >>> JOIN #test
09:24:15 Cfounder >>> SAMODE #test +o Cfounder
09:24:15 Cfounder >>> PRIVMSG ChanServ :REGISTER #test chanpw Test channel
09:24:17 Cfounder >>> PRIVMSG ChanServ :SET #test TOPICLOCK ON
09:24:17 Cfounder >>> PRIVMSG ChanServ :SET #test KEEPTOPIC ON
09:24:17 Cfounder >>> TOPIC #test :T1-initial-from-Cfounder
09:24:20 Cfounder >>> PRIVMSG #test :MARKER_SCENARIO_START_1
09:24:21 Cfounder >>> SQUIT leaf4.azzurra.chat :test-split
09:24:26 Cfounder >>> CONNECT leaf4.azzurra.chat 7000 hub.azzurra.chat
09:25:26 Cfounder >>> PRIVMSG #test :MARKER_SCENARIO_END_1
09:25:28 Cfounder >>> TOPIC #test
09:16:08 Cfounder >>> OPER testoper testoperpass
09:16:08 Cfounder >>> PRIVMSG NickServ :REGISTER secretpw x@x.com
09:16:09 Cleaf >>> OPER testoper testoperpass
09:16:10 Cleaf >>> JOIN #test
09:16:11 Cleaf >>> SAMODE #test +o Cleaf
09:16:11 Cfounder >>> JOIN #test
09:16:11 Cfounder >>> SAMODE #test +o Cfounder
09:16:12 Cfounder >>> PRIVMSG ChanServ :REGISTER #test chanpw Test channel
09:16:13 Cfounder >>> PRIVMSG ChanServ :SET #test TOPICLOCK ON
09:16:13 Cfounder >>> PRIVMSG ChanServ :SET #test KEEPTOPIC ON
09:16:14 Cfounder >>> TOPIC #test :T1-initial-from-Cfounder
09:16:16 Cfounder >>> PRIVMSG #test :MARKER_SCENARIO_START_2
09:16:17 Cfounder >>> SQUIT leaf4.azzurra.chat :test-split
09:16:20 Cleaf >>> TOPIC #test :T2-changed-during-split
09:16:22 Cleaf >>> TOPIC #test
09:16:28 Cfounder >>> CONNECT leaf4.azzurra.chat 7000 hub.azzurra.chat
09:16:43 Cfounder >>> PRIVMSG #test :MARKER_SCENARIO_END_2
09:16:46 Cfounder >>> TOPIC #test
09:26:09 Cfounder >>> OPER testoper testoperpass
09:26:09 Cfounder >>> PRIVMSG NickServ :REGISTER secretpw x@x.com
09:26:11 Cleaf >>> OPER testoper testoperpass
09:26:11 Cleaf >>> JOIN #test
09:26:12 Cleaf >>> SAMODE #test +o Cleaf
09:26:12 Cfounder >>> JOIN #test
09:26:13 Cfounder >>> SAMODE #test +o Cfounder
09:26:13 Cfounder >>> PRIVMSG ChanServ :REGISTER #test chanpw Test channel
09:26:14 Cfounder >>> PRIVMSG ChanServ :SET #test TOPICLOCK ON
09:26:15 Cfounder >>> PRIVMSG ChanServ :SET #test KEEPTOPIC ON
09:26:15 Cfounder >>> TOPIC #test :T1-initial-from-Cfounder
09:26:18 Cfounder >>> PRIVMSG #test :MARKER_SCENARIO_START_3
09:26:19 Cleaf >>> SAMODE #test +o Cleaf
09:26:19 Cleaf >>> TOPIC #test :T3-attempted-change-during-normal-ops
09:26:24 Cfounder >>> PRIVMSG #test :MARKER_SCENARIO_END_3
09:26:26 Cfounder >>> TOPIC #test
09:20:12.703977 IP 172.30.1.2.7000 > 172.30.1.3.34734: Flags [P.], seq 3971501860:3971501997, ack 1542960431, win 32883, options [nop,nop,TS val 1740301323 ecr 1202598801], length 137
E...>L@.@............X....O$[../...sZ......
g...G.3.:hub.azzurra.chat GNOTICE :Received SQUIT leaf4.azzurra.chat from Cfounder[~u@0.0.0.0] (test-split)
SQUIT leaf4.azzurra.chat :test-split
09:20:12.703989 IP 172.30.1.3.34734 > 172.30.1.2.7000: Flags [.], ack 137, win 501, options [nop,nop,TS val 1202602558 ecr 1740301323], length 0
E..4m.@.@.r............X[../..O.....Zh.....
G.B>g...
09:20:17.703747 IP 172.30.1.2.7000 > 172.30.1.3.34734: Flags [P.], seq 137:228, ack 1, win 32883, options [nop,nop,TS val 1740306323 ecr 1202602558], length 91
E...>M@.@............X....O.[../...sZ......
g...G.B>:hub.azzurra.chat GNOTICE :Local CONNECT leaf4.azzurra.chat 7000 from Cfounder[~u@0.0.0.0]
09:20:17.703760 IP 172.30.1.3.34734 > 172.30.1.2.7000: Flags [.], ack 228, win 501, options [nop,nop,TS val 1202607558 ecr 1740306323], length 0
E..4m.@.@.r............X[../..P.....Zh.....
G.U.g...
09:20:17.704233 IP 172.30.1.2.7000 > 172.30.1.3.34734: Flags [P.], seq 228:644, ack 1, win 32883, options [nop,nop,TS val 1740306324 ecr 1202607558], length 416
E...>N@.@............X....P.[../...s\......
g...G.U.:hub.azzurra.chat GNOTICE :Link with leaf4.azzurra.chat[unknown@0.0.0.0] established: TS link
:hub.azzurra.chat SERVER leaf4.azzurra.chat 2 :Azzurra testnet leaf v4
:leaf4.azzurra.chat GNOTICE :Link with hub.azzurra.chat[unknown@0.0.0.0] established: TS link
NICK Cleaf 2 1776763204 +oix ~u 172.30.4.1 leaf4.azzurra.chat 140733193388032 93826448229377 :Test User
:leaf4.azzurra.chat SJOIN 1776763204 #test +r :Cleaf
09:20:17.704243 IP 172.30.1.3.34734 > 172.30.1.2.7000: Flags [.], ack 644, win 501, options [nop,nop,TS val 1202607559 ecr 1740306324], length 0
E..4m.@.@.r............X[../..Q.....Zh.....
G.U.g...
09:20:17.705654 IP 172.30.1.2.7000 > 172.30.1.3.34734: Flags [P.], seq 644:719, ack 1, win 32883, options [nop,nop,TS val 1740306325 ecr 1202607559], length 75
E...>O@.@............X....Q.[../...sZ......
g...G.U.:hub.azzurra.chat GNOTICE :leaf4.azzurra.chat has synched to network data.
09:20:17.705670 IP 172.30.1.3.34734 > 172.30.1.2.7000: Flags [.], ack 719, win 501, options [nop,nop,TS val 1202607560 ecr 1740306325], length 0
E..4m.@.@.r............X[../..Q.....Zh.....
G.U.g...
09:20:17.706534 IP 172.30.1.2.7000 > 172.30.1.3.34734: Flags [P.], seq 719:795, ack 1, win 32883, options [nop,nop,TS val 1740306326 ecr 1202607560], length 76
E...>P@.@............X....Q.[../...sZ......
g...G.U.:hub.azzurra.chat GNOTICE :synch to leaf4.azzurra.chat in 0 secs at 0 sendq
09:20:17.706545 IP 172.30.1.3.34734 > 172.30.1.2.7000: Flags [.], ack 795, win 501, options [nop,nop,TS val 1202607561 ecr 1740306326], length 0
E..4m.@.@.r............X[../..R?....Zh.....
G.U.g...
09:20:17.706614 IP 172.30.1.2.7000 > 172.30.1.3.34734: Flags [P.], seq 795:871, ack 1, win 32883, options [nop,nop,TS val 1740306326 ecr 1202607561], length 76
E...>Q@.@............X....R?[../...sZ......
g...G.U.:leaf4.azzurra.chat GNOTICE :synch to hub.azzurra.chat in 4 secs at 0 sendq
09:20:17.706619 IP 172.30.1.3.34734 > 172.30.1.2.7000: Flags [.], ack 871, win 501, options [nop,nop,TS val 1202607561 ecr 1740306326], length 0
E..4m.@.@.r............X[../..R.....Zh.....
G.U.g...
09:20:27.711553 IP 172.30.1.3.34734 > 172.30.1.2.7000: Flags [P.], seq 1:97, ack 871, win 501, options [nop,nop,TS val 1202617566 ecr 1740306326], length 96
E...m.@.@.r............X[../..R.....Z......
G.|.g...:NickServ NOTICE Cfounder :You now have 40 seconds to change your nick before I do it for you.
09:20:27.711597 IP 172.30.1.2.7000 > 172.30.1.3.34734: Flags [.], ack 97, win 32883, options [nop,nop,TS val 1740316331 ecr 1202617566], length 0
E..4>R@.@..0.........X....R.[......sZh.....
g...G.|.
09:20:47.728550 IP 172.30.1.3.34734 > 172.30.1.2.7000: Flags [P.], seq 97:193, ack 871, win 501, options [nop,nop,TS val 1202637583 ecr 1740316331], length 96
E...m.@.@.r............X[.....R.....Z......
G...g...:NickServ NOTICE Cfounder :You now have 20 seconds to change your nick before I do it for you.
09:20:47.728598 IP 172.30.1.2.7000 > 172.30.1.3.34734: Flags [.], ack 193, win 32883, options [nop,nop,TS val 1740336348 ecr 1202637583], length 0
E..4>S@.@../.........X....R.[......sZh.....
g.l.G...
09:21:07.747223 IP 172.30.1.3.34734 > 172.30.1.2.7000: Flags [P.], seq 193:298, ack 871, win 501, options [nop,nop,TS val 1202657602 ecr 1740336348], length 105
E...m.@.@.r............X[.....R.....Z......
G..Bg.l.:NickServ NOTICE Cfounder :Your nick has been changed because .Cfounder. is registered to another user.
09:21:07.747274 IP 172.30.1.2.7000 > 172.30.1.3.34734: Flags [.], ack 298, win 32883, options [nop,nop,TS val 1740356367 ecr 1202657602], length 0
E..4>T@.@............X....R.[..X...sZh.....
g...G..B
09:21:07.747411 IP 172.30.1.3.34734 > 172.30.1.2.7000: Flags [P.], seq 298:338, ack 871, win 501, options [nop,nop,TS val 1202657602 ecr 1740356367], length 40
E..\m.@.@.r............X[..X..R.....Z......
G..Bg...SVSNICK Cfounder Guest88806 1776763267
09:21:07.747430 IP 172.30.1.2.7000 > 172.30.1.3.34734: Flags [.], ack 338, win 32883, options [nop,nop,TS val 1740356367 ecr 1202657602], length 0
E..4>U@.@..-.........X....R.[......sZh.....
g...G..B
09:21:07.747476 IP 172.30.1.2.7000 > 172.30.1.3.34734: Flags [P.], seq 871:909, ack 338, win 32883, options [nop,nop,TS val 1740356367 ecr 1202657602], length 38
E..Z>V@.@............X....R.[......sZ......
g...G..B:Cfounder NICK Guest88806 :1776763267
09:21:07.747482 IP 172.30.1.3.34734 > 172.30.1.2.7000: Flags [.], ack 909, win 501, options [nop,nop,TS val 1202657602 ecr 1740356367], length 0
E..4m.@.@.r............X[.....R.....Zh.....
G..Bg...
09:21:07.747506 IP 172.30.1.3.34734 > 172.30.1.2.7000: Flags [P.], seq 338:455, ack 909, win 501, options [nop,nop,TS val 1202657602 ecr 1740356367], length 117
E...m.@.@.r|...........X[.....R.....Z......
G..Bg...NICK Cfounder 1 1776763267 +i enforcer azzurra.chat services.azzurra.chat 0 3221554673 :Nick Protection Enforcement
09:21:07.790202 IP 172.30.1.2.7000 > 172.30.1.3.34734: Flags [.], ack 455, win 32883, options [nop,nop,TS val 1740356410 ecr 1202657602], length 0
E..4>W@.@..+.........X....R.[......sZh.....
g..:G..B
09:17:51.219821 IP 172.30.1.2.7000 > 172.30.1.3.34734: Flags [P.], seq 3971500355:3971500446, ack 1542959262, win 32883, options [nop,nop,TS val 1740159839 ecr 1202446425], length 91
E...>)@.@............X....IC[......sZ......
g.._G..Y:hub.azzurra.chat GNOTICE :Local CONNECT leaf4.azzurra.chat 7000 from Cfounder[~u@0.0.0.0]
09:17:51.219836 IP 172.30.1.3.34734 > 172.30.1.2.7000: Flags [.], ack 91, win 501, options [nop,nop,TS val 1202461074 ecr 1740159839], length 0
E..4mg@.@.s............X[.....I.....Zh.....
G...g.._
09:17:51.220122 IP 172.30.1.2.7000 > 172.30.1.3.34734: Flags [P.], seq 91:508, ack 1, win 32883, options [nop,nop,TS val 1740159839 ecr 1202461074], length 417
E...>*@.@............X....I.[......s\ .....
g.._G...:hub.azzurra.chat GNOTICE :Link with leaf4.azzurra.chat[unknown@0.0.0.0] established: TS link
:hub.azzurra.chat SERVER leaf4.azzurra.chat 2 :Azzurra testnet leaf v4
:leaf4.azzurra.chat GNOTICE :Link with hub.azzurra.chat[unknown@0.0.0.0] established: TS link
NICK Cleaf 2 1776763052 +oix ~u 172.30.4.1 leaf4.azzurra.chat 140733193388032 93826448229377 :Test User
:leaf4.azzurra.chat SJOIN 1776763052 #test +r :@Cleaf
09:17:51.220129 IP 172.30.1.3.34734 > 172.30.1.2.7000: Flags [.], ack 508, win 501, options [nop,nop,TS val 1202461074 ecr 1740159839], length 0
E..4mh@.@.s............X[.....K?....Zh.....
G...g.._
09:17:51.220386 IP 172.30.1.3.34734 > 172.30.1.2.7000: Flags [P.], seq 1:59, ack 508, win 501, options [nop,nop,TS val 1202461075 ecr 1740159839], length 58
E..nmi@.@.r............X[.....K?....Z......
G...g.._:ChanServ NOTICE Cleaf :.#test. is a registered channel.
09:17:51.220391 IP 172.30.1.2.7000 > 172.30.1.3.34734: Flags [P.], seq 508:582, ack 1, win 32883, options [nop,nop,TS val 1740159840 ecr 1202461074], length 74
E..~>+@.@............X....K?[......sZ......
g..`G...:leaf4.azzurra.chat TOPIC #test Cleaf 1776763061 :T2-changed-during-split
09:17:51.220400 IP 172.30.1.2.7000 > 172.30.1.3.34734: Flags [.], ack 59, win 32883, options [nop,nop,TS val 1740159840 ecr 1202461075], length 0
E..4>,@.@..V.........X....K.[......sZh.....
g..`G...
09:17:51.220411 IP 172.30.1.3.34734 > 172.30.1.2.7000: Flags [P.], seq 59:90, ack 582, win 501, options [nop,nop,TS val 1202461075 ecr 1740159840], length 31
E..Smj@.@.r............X[.....K.....Z......
G...g..`:ChanServ MODE #test -o Cleaf
09:17:51.220420 IP 172.30.1.2.7000 > 172.30.1.3.34734: Flags [.], ack 90, win 32883, options [nop,nop,TS val 1740159840 ecr 1202461075], length 0
E..4>-@.@..U.........X....K.[......sZh.....
g..`G...
09:17:51.220747 IP 172.30.1.2.7000 > 172.30.1.3.34734: Flags [P.], seq 582:657, ack 90, win 32883, options [nop,nop,TS val 1740159840 ecr 1202461075], length 75
E...>.@.@.. .........X....K.[......sZ......
g..`G...:hub.azzurra.chat GNOTICE :leaf4.azzurra.chat has synched to network data.
09:17:51.262167 IP 172.30.1.3.34734 > 172.30.1.2.7000: Flags [.], ack 657, win 501, options [nop,nop,TS val 1202461117 ecr 1740159840], length 0
E..4mk@.@.s............X[.....K.....Zh.....
G...g..`
09:17:51.262258 IP 172.30.1.2.7000 > 172.30.1.3.34734: Flags [P.], seq 657:807, ack 90, win 32883, options [nop,nop,TS val 1740159882 ecr 1202461117], length 150
E...>/@.@............X....K.[......sZ......
g...G...:hub.azzurra.chat GNOTICE :synch to leaf4.azzurra.chat in 1 sec at 0 sendq
:leaf4.azzurra.chat GNOTICE :synch to hub.azzurra.chat in 1 sec at 0 sendq
09:17:51.262270 IP 172.30.1.3.34734 > 172.30.1.2.7000: Flags [.], ack 807, win 501, options [nop,nop,TS val 1202461117 ecr 1740159882], length 0
E..4ml@.@.s............X[.....Lj....Zh.....
G...g...
09:24:26.341689 IP 172.30.1.2.7000 > 172.30.1.3.32850: Flags [P.], seq 3837649652:3837649743, ack 2479870000, win 32870, options [nop,nop,TS val 1740554961 ecr 1202847553], length 91
E....~@.@.,..........X.R.......0...fZ......
g...G..A:hub.azzurra.chat GNOTICE :Local CONNECT leaf4.azzurra.chat 7000 from Cfounder[~u@0.0.0.0]
09:24:26.341698 IP 172.30.1.3.32850 > 172.30.1.2.7000: Flags [.], ack 91, win 501, options [nop,nop,TS val 1202856196 ecr 1740554961], length 0
E..48.@.@..k.........R.X...0...O....Zh.....
G.!.g...
09:24:26.342636 IP 172.30.1.2.7000 > 172.30.1.3.32850: Flags [P.], seq 91:503, ack 1, win 32870, options [nop,nop,TS val 1740554962 ecr 1202856196], length 412
E.....@.@.+g.........X.R...O...0...f\......
g...G.!.:hub.azzurra.chat GNOTICE :Link with leaf4.azzurra.chat[unknown@0.0.0.0] established: TS link
:hub.azzurra.chat SERVER leaf4.azzurra.chat 2 :Azzurra testnet leaf v4
:leaf4.azzurra.chat GNOTICE :Link with hub.azzurra.chat[unknown@0.0.0.0] established: TS link
NICK Cleaf 2 1776763453 +oix ~u 172.30.4.1 leaf4.azzurra.chat 93827855548416 2887648257 :Test User
:leaf4.azzurra.chat SJOIN 1776763453 #test +r :@Cleaf
09:24:26.342644 IP 172.30.1.3.32850 > 172.30.1.2.7000: Flags [.], ack 503, win 501, options [nop,nop,TS val 1202856197 ecr 1740554962], length 0
E..48.@.@..j.........R.X...0........Zh.....
G.!.g...
09:24:26.342719 IP 172.30.1.3.32850 > 172.30.1.2.7000: Flags [P.], seq 1:59, ack 503, win 501, options [nop,nop,TS val 1202856197 ecr 1740554962], length 58
E..n8.@.@../.........R.X...0........Z......
G.!.g...:ChanServ NOTICE Cleaf :.#test. is a registered channel.
09:24:26.342741 IP 172.30.1.2.7000 > 172.30.1.3.32850: Flags [.], ack 59, win 32870, options [nop,nop,TS val 1740554962 ecr 1202856197], length 0
E..4..@.@.-..........X.R.......j...fZh.....
g...G.!.
09:24:26.342752 IP 172.30.1.3.32850 > 172.30.1.2.7000: Flags [P.], seq 59:90, ack 503, win 501, options [nop,nop,TS val 1202856197 ecr 1740554962], length 31
E..S8.@.@..I.........R.X...j........Z......
G.!.g...:ChanServ MODE #test -o Cleaf
09:24:26.342761 IP 172.30.1.2.7000 > 172.30.1.3.32850: Flags [.], ack 90, win 32870, options [nop,nop,TS val 1740554962 ecr 1202856197], length 0
E..4..@.@.-..........X.R...........fZh.....
g...G.!.
09:24:26.342879 IP 172.30.1.2.7000 > 172.30.1.3.32850: Flags [P.], seq 503:578, ack 90, win 32870, options [nop,nop,TS val 1740554962 ecr 1202856197], length 75
E.....@.@.,..........X.R...........fZ......
g...G.!.:hub.azzurra.chat GNOTICE :leaf4.azzurra.chat has synched to network data.
09:24:26.386151 IP 172.30.1.3.32850 > 172.30.1.2.7000: Flags [.], ack 578, win 501, options [nop,nop,TS val 1202856241 ecr 1740554962], length 0
E..48.@.@..g.........R.X.......6....Zh.....
G.!1g...
09:24:26.386196 IP 172.30.1.2.7000 > 172.30.1.3.32850: Flags [P.], seq 578:729, ack 90, win 32870, options [nop,nop,TS val 1740555006 ecr 1202856241], length 151
E.....@.@.,h.........X.R...6.......fZ......
g...G.!1:hub.azzurra.chat GNOTICE :synch to leaf4.azzurra.chat in 0 secs at 0 sendq
:leaf4.azzurra.chat GNOTICE :synch to hub.azzurra.chat in 1 sec at 0 sendq
09:24:26.386205 IP 172.30.1.3.32850 > 172.30.1.2.7000: Flags [.], ack 729, win 501, options [nop,nop,TS val 1202856241 ecr 1740555006], length 0
E..48.@.@..f.........R.X............Zh.....
G.!1g...
09:16:28.925137 IP 172.30.1.2.7000 > 172.30.1.3.55718: Flags [P.], seq 1229049086:1229049177, ack 3565977534, win 32883, options [nop,nop,TS val 1740077544 ecr 1202364105], length 91
E.....@.@..0.........X..IA.........sZ......
g.y.G...:hub.azzurra.chat GNOTICE :Local CONNECT leaf4.azzurra.chat 7000 from Cfounder[~u@0.0.0.0]
09:16:28.925149 IP 172.30.1.3.55718 > 172.30.1.2.7000: Flags [.], ack 91, win 501, options [nop,nop,TS val 1202378780 ecr 1740077544], length 0
E..4.I@.@..9...........X....IA.Y....Zh.....
G...g.y.
09:16:28.925492 IP 172.30.1.2.7000 > 172.30.1.3.55718: Flags [P.], seq 91:507, ack 1, win 32883, options [nop,nop,TS val 1740077545 ecr 1202378780], length 416
E.....@.@............X..IA.Y.......s\......
g.y.G...:hub.azzurra.chat GNOTICE :Link with leaf4.azzurra.chat[unknown@0.0.0.0] established: TS link
:hub.azzurra.chat SERVER leaf4.azzurra.chat 2 :Azzurra testnet leaf v4
:leaf4.azzurra.chat GNOTICE :Link with hub.azzurra.chat[unknown@0.0.0.0] established: TS link
NICK Cleaf 2 1776762969 +oix ~u 172.30.4.1 leaf4.azzurra.chat 140733193388032 93826448229377 :Test User
:leaf4.azzurra.chat SJOIN 1776762969 #test + :@Cleaf
09:16:28.925500 IP 172.30.1.3.55718 > 172.30.1.2.7000: Flags [.], ack 507, win 501, options [nop,nop,TS val 1202378780 ecr 1740077545], length 0
E..4.J@.@..8...........X....IA......Zh.....
G...g.y.
09:16:28.925604 IP 172.30.1.3.55718 > 172.30.1.2.7000: Flags [P.], seq 1:59, ack 507, win 501, options [nop,nop,TS val 1202378780 ecr 1740077545], length 58
E..n.K@.@..............X....IA......Z......
G...g.y.:ChanServ NOTICE Cleaf :.#test. is a registered channel.
09:16:28.925628 IP 172.30.1.2.7000 > 172.30.1.3.55718: Flags [.], ack 59, win 32883, options [nop,nop,TS val 1740077545 ecr 1202378780], length 0
E..4..@.@............X..IA.........sZh.....
g.y.G...
09:16:28.925638 IP 172.30.1.3.55718 > 172.30.1.2.7000: Flags [P.], seq 59:90, ack 507, win 501, options [nop,nop,TS val 1202378780 ecr 1740077545], length 31
E..S.L@.@..............X....IA......Z......
G...g.y.:ChanServ MODE #test -o Cleaf
09:16:28.925647 IP 172.30.1.2.7000 > 172.30.1.3.55718: Flags [.], ack 90, win 32883, options [nop,nop,TS val 1740077545 ecr 1202378780], length 0
E..4..@.@............X..IA.........sZh.....
g.y.G...
09:16:28.925655 IP 172.30.1.3.55718 > 172.30.1.2.7000: Flags [P.], seq 90:115, ack 507, win 501, options [nop,nop,TS val 1202378780 ecr 1740077545], length 25
E..M.M@.@..............X....IA......Z......
G...g.y.:ChanServ MODE #test +r
09:16:28.925662 IP 172.30.1.2.7000 > 172.30.1.3.55718: Flags [.], ack 115, win 32883, options [nop,nop,TS val 1740077545 ecr 1202378780], length 0
E..4..@.@............X..IA.....0...sZh.....
g.y.G...
09:16:28.925732 IP 172.30.1.2.7000 > 172.30.1.3.55718: Flags [P.], seq 507:581, ack 115, win 32883, options [nop,nop,TS val 1740077545 ecr 1202378780], length 74
E..~..@.@..<.........X..IA.....0...sZ......
g.y.G...:leaf4.azzurra.chat TOPIC #test Cleaf 1776762976 :T2-changed-during-split
09:16:28.966159 IP 172.30.1.3.55718 > 172.30.1.2.7000: Flags [.], ack 581, win 501, options [nop,nop,TS val 1202378821 ecr 1740077545], length 0
E..4.N@.@..4...........X...0IA.C....Zh.....
G..Eg.y.
09:16:28.966228 IP 172.30.1.2.7000 > 172.30.1.3.55718: Flags [P.], seq 581:808, ack 115, win 32883, options [nop,nop,TS val 1740077586 ecr 1202378821], length 227
E.....@.@............X..IA.C...0...s[K.....
g.z.G..E:hub.azzurra.chat GNOTICE :leaf4.azzurra.chat has synched to network data.
:hub.azzurra.chat GNOTICE :synch to leaf4.azzurra.chat in 0 secs at 0 sendq
:leaf4.azzurra.chat GNOTICE :synch to hub.azzurra.chat in 3 secs at 0 sendq
09:16:28.966239 IP 172.30.1.3.55718 > 172.30.1.2.7000: Flags [.], ack 808, win 501, options [nop,nop,TS val 1202378821 ecr 1740077586], length 0
E..4.O@.@..3...........X...0IA.&....Zh.....
G..Eg.z.
09:16:28.966332 IP 172.30.1.3.55718 > 172.30.1.2.7000: Flags [P.], seq 115:184, ack 808, win 501, options [nop,nop,TS val 1202378821 ecr 1740077586], length 69
E..y.P@.@..............X...0IA.&....Z......
G..Eg.z.:ChanServ TOPIC #test Cfounder 1776762973 :T1-initial-from-Cfounder
09:16:29.010202 IP 172.30.1.2.7000 > 172.30.1.3.55718: Flags [.], ack 184, win 32883, options [nop,nop,TS val 1740077630 ecr 1202378821], length 0
E..4..@.@............X..IA.&...u...sZh.....
g.z>G..E

azzurra/services issue #1 — TOPIC doubling on netsplit heal

Empirical test of PR #13 (commit fe6a8c9) against baseline 96300ee (master pre-fix).

Bug

With +TOPICLOCK +KEEPTOPIC, after a netsplit heals, ChanServ used to emit up to two back-to-back TOPIC commands per channel:

  1. restore_topic() from chan_handle_SJOIN at channel re-creation.
  2. TOPICLOCK override in chan_handle_TOPIC server-branch when the same burst propagated the remote topic.

Both paths were gated only on synched == TRUE, not on per-server burst state. Fix introduces SERVER_FLAG_BURSTING check on both paths and defers reconciliation to a single synch_topics() call at m_gnotice "has synched to network data." EOB.

Testnet

docker compose (/tmp/infra-pr22/compose.yaml): hub.azzurra.chat, leaf4.azzurra.chat, leaf6.azzurra.chat, services.azzurra.chat. Services binary swapped between runs via /tmp/topic-test/compose.override.yaml bind-mount. Oper-initiated SQUIT/CONNECT simulates splits without restarting containers — leaf4's local channel/user/topic state is preserved and bursts to hub on heal, which is the exact path the bug lives on.

Pcap sniffer: tcpdump -U -i eth0 -A -s 0 tcp port 7000 run via a netshoot sidecar sharing services' netns (--net container:azzurra-services). This captures the hub↔services S2S link.

Clients:

  • Cfounder on hub (port 6667). Opered, registers NickServ, creates+registers #test, sets +TOPICLOCK +KEEPTOPIC, sets initial topic T1.
  • Cleaf on leaf4 (port 6668). Opered. Joins #test FIRST so the SJOIN TS is leaf4-owned and propagates to hub before Cfounder joins — both sides share the same TS, preserved across the split.

Scenarios

Scenario 1 — MATCH (no topic change across split)

SQUIT → wait → CONNECT. No topic change. Expected: 0 ChanServ TOPIC frames post-heal.

Binary ChanServ TOPIC frames Total TOPIC frames
baseline 0 0
fix 0 0

Fix does not introduce spurious TOPIC traffic when there is nothing to reconcile.

Scenario 2 — MISMATCH (topic changes during split) — the bug

SQUIT → Cleaf sets T2-changed-during-split locally on leaf4 → CONNECT (leaf4 bursts T2 to hub, hub forwards to services).

Binary ChanServ TOPIC frames Total TOPIC frames Final topic on channel
baseline 0 1 (T2 from leaf4) T2 (wrong — KEEPTOPIC+TOPICLOCK silently violated)
fix 1 (restores T1) 2 (T2 burst + ChanServ T1 restore) T1 (correct)

Scenario 3 — REGRESSION (normal TOPIC under lock, no split)

Non-founder op attempts TOPIC change on a TOPICLOCKed channel during normal operation. Sniffer on svc-net did not capture frames — Cleaf's local TOPIC was rejected at leaf4 before propagation (ChanServ auto-deops non-founder post-REGISTER; +t blocks non-ops). Regression verified instead by code inspection: the PR only adds an src_bursting gate on the server-source branch; non-burst paths are byte-for-byte identical to baseline. No functional change outside the burst window.

Evidence — pcap excerpts

fix / scenario 2 (pcap-fix-s2.txt, timestamps 09:16:28.*)

09:16:28.925137 GNOTICE :Local CONNECT leaf4.azzurra.chat 7000 from Cfounder[...]
09:16:28.925492 :hub.azzurra.chat SERVER leaf4.azzurra.chat 2 :Azzurra testnet leaf v4
                NICK Cleaf 2 1776762969 +oix ...
                :leaf4.azzurra.chat SJOIN 1776762969 #test + :@Cleaf
09:16:28.925604 :ChanServ NOTICE Cleaf :.#test. is a registered channel.
09:16:28.925638 :ChanServ MODE #test -o Cleaf            <-- TOPICLOCK enforcement (deop)
09:16:28.925655 :ChanServ MODE #test +r
09:16:28.925732 :leaf4.azzurra.chat TOPIC #test Cleaf 1776762976 :T2-changed-during-split   <-- burst T2 (deferred, not overridden inline)
09:16:28.966228 GNOTICE :leaf4.azzurra.chat has synched to network data.   <-- EOB, BURSTING cleared
09:16:28.966332 :ChanServ TOPIC #test Cfounder 1776762973 :T1-initial-from-Cfounder   <-- synch_topics() restore

One ChanServ TOPIC, emitted after EOB by synch_topics(). ci->last_topic (T1) was preserved through the burst because record_topic() was gated by src_bursting.

baseline / scenario 2 (pcap-baseline-s2.txt, timestamps 09:17:51.*)

09:17:51.219821 GNOTICE :Local CONNECT leaf4.azzurra.chat 7000 from Cfounder[...]
09:17:51.220122 :hub.azzurra.chat SERVER leaf4.azzurra.chat 2 :Azzurra testnet leaf v4
                NICK Cleaf 2 1776763052 +oix ...
                :leaf4.azzurra.chat SJOIN 1776763052 #test +r :@Cleaf
09:17:51.220386 :ChanServ NOTICE Cleaf :.#test. is a registered channel.
09:17:51.220391 :leaf4.azzurra.chat TOPIC #test Cleaf 1776763061 :T2-changed-during-split
09:17:51.220411 :ChanServ MODE #test -o Cleaf
09:17:51.220747 GNOTICE :leaf4.azzurra.chat has synched to network data.
                                                                            <-- NO ChanServ TOPIC restore

Zero ChanServ TOPIC restore. The baseline path called record_topic() on the remote TOPIC during burst, overwriting ci->last_topic = T2. By the time EOB fires, there's no mismatch to reconcile — T2 wins silently. TOPICLOCK + KEEPTOPIC were silently bypassed.

(Historical issue #1 described this as "TOPIC set twice" — i.e. the other failure mode where restore_topic() fires at SJOIN and the TOPICLOCK override fires at TOPIC — in this run only one of the two paths visibly broke, but both are gated by the same fix.)

Client commands (fix / scenario 2 — identical for baseline)

09:16:08 Cfounder >>> OPER testoper testoperpass
09:16:08 Cfounder >>> PRIVMSG NickServ :REGISTER secretpw x@x.com
09:16:09 Cleaf    >>> OPER testoper testoperpass
09:16:10 Cleaf    >>> JOIN #test                           # chan created on leaf4 side; SJOIN → hub with leaf4 TS
09:16:11 Cleaf    >>> SAMODE #test +o Cleaf
09:16:11 Cfounder >>> JOIN #test                           # hub joins existing chan, same TS
09:16:11 Cfounder >>> SAMODE #test +o Cfounder
09:16:12 Cfounder >>> PRIVMSG ChanServ :REGISTER #test chanpw Test channel
09:16:13 Cfounder >>> PRIVMSG ChanServ :SET #test TOPICLOCK ON
09:16:13 Cfounder >>> PRIVMSG ChanServ :SET #test KEEPTOPIC ON
09:16:14 Cfounder >>> TOPIC #test :T1-initial-from-Cfounder
09:16:16 Cfounder >>> PRIVMSG #test :MARKER_SCENARIO_START_2
09:16:17 Cfounder >>> SQUIT leaf4.azzurra.chat :test-split
09:16:20 Cleaf    >>> TOPIC #test :T2-changed-during-split    # during split, leaf4 local state only
09:16:22 Cleaf    >>> TOPIC #test                              # verify leaf4 sees T2
09:16:28 Cfounder >>> CONNECT leaf4.azzurra.chat 7000 hub.azzurra.chat
09:16:43 Cfounder >>> PRIVMSG #test :MARKER_SCENARIO_END_2
09:16:46 Cfounder >>> TOPIC #test                              # query final state

Scenarios 1 and 3 use the same setup minus the post-START behavior; full traces in cmds-{tag}-s{1,2,3}.txt.

TL;DR

Scenario Baseline Fix Verdict
1 MATCH 0 CS TOPIC (correct) 0 CS TOPIC (correct) fix: no regression
2 MISMATCH 0 CS TOPIC, T2 wins (bug) 1 CS TOPIC, T1 restored at EOB bug fixed
3 REGRESSION n/a — code-audit only: non-burst path unchanged n/a fix: no regression

PR #13 can merge.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment