Update of /project/beirc/cvsroot/beirc
In directory clnet:/tmp/cvs-serv25758
Modified Files:
application.lisp message-display.lisp message-processing.lisp
receivers.lisp
Log Message:
Add "reconnect" support.
* notices when connections are dropped
* offers to reconnect when the connection is dropped.
* connection setup now believes in reconnecting.
--- /project/beirc/cvsroot/beirc/application.lisp 2006/04/07 01:42:56 1.75
+++ /project/beirc/cvsroot/beirc/application.lisp 2006/04/12 18:27:16 1.76
@@ -374,9 +374,8 @@
(make-instance 'bar-event :sheet frame))
(sleep 1)))
-(defun join-missing-channels (frame)
- (let* ((connection (current-connection frame))
- (server (when connection (irc:server-name connection))))
+(defun join-missing-channels (frame &optional (connection (current-connection frame)))
+ (let* ((server (when connection (irc:server-name connection))))
(when server
(loop for join-channel in (cdr (assoc server *auto-join-alist* :test #'equal))
do (unless (gethash join-channel (receivers frame))
@@ -890,15 +889,20 @@
(nick 'string :prompt "Nick name" :default *default-nick*)
(pass 'string :prompt "Password" :default nil)
(port 'number :prompt "Port" :default irc::*default-irc-server-port*))
- (let ((success nil))
- (or (server-receiver-from-args *application-frame* server port nick)
+ (let ((success nil)
+ (maybe-server-receiver (server-receiver-from-args *application-frame* server port nick)))
+ (or (and maybe-server-receiver (connection-open-p maybe-server-receiver))
(let* ((frame *application-frame*)
(connection (apply #'irc:connect
:nickname nick :server server :connection-type 'beirc-connection :port port
(if (null pass)
nil
`(:password ,pass))))
- (server-receiver (intern-receiver (format nil "~A on ~A:~A" nick server port) connection frame)))
+ (server-receiver (if maybe-server-receiver
+ (prog1 maybe-server-receiver
+ (reinit-receiver-for-new-connection maybe-server-receiver
+ connection))
+ (intern-receiver (format nil "~A on ~A:~A" nick server port) connection frame))))
(unwind-protect
(progn
(setf (irc:client-stream connection) (make-broadcast-stream))
@@ -1030,13 +1034,17 @@
(command
(save-input-line stream frame)
object)))
- (window-clear stream)))
+ (window-clear stream)))
(defun irc-event-loop (frame connection)
- (unwind-protect
- (let ((*application-frame* frame))
- (irc:read-message-loop connection))
- (irc:remove-all-hooks connection)))
+ (let ((*application-frame* frame))
+ (unwind-protect (irc:read-message-loop connection)
+ (setf (connection-open-p (server-receiver frame connection)) nil)
+ (irc:remove-all-hooks connection)
+ (irc:irc-message-event connection
+ (make-fake-irc-message 'irc-connection-closed-message
+ :command "Connnection closed"
+ :source (irc:server-name connection))))))
;;; Hack:
--- /project/beirc/cvsroot/beirc/message-display.lisp 2006/04/02 20:51:54 1.45
+++ /project/beirc/cvsroot/beirc/message-display.lisp 2006/04/12 18:27:16 1.46
@@ -494,6 +494,14 @@
(with-drawing-options (*standard-output* :ink +grey12+ :text-size :small)
(format-message* "Click here to close this tab."))))
+(defun offer-reconnect (receiver)
+ (let* ((conn (connection receiver))
+ (server (irc:server-name conn))
+ (nickname (irc:nickname (irc:user conn))))
+ (with-output-as-presentation (t `(com-connect ,server :nick ,nickname) 'command)
+ (with-drawing-options (*standard-output* :ink +grey12+ :text-size :small)
+ (format-message* (format nil "Click here to reconnect to ~A as ~A" server nickname))))))
+
(defmethod print-message ((message irc:irc-err_nosuchnick-message) receiver)
(formatting-message (t message receiver)
((format t " "))
@@ -672,6 +680,13 @@
(irc:irc-rpl_invitelist-message "INVITED: ")
(irc:irc-rpl_exceptlist-message "UNBANNED: ")))
+(defmethod print-message ((message irc-connection-closed-message) receiver)
+ (formatting-message (t message receiver)
+ ((format t " "))
+ ((with-drawing-options (*standard-output* :ink +red3+)
+ (format-message* "Connection to server closed.")
+ (offer-reconnect receiver)))))
+
;;; the display function (& utilities)
(defgeneric preamble-length (message)
--- /project/beirc/cvsroot/beirc/message-processing.lisp 2006/04/04 18:37:28 1.7
+++ /project/beirc/cvsroot/beirc/message-processing.lisp 2006/04/12 18:27:16 1.8
@@ -71,5 +71,4 @@
(define-beirc-hook autojoin-hoook ((message cl-irc:irc-rpl_welcome-message))
"When a connection is established, check the list of channels for autojoin
and set them up accordingly."
- (declare (ignore message))
- (join-missing-channels *application-frame*))
+ (join-missing-channels *application-frame* (irc:connection message)))
--- /project/beirc/cvsroot/beirc/receivers.lisp 2006/04/11 22:28:58 1.26
+++ /project/beirc/cvsroot/beirc/receivers.lisp 2006/04/12 18:27:16 1.27
@@ -9,7 +9,8 @@
(messages-directed-to-me :accessor messages-directed-to-me :initform 0)
(channel :reader channel :initform nil :initarg :channel)
(connection :accessor connection :initarg :connection)
- (query :reader query :initform nil :initarg :query) ;; <- XXX: remove this.
+ (connection-open-p :accessor connection-open-p :initform t) ; used only on server receivers.
+ (query :reader query :initform nil :initarg :query)
(focused-nicks :accessor focused-nicks :initform nil)
(title :reader title :initarg :title)
(last-visited :accessor last-visited :initform 0)
@@ -18,6 +19,8 @@
(pane :reader pane)
(tab-pane :accessor tab-pane)))
+(defclass irc-connection-closed-message (irc:irc-message) ())
+
(defun slot-value-or-something (object &key (slot 'name) (something "without name"))
(if (slot-boundp object slot)
(slot-value object slot)
@@ -107,6 +110,23 @@
(setf (gethash (list connection normalized-name) (receivers frame)) receiver)
receiver))))
+(defun reinit-receiver-for-new-connection (server-receiver connection &optional (frame *application-frame*))
+ (let ((old-connection (connection server-receiver)))
+ (maphash (lambda (key receiver)
+ (destructuring-bind (rec-connection name) key
+ (when (eql old-connection rec-connection)
+ (remhash key (receivers frame))
+ (setf (gethash (list connection name) (receivers frame)) receiver)
+ (setf (connection receiver) connection)
+ (dolist (message (messages receiver))
+ ;; KLUDGE: reset the connection of messages so
+ ;; that channel/user finding queries don't fail
+ ;; horribly
+ (setf (irc:connection message) connection)))
+ (write-char #\Newline *debug-io*)))
+ (receivers frame))))
+
+
(defun remove-receiver (receiver frame)
(tab-layout:remove-pane (tab-pane receiver)
(find-pane-named frame 'query))
@@ -256,7 +276,6 @@
cl-irc:irc-rpl_endofexceptlist-message
cl-irc:irc-ping-message))
-
;;; default receiver.
(defmethod receiver-for-message ((message irc:irc-message) frame)
#+or ; comment out to debug on uncaught messages.