Deduplicate NICK and QUIT messages

This commit is contained in:
Tony Garnock-Jones 2017-08-01 18:56:05 -04:00
parent 75aee96e1a
commit 24ac40b251
2 changed files with 27 additions and 22 deletions

View File

@ -1,12 +1,3 @@
If two connections, A and B, exist, and
- A and B are both in #room1
- A and B are both in #room2
- A renames itself to A'
then B receives two ":A NICK A'" messages. This shouldn't happen.
A similar problem occurs for ":B QUIT" messages when A is in two
channels that B is also in, and B disconnects.
When A is a member of #room1, which has B and C in it, and A When A is a member of #room1, which has B and C in it, and A
disconnects, the session code futilely sends ":B PART #room1" and ":C disconnects, the session code futilely sends ":B PART #room1" and ":C
PART #room1", even though the connection is now gone. PART #room1", even though the connection is now gone.

View File

@ -10,6 +10,7 @@
(require/activate syndicate/drivers/tcp) (require/activate syndicate/drivers/tcp)
(require/activate syndicate/drivers/line-reader) (require/activate syndicate/drivers/line-reader)
(require syndicate/protocol/advertise) (require syndicate/protocol/advertise)
(require syndicate/support/hash)
(define (ircd-connection-facet this-conn server-handle) (define (ircd-connection-facet this-conn server-handle)
(define (send-to-remote #:newline [with-newline #t] fmt . vs) (define (send-to-remote #:newline [with-newline #t] fmt . vs)
@ -41,29 +42,42 @@
(for [(line motd-lines)] (send* 372 (nick) #:trailing (format "- ~a" line))) (for [(line motd-lines)] (send* 372 (nick) #:trailing (format "- ~a" line)))
(send* 376 (nick) #:trailing (format "End of /MOTD command")))))) (send* 376 (nick) #:trailing (format "End of /MOTD command"))))))
(field [peer-common-channels (hash)]
[peer-names (hash)])
(during (ircd-channel-member $Ch this-conn) (during (ircd-channel-member $Ch this-conn)
(field [initial-names-sent? #f] (field [initial-names-sent? #f]
[initial-member-nicks (set)]) [initial-member-nicks (set)])
(during (ircd-channel-member Ch $other-conn) (during (ircd-channel-member Ch $other-conn)
(on-start (peer-common-channels (hashset-add (peer-common-channels) other-conn Ch)))
(on-stop (peer-common-channels (hashset-remove (peer-common-channels) other-conn Ch)))
(field [current-other-source #f]) (field [current-other-source #f])
(define/query-value next-other-source #f (define/query-value next-other-source #f
(ircd-connection-info other-conn $N $U) (ircd-connection-info other-conn $N $U)
(irc-source-nick N U)) (irc-source-nick N U))
(on-stop (when (current-other-source) (send* #:source (current-other-source) "PART" Ch))) (on-stop
(when (current-other-source) (send* #:source (current-other-source) "PART" Ch))
(when (not (hash-has-key? (peer-common-channels) other-conn))
(peer-names (hash-remove (peer-names) other-conn))))
(begin/dataflow (begin/dataflow
(when (not (equal? (current-other-source) (next-other-source))) (when (not (equal? (current-other-source) (next-other-source)))
(cond (if (not (next-other-source)) ;; other-conn is disconnecting
[(not (next-other-source)) ;; other-conn is disconnecting (when (hash-ref (peer-names) other-conn #f)
(send* #:source (current-other-source) "QUIT")] (send* #:source (current-other-source) "QUIT")
[(not (initial-names-sent?)) ;; still gathering data for 353/366 below (peer-names (hash-remove (peer-names) other-conn)))
(initial-member-nicks (set-add (initial-member-nicks) (begin
(irc-source-nick-nick (next-other-source))))] (cond
[(not (current-other-source)) ;; other-conn is joining [(not (initial-names-sent?)) ;; still gathering data for 353/366 below
(send* #:source (next-other-source) "JOIN" Ch)] (initial-member-nicks (set-add (initial-member-nicks)
[else ;; it's a nick change (irc-source-nick-nick (next-other-source))))]
(when (not (equal? this-conn other-conn)) ;; avoid dups for our own connection [(not (current-other-source)) ;; other-conn is joining
(send* #:source (current-other-source) "NICK" (send* #:source (next-other-source) "JOIN" Ch)]
(irc-source-nick-nick (next-other-source))))]) [else ;; it's a nick change
(when (not (equal? this-conn other-conn)) ;; avoid dups for our own connection
(when (not (equal? (next-other-source) (hash-ref (peer-names) other-conn #f)))
(send* #:source (current-other-source) "NICK"
(irc-source-nick-nick (next-other-source)))))])
(peer-names (hash-set (peer-names) other-conn (next-other-source)))))
(current-other-source (next-other-source))))) (current-other-source (next-other-source)))))
(on (asserted (ircd-channel-topic Ch $topic)) (on (asserted (ircd-channel-topic Ch $topic))
(if topic (if topic