Revision: mange@freemail.hu--2005/emacs-jabber--cvs-head--0--patch-294

Creator:  Magnus Henoch <mange@freemail.hu>

Multiaccountify file transfer
This commit is contained in:
Magnus Henoch 2007-02-07 13:49:38 +00:00 committed by Kirill A. Korinskiy
parent 97a9ce73d2
commit 316e9440f3
5 changed files with 52 additions and 38 deletions

View File

@ -25,9 +25,10 @@
(require 'jabber-ft-common)
(defun jabber-ft-send (jid filename desc)
(defun jabber-ft-send (jc jid filename desc)
"Attempt to send FILENAME to JID."
(interactive (list (jabber-read-jid-completing "Send file to: " nil nil nil 'full)
(interactive (list (jabber-read-account)
(jabber-read-jid-completing "Send file to: " nil nil nil 'full)
(read-file-name "Send which file: " nil nil t)
(jabber-read-with-input-method "Description (optional): ")))
(if (zerop (length desc)) (setq desc nil))
@ -38,7 +39,7 @@
(size (nth 7 attributes))
(date (nth 5 attributes))
(hash (jabber-ft-get-md5 filename)))
(jabber-si-initiate jid "http://jabber.org/protocol/si/profile/file-transfer"
(jabber-si-initiate jc jid "http://jabber.org/protocol/si/profile/file-transfer"
`(file ((xmlns . "http://jabber.org/protocol/si/profile/file-transfer")
(name . ,(file-name-nondirectory filename))
(size . ,size)
@ -47,7 +48,7 @@
(list (cons 'hash hash))))
(desc () ,desc))
(lexical-let ((filename filename))
(lambda (jid sid send-data-function)
(lambda (jc jid sid send-data-function)
(jabber-ft-do-send
jid sid send-data-function filename))))))

View File

@ -35,7 +35,7 @@
'jabber-ft-accept
'jabber-ft-server-connected))
(defun jabber-ft-accept (xml-data)
(defun jabber-ft-accept (jc xml-data)
"Receive IQ stanza containing file transfer request, ask user"
(let* ((from (jabber-xml-get-attribute xml-data 'from))
(query (jabber-iq-query xml-data))
@ -86,7 +86,7 @@
;; to support range, return something sensible here
nil))
(defun jabber-ft-server-connected (jid sid send-data-function)
(defun jabber-ft-server-connected (jc jid sid send-data-function)
;; We don't really care about the send-data-function. But if it's
;; a string, it means that we have no connection.
(if (stringp send-data-function)
@ -94,7 +94,7 @@
;; On success, we just return our data receiving function.
'jabber-ft-data))
(defun jabber-ft-data (jid sid data)
(defun jabber-ft-data (jc jid sid data)
"Receive chunk of transferred file."
(let ((buffer (cdr (assoc (list sid jid) jabber-ft-sessions))))
(with-current-buffer buffer

View File

@ -23,7 +23,7 @@
(require 'jabber-si-common)
(defun jabber-si-initiate (jid profile-namespace profile-data profile-function &optional mime-type)
(defun jabber-si-initiate (jc jid profile-namespace profile-data profile-function &optional mime-type)
"Try to initiate a stream to JID.
PROFILE-NAMESPACE is, well, the namespace of the profile to use.
PROFILE-DATA is the XML data to send within the SI request.
@ -33,7 +33,7 @@ MIME-TYPE is the MIME type to specify.
Returns the SID."
(let ((sid (apply 'format "emacs-sid-%d.%d.%d" (current-time))))
(jabber-send-iq jid "set"
(jabber-send-iq jc jid "set"
`(si ((xmlns . "http://jabber.org/protocol/si")
(id . ,sid)
,(if mime-type
@ -50,7 +50,7 @@ Returns the SID."
#'jabber-report-success "Stream initiation")
sid))
(defun jabber-si-initiate-process (xml-data closure-data)
(defun jabber-si-initiate-process (jc xml-data closure-data)
"Act on response to our SI query."
(let* ((profile-function (car closure-data))
@ -63,7 +63,7 @@ Returns the SID."
(method-data (assoc chosen-method jabber-si-stream-methods)))
;; Our work is done. Hand it over to the stream method.
(let ((stream-negotiate (nth 1 method-data)))
(funcall stream-negotiate from sid profile-function))))
(funcall stream-negotiate jc from sid profile-function))))
(provide 'jabber-si-client)

View File

@ -41,7 +41,7 @@ Each entry is a list, containing:
(add-to-list 'jabber-iq-set-xmlns-alist
(cons "http://jabber.org/protocol/si" 'jabber-si-process))
(defun jabber-si-process (xml-data)
(defun jabber-si-process (jc xml-data)
(let* ((to (jabber-xml-get-attribute xml-data 'from))
(id (jabber-xml-get-attribute xml-data 'id))
@ -76,9 +76,9 @@ Each entry is a list, containing:
(stream-data (assoc stream-method-id jabber-si-stream-methods))
(stream-accept-function (nth 2 stream-data)))
;; prepare stream for the transfer
(funcall stream-accept-function to si-id profile-connected-function)
(funcall stream-accept-function jc to si-id profile-connected-function)
;; return result of feature negotiation of stream type
(jabber-send-iq to "result"
(jabber-send-iq jc to "result"
`(si ((xmlns . "http://jabber.org/protocol/si"))
,@profile-response
(feature ((xmlns . "http://jabber.org/protocol/feature-neg"))

View File

@ -72,23 +72,23 @@ This is the set function of `jabber-socks5-proxies-data'."
(when *jabber-connected*
(jabber-socks5-query-all-proxies)))
(defun jabber-socks5-query-all-proxies (&optional callback)
(defun jabber-socks5-query-all-proxies (jc &optional callback)
"Ask all proxies in `jabber-socks5-proxies' for connection information.
If CALLBACK is non-nil, call it with no arguments when all
proxies have answered."
(interactive)
(interactive (list (jabber-read-account)))
(setq jabber-socks5-proxies-data nil)
(dolist (proxy jabber-socks5-proxies)
(jabber-socks5-query-proxy proxy callback)))
(jabber-socks5-query-proxy jc proxy callback)))
(defun jabber-socks5-query-proxy (jid &optional callback)
(defun jabber-socks5-query-proxy (jc jid &optional callback)
"Query the SOCKS5 proxy specified by JID for IP and port number."
(jabber-send-iq jid "get"
(jabber-send-iq jc jid "get"
'(query ((xmlns . "http://jabber.org/protocol/bytestreams")))
#'jabber-socks5-process-proxy-response (list callback t)
#'jabber-socks5-process-proxy-response (list callback nil)))
(defun jabber-socks5-process-proxy-response (xml-data closure-data)
(defun jabber-socks5-process-proxy-response (jc xml-data closure-data)
"Process response from proxy query."
(let* ((query (jabber-iq-query xml-data))
(from (jabber-xml-get-attribute xml-data 'from))
@ -111,13 +111,14 @@ proxies have answered."
(funcall callback)))))
(define-state-machine jabber-socks5
:start ((jid sid profile-function role)
:start ((jc jid sid profile-function role)
"Start JEP-0065 bytestream with JID.
SID is the session ID used.
PROFILE-FUNCTION is the function to call upon success. See `jabber-si-stream-methods'.
ROLE is either :initiator or :target. The initiator sends an IQ
set; the target waits for one."
(let ((new-state-data (list :jid jid
(let ((new-state-data (list :jc jc
:jid jid
:sid sid
:profile-function profile-function
:role role))
@ -144,8 +145,9 @@ set; the target waits for one."
(define-enter-state jabber-socks5 seek-proxies (fsm state-data)
;; Look for items at the server.
(jabber-disco-get-items jabber-server nil
(lambda (fsm result)
(jabber-disco-get-items (plist-get state-data :jc)
jabber-server nil
(lambda (jc fsm result)
(fsm-send-sync fsm (cons :items result)))
fsm)
;; Spend no more than five seconds looking for a proxy.
@ -168,8 +170,9 @@ set; the target waits for one."
(when (null (aref entry 2))
(lexical-let ((jid (aref entry 1)))
(jabber-disco-get-info
(plist-get state-data :jc)
jid nil
(lambda (fsm result)
(lambda (jc fsm result)
(fsm-send-sync fsm (list :info jid result)))
fsm))))
;; Remember number of requests sent. But if none, we just go on.
@ -205,8 +208,9 @@ set; the target waits for one."
(define-enter-state jabber-socks5 query-proxies (fsm state-data)
(jabber-socks5-query-all-proxies
(lexical-let ((fsm fsm))
(lambda () (fsm-send-sync fsm :proxies))))
(plist-get state-data :jc)
(lexical-let ((fsm fsm))
(lambda () (fsm-send-sync fsm :proxies))))
(list state-data 5))
(define-state jabber-socks5 query-proxies (fsm state-data event callback)
@ -238,6 +242,7 @@ set; the target waits for one."
;; This is where initiation of server sockets would go
(jabber-send-iq
(plist-get state-data :jc)
(plist-get state-data :jid) "set"
`(query ((xmlns . "http://jabber.org/protocol/bytestreams")
(sid . ,(plist-get state-data :sid)))
@ -256,7 +261,7 @@ set; the target waits for one."
;; (fast ((xmlns . "http://affinix.com/jabber/stream")))
)
(lexical-let ((fsm fsm))
(lambda (xml-data closure-data)
(lambda (jc xml-data closure-data)
(fsm-send-sync fsm (list :iq xml-data))))
nil
;; TODO: error handling
@ -267,7 +272,7 @@ set; the target waits for one."
(add-to-list 'jabber-iq-set-xmlns-alist
(cons "http://jabber.org/protocol/bytestreams" 'jabber-socks5-process))
(defun jabber-socks5-process (xml-data)
(defun jabber-socks5-process (jc xml-data)
"Accept IQ get for SOCKS5 bytestream"
(let* ((jid (jabber-xml-get-attribute xml-data 'from))
(id (jabber-xml-get-attribute xml-data 'id))
@ -309,7 +314,11 @@ set; the target waits for one."
))
(define-state jabber-socks5 initiate (fsm state-data event callback)
(let* ((our-jid (concat jabber-username "@" jabber-server "/" jabber-resource))
(let* ((jc (plist-get state-data :jc))
(jc-data (fsm-get-state-data jc))
(our-jid (concat (plist-get jc-data :username) "@"
(plist-get jc-data :server) "/"
(plist-get jc-data :resource)))
(their-jid (plist-get state-data :jid))
(initiator-jid (if (eq (plist-get state-data :role) :initiator) our-jid their-jid))
(target-jid (if (eq (plist-get state-data :role) :initiator) their-jid our-jid)))
@ -497,6 +506,7 @@ set; the target waits for one."
(let ((iq-id (plist-get state-data :iq-id)))
(when iq-id
(jabber-send-iq
(plist-get state-data :jc)
(plist-get state-data :jid) "result"
`(query ((xmlns . "http://jabber.org/protocol/bytestreams"))
(streamhost-used ((jid . ,streamhost-jid))))
@ -507,12 +517,13 @@ set; the target waits for one."
(if (eq (plist-get state-data :role) :initiator)
(progn
(jabber-send-iq
(plist-get state-data :jc)
streamhost-jid "set"
`(query ((xmlns . "http://jabber.org/protocol/bytestreams")
(sid . ,(plist-get state-data :sid)))
(activate nil ,(plist-get state-data :jid)))
(lambda (xml-data fsm) (fsm-send-sync fsm :activated)) fsm
(lambda (xml-data fsm) (fsm-send-sync fsm :activation-failed)) fsm)
(lambda (jc xml-data fsm) (fsm-send-sync fsm :activated)) fsm
(lambda (jc xml-data fsm) (fsm-send-sync fsm :activation-failed)) fsm)
(list 'wait-for-activation state-data 10))
;; Otherwise, we just let the data flow.
(list 'stream-activated state-data nil))))
@ -544,6 +555,7 @@ set; the target waits for one."
(define-enter-state jabber-socks5 stream-activated
(fsm state-data)
(let ((connection (plist-get state-data :connection))
(jc (plist-get state-data :jc))
(jid (plist-get state-data :jid))
(sid (plist-get state-data :sid))
(profile-function (plist-get state-data :profile-function)))
@ -555,7 +567,7 @@ set; the target waits for one."
(list (plist-put state-data
:profile-data-function
(funcall profile-function
jid sid
jc jid sid
(lexical-let ((fsm fsm))
(lambda (data)
(fsm-send fsm (list :send data))))))
@ -598,22 +610,23 @@ set; the target waits for one."
(define-enter-state jabber-socks5 fail (fsm state-data)
"Tell our caller that we failed."
(let ((jid (plist-get state-data :jid))
(let ((jc (plist-get state-data :jc))
(jid (plist-get state-data :jid))
(sid (plist-get state-data :sid))
(profile-function (plist-get state-data :profile-function))
(iq-id (plist-get state-data :iq-id)))
(funcall profile-function jid sid (plist-get state-data :error))
(funcall profile-function jc jid sid (plist-get state-data :error))
(when iq-id
(jabber-send-iq-error jid iq-id nil "cancel"
(jabber-send-iq-error jc jid iq-id nil "cancel"
'remote-server-not-found)))
(list nil nil))
(defun jabber-socks5-client-1 (jid sid profile-function)
(defun jabber-socks5-client-1 (jc jid sid profile-function)
"Negotiate a SOCKS5 connection with JID.
This function simply starts a state machine."
(add-to-list 'jabber-socks5-pending-sessions
(list sid jid (start-jabber-socks5 jid sid profile-function :initiator))))
(list sid jid (start-jabber-socks5 jc jid sid profile-function :initiator))))
;; (defun jabber-socks5-client-2 (xml-data jid sid profile-function)
;; "Contact has selected a streamhost to use. Connect to the proxy."