Currently, the user nickname is recorded in the connection object when `connect' is called. Unfortunately, if it happens that the nickname used to connect is already taken, err_nicknameinuse is received and the connection is not established (yet).
The thing to do to handle this, is to issue a `nick' command in err_nicknameinuse to pick a different nickname.
The problem is that such a case, even if a NICK request was sent (and might or not be successful), there's no NICK reply sent by the server, because all of this happens before the welcome message has been sent. Therefore, the connection object as a wrong value for the user nickname (the one issued the first time, not the one actually negotiated).
Consequently, functions such as `self-message-p' don't work correctly, and everything is just mess and chaos.
To fix this, this patch stop registering the nickname at `connect' time, but does it as soon as the welcome message is received. That way, it is sure that the connection stores the real nickname, not the one asked for the first time.
Signed-off-by: Julien Danjou julien@danjou.info --- command.lisp | 7 +------ event.lisp | 13 +++++++++++++ protocol.lisp | 1 + 3 files changed, 15 insertions(+), 6 deletions(-)
diff --git a/command.lisp b/command.lisp index c0277fc..aac445b 100644 --- a/command.lisp +++ b/command.lisp @@ -296,13 +296,8 @@ connect to. `connection-security' determines which port number is found. :socket socket :network-stream stream :client-stream logging-stream - :server-name server)) - (user (make-user connection - :nickname nickname - :username username - :realname realname))) + :server-name server))) #+sbcl (setf (sb-bsd-sockets::sockopt-keep-alive (usocket:socket socket)) t) - (setf (user connection) user) (unless (null password) (pass connection password)) (nick connection nickname) diff --git a/event.lisp b/event.lisp index 3b99d4a..eb97fc9 100644 --- a/event.lisp +++ b/event.lisp @@ -141,6 +141,19 @@ objects in sync.")) (username user) username (hostname user) hostname)))))
+(defmethod default-hook ((message irc-rpl_welcome-message)) + (with-slots + (connection host user arguments) + message + (destructuring-bind + (nickname welcome-message) + arguments + (setf (user connection) + (make-user connection + :nickname nickname + :hostname host + :username user))))) + (defmethod default-hook ((message irc-rpl_list-message)) (destructuring-bind (channel count topic) diff --git a/protocol.lisp b/protocol.lisp index b464697..1c2ec19 100644 --- a/protocol.lisp +++ b/protocol.lisp @@ -246,6 +246,7 @@ connection.") irc-rpl_topic-message irc-rpl_namreply-message irc-rpl_endofnames-message + irc-rpl_welcome-message irc-ping-message irc-join-message irc-topic-message