From: Magnus H. <leg...@us...> - 2013-06-30 17:16:44
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "emacs-jabber". The branch, master has been updated via 05340c6ad725a701dd7d157938263906977e4714 (commit) from 2999f58619dd9c20cc6cac8060c4c850a504cbbd (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 05340c6ad725a701dd7d157938263906977e4714 Author: Magnus Henoch <mag...@gm...> Date: Sun Jun 30 18:15:49 2013 +0100 Perform asynchronous connection if possible When using native GnuTLS, we can now connect asynchronously, without blocking Emacs if the remote server is slow to accept the connection (or just times out). Such connections are now identical to "network" (i.e. TLS-less) connections, so I reverted jabber-starttls-connect to its previous state: it is now used exclusively to connect using gnutls-cli external processes. diff --git a/jabber-conn.el b/jabber-conn.el index a22f88b..307051b 100644 --- a/jabber-conn.el +++ b/jabber-conn.el @@ -88,8 +88,14 @@ or later." :group 'jabber-conn) (defvar jabber-connect-methods - '((network jabber-network-connect jabber-network-send) - (starttls jabber-starttls-connect jabber-network-send) + `((network jabber-network-connect jabber-network-send) + (starttls + ,(if (and (fboundp 'gnutls-available-p) + (gnutls-available-p)) + ;; With "native" TLS, we can use a normal connection. + 'jabber-network-connect + 'jabber-starttls-connect) + jabber-network-send) (ssl jabber-ssl-connect jabber-ssl-send) (virtual jabber-virtual-connect jabber-virtual-send)) "Alist of connection methods and functions. @@ -128,7 +134,60 @@ If we can't find SRV records, use standard defaults." Send a message of the form (:connected CONNECTION) to FSM if connection succeeds. Send a message :connection-failed if connection fails." - ;; XXX: asynchronous connection + (cond + ((featurep 'make-network-process '(:nowait t)) + ;; We can connect asynchronously! + (jabber-network-connect-async fsm server network-server port)) + (t + ;; Connecting to the server will block Emacs. + (jabber-network-connect-sync fsm server network-server port)))) + +(defun jabber-network-connect-async (fsm server network-server port) + ;; Get all potential targets... + (lexical-let ((targets (jabber-srv-targets server network-server port)) + (fsm fsm)) + ;; ...and connect to them one after another, asynchronously, until + ;; connection succeeds. + (labels + ((connect + (target remaining-targets) + (make-network-process + :name "jabber" + :buffer (generate-new-buffer jabber-process-buffer) + :host (car target) :service (cdr target) + :coding 'utf-8 + :nowait t + :sentinel + (lexical-let ((target target) (remaining-targets remaining-targets)) + (lambda (connection status) + (cond + ((string-match "^open" status) + ;; This mustn't be `fsm-send-sync', because the FSM + ;; needs to change the sentinel, which cannot be done + ;; from inside the sentinel. + (fsm-send fsm (list :connected connection))) + ((string-match "^failed" status) + (message "Couldn't connect to %s:%s" (car target) (cdr target)) + (delete-process connection) + (if remaining-targets + (progn + (message + "Connecting to %s:%s..." + (caar remaining-targets) (cdar remaining-targets)) + (connect (car remaining-targets) (cdr remaining-targets))) + (fsm-send fsm :connection-failed))) + ((string-match "^deleted" status) + ;; This happens when we delete a process in the + ;; "failed" case above. + nil) + (t + (message "Unknown sentinel status `%s'" status)))))))) + (message "Connecting to %s:%s..." (caar targets) (cdar targets)) + (connect (car targets) (cdr targets))))) + +(defun jabber-network-connect-sync (fsm server network-server port) + ;; This code will AFAIK only be used on Windows. Apologies in + ;; advance for any bit rot... (let ((coding-system-for-read 'utf-8) (coding-system-for-write 'utf-8) (targets (jabber-srv-targets server network-server port))) @@ -205,25 +264,15 @@ connection fails." (process-send-string connection "\n")) (defun jabber-starttls-connect (fsm server network-server port) - "Connect via GnuTLS to a Jabber Server. + "Connect via an external GnuTLS process to a Jabber Server. Send a message of the form (:connected CONNECTION) to FSM if connection succeeds. Send a message :connection-failed if connection fails." (let ((coding-system-for-read 'utf-8) (coding-system-for-write 'utf-8) - (targets (jabber-srv-targets server network-server port)) - (connect-function - (cond - ((and (fboundp 'gnutls-available-p) - (gnutls-available-p)) - (lambda (buffer host port) - (open-network-stream "jabber" buffer host port))) - ((fboundp 'starttls-open-stream) - (lambda (buffer host port) - (starttls-open-stream "jabber" buffer host port))) - (t - (error "Neither native GnuTLS nor starttls.el available"))))) - + (targets (jabber-srv-targets server network-server port))) + (unless (fboundp 'starttls-open-stream) + (error "starttls.el not available")) (catch 'connected (dolist (target targets) (condition-case e @@ -231,10 +280,11 @@ connection fails." connection) (unwind-protect (setq connection - (funcall connect-function - process-buffer - (car target) - (cdr target))) + (starttls-open-stream + "jabber" + process-buffer + (car target) + (cdr target))) (unless (or connection jabber-debug-keep-process-buffers) (kill-buffer process-buffer))) (when connection ----------------------------------------------------------------------- Summary of changes: jabber-conn.el | 92 +++++++++++++++++++++++++++++++++++++++++++------------- 1 files changed, 71 insertions(+), 21 deletions(-) hooks/post-receive -- emacs-jabber |