| 
									
										
										
										
											2010-06-06 23:22:52 +08:00
										 |  |  | # -*- coding:utf-8 -*- | 
					
						
							|  |  |  | ## This file is part of Gajim. | 
					
						
							|  |  |  | ## | 
					
						
							|  |  |  | ## Gajim is free software; you can redistribute it and/or modify | 
					
						
							|  |  |  | ## it under the terms of the GNU General Public License as published | 
					
						
							|  |  |  | ## by the Free Software Foundation; version 3 only. | 
					
						
							|  |  |  | ## | 
					
						
							|  |  |  | ## Gajim is distributed in the hope that it will be useful, | 
					
						
							|  |  |  | ## but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 
					
						
							|  |  |  | ## GNU General Public License for more details. | 
					
						
							|  |  |  | ## | 
					
						
							|  |  |  | ## You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  | ## along with Gajim. If not, see <http://www.gnu.org/licenses/>. | 
					
						
							|  |  |  | ## | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | """
 | 
					
						
							|  |  |  | Handles  Jingle File Transfer (XEP 0234) | 
					
						
							|  |  |  | """
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-16 18:41:33 -04:00
										 |  |  | import hashlib | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  | import logging | 
					
						
							|  |  |  | import os | 
					
						
							|  |  |  | import threading | 
					
						
							| 
									
										
										
										
											2017-03-04 21:22:46 +01:00
										 |  |  | from enum import IntEnum, unique | 
					
						
							| 
									
										
										
										
											2012-12-09 21:37:51 +01:00
										 |  |  | import nbxmpp | 
					
						
							| 
									
										
										
										
											2017-08-13 13:18:56 +02:00
										 |  |  | from gajim.common import app | 
					
						
							| 
									
										
										
										
											2017-06-13 23:58:06 +02:00
										 |  |  | from gajim.common import configpaths | 
					
						
							|  |  |  | from gajim.common import jingle_xtls | 
					
						
							|  |  |  | from gajim.common.jingle_content import contents, JingleContent | 
					
						
							|  |  |  | from gajim.common.jingle_transport import JingleTransportSocks5, TransportType | 
					
						
							|  |  |  | from gajim.common import helpers | 
					
						
							|  |  |  | from gajim.common.connection_handlers_events import FileRequestReceivedEvent | 
					
						
							|  |  |  | from gajim.common.jingle_ftstates import ( | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  |     StateInitialized, StateCandSent, StateCandReceived, StateTransfering, | 
					
						
							|  |  |  |     StateCandSentAndRecv, StateTransportReplace) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-06 23:22:52 +08:00
										 |  |  | log = logging.getLogger('gajim.c.jingle_ft') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-04 21:22:46 +01:00
										 |  |  | @unique | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  | class State(IntEnum): | 
					
						
							|  |  |  |     NOT_STARTED = 0 | 
					
						
							|  |  |  |     INITIALIZED = 1 | 
					
						
							|  |  |  |     # We send the candidates and we are waiting for a reply | 
					
						
							|  |  |  |     CAND_SENT = 2 | 
					
						
							|  |  |  |     # We received the candidates and we are waiting to reply | 
					
						
							|  |  |  |     CAND_RECEIVED = 3 | 
					
						
							|  |  |  |     # We have sent and received the candidates | 
					
						
							|  |  |  |     # This also includes any candidate-error received or sent | 
					
						
							|  |  |  |     CAND_SENT_AND_RECEIVED = 4 | 
					
						
							|  |  |  |     TRANSPORT_REPLACE = 5 | 
					
						
							|  |  |  |     # We are transfering the file | 
					
						
							|  |  |  |     TRANSFERING = 6 | 
					
						
							| 
									
										
										
										
											2011-08-14 23:59:39 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-06 23:22:52 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | class JingleFileTransfer(JingleContent): | 
					
						
							| 
									
										
										
										
											2012-09-05 19:39:07 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-24 23:12:34 +02:00
										 |  |  |     def __init__(self, session, transport=None, file_props=None, | 
					
						
							| 
									
										
										
										
											2017-08-07 17:41:32 +02:00
										 |  |  |                  use_security=False, senders=None): | 
					
						
							|  |  |  |         JingleContent.__init__(self, session, transport, senders) | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  |         log.info("transport value: %s", transport) | 
					
						
							| 
									
										
										
										
											2010-08-24 23:12:34 +02:00
										 |  |  |         # events we might be interested in | 
					
						
							| 
									
										
										
										
											2010-06-06 23:22:52 +08:00
										 |  |  |         self.callbacks['session-initiate'] += [self.__on_session_initiate] | 
					
						
							| 
									
										
										
										
											2012-08-22 12:21:45 +02:00
										 |  |  |         self.callbacks['session-initiate-sent'] += [ | 
					
						
							|  |  |  |             self.__on_session_initiate_sent] | 
					
						
							| 
									
										
										
										
											2010-08-26 10:36:58 +02:00
										 |  |  |         self.callbacks['content-add'] += [self.__on_session_initiate] | 
					
						
							| 
									
										
										
										
											2010-06-06 23:22:52 +08:00
										 |  |  |         self.callbacks['session-accept'] += [self.__on_session_accept] | 
					
						
							| 
									
										
										
										
											2012-08-22 11:54:21 +02:00
										 |  |  |         self.callbacks['session-terminate'] += [self.__on_session_terminate] | 
					
						
							| 
									
										
										
										
											2012-01-15 19:37:00 -05:00
										 |  |  |         self.callbacks['session-info'] += [self.__on_session_info] | 
					
						
							| 
									
										
										
										
											2010-06-06 23:22:52 +08:00
										 |  |  |         self.callbacks['transport-accept'] += [self.__on_transport_accept] | 
					
						
							| 
									
										
										
										
											2010-08-24 23:12:34 +02:00
										 |  |  |         self.callbacks['transport-replace'] += [self.__on_transport_replace] | 
					
						
							| 
									
										
										
										
											2012-01-06 23:18:50 -05:00
										 |  |  |         self.callbacks['session-accept-sent'] += [self.__transport_setup] | 
					
						
							| 
									
										
										
										
											2010-08-24 23:12:34 +02:00
										 |  |  |         # fallback transport method | 
					
						
							| 
									
										
										
										
											2010-06-06 23:22:52 +08:00
										 |  |  |         self.callbacks['transport-reject'] += [self.__on_transport_reject] | 
					
						
							|  |  |  |         self.callbacks['transport-info'] += [self.__on_transport_info] | 
					
						
							| 
									
										
										
										
											2010-07-03 16:22:47 +08:00
										 |  |  |         self.callbacks['iq-result'] += [self.__on_iq_result] | 
					
						
							| 
									
										
										
										
											2010-07-22 15:05:06 +08:00
										 |  |  |         self.use_security = use_security | 
					
						
							| 
									
										
										
										
											2013-12-04 18:43:28 +01:00
										 |  |  |         self.x509_fingerprint = None | 
					
						
							| 
									
										
										
										
											2010-06-06 23:22:52 +08:00
										 |  |  |         self.file_props = file_props | 
					
						
							| 
									
										
										
										
											2012-09-15 10:39:35 -04:00
										 |  |  |         self.weinitiate = self.session.weinitiate | 
					
						
							| 
									
										
										
										
											2012-12-09 21:37:51 +01:00
										 |  |  |         self.werequest = self.session.werequest | 
					
						
							| 
									
										
										
										
											2010-06-14 21:21:22 +08:00
										 |  |  |         if self.file_props is not None: | 
					
						
							| 
									
										
										
										
											2012-09-15 10:39:35 -04:00
										 |  |  |             if self.session.werequest: | 
					
						
							|  |  |  |                 self.file_props.sender = self.session.peerjid | 
					
						
							|  |  |  |                 self.file_props.receiver = self.session.ourjid | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 self.file_props.sender = self.session.ourjid | 
					
						
							|  |  |  |                 self.file_props.receiver = self.session.peerjid | 
					
						
							| 
									
										
										
										
											2012-06-14 12:27:23 -04:00
										 |  |  |             self.file_props.session_type = 'jingle' | 
					
						
							| 
									
										
										
										
											2012-08-25 12:09:50 -04:00
										 |  |  |             self.file_props.sid = session.sid | 
					
						
							| 
									
										
										
										
											2012-06-14 12:27:23 -04:00
										 |  |  |             self.file_props.transfered_size = [] | 
					
						
							| 
									
										
										
										
											2012-08-25 12:09:50 -04:00
										 |  |  |             self.file_props.transport_sid = self.transport.sid | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  |         log.info("FT request: %s", file_props) | 
					
						
							| 
									
										
										
										
											2010-06-14 21:21:22 +08:00
										 |  |  |         if transport is None: | 
					
						
							| 
									
										
										
										
											2010-06-19 22:52:17 +08:00
										 |  |  |             self.transport = JingleTransportSocks5() | 
					
						
							| 
									
										
										
										
											2011-07-17 18:28:38 -04:00
										 |  |  |         self.transport.set_connection(session.connection) | 
					
						
							|  |  |  |         self.transport.set_file_props(self.file_props) | 
					
						
							|  |  |  |         self.transport.set_our_jid(session.ourjid) | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  |         log.info('ourjid: %s', session.ourjid) | 
					
						
							| 
									
										
										
										
											2010-06-08 21:24:41 +08:00
										 |  |  |         self.session = session | 
					
						
							| 
									
										
										
										
											2010-06-14 20:41:24 +08:00
										 |  |  |         self.media = 'file' | 
					
						
							| 
									
										
										
										
											2011-08-14 23:59:39 -04:00
										 |  |  |         self.nominated_cand = {} | 
					
						
							| 
									
										
										
										
											2017-08-13 13:18:56 +02:00
										 |  |  |         if app.contacts.is_gc_contact(session.connection.name, | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  |                                         session.peerjid): | 
					
						
							| 
									
										
										
										
											2012-06-16 18:41:33 -04:00
										 |  |  |             roomjid = session.peerjid.split('/')[0] | 
					
						
							| 
									
										
										
										
											2013-08-26 20:34:58 +02:00
										 |  |  |             dstaddr = hashlib.sha1(('%s%s%s' % (self.file_props.sid, | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  |                                                 session.ourjid, roomjid)) | 
					
						
							|  |  |  |                                    .encode('utf-8')).hexdigest() | 
					
						
							| 
									
										
										
										
											2012-08-23 13:10:30 +02:00
										 |  |  |             self.file_props.dstaddr = dstaddr | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  |         self.state = State.NOT_STARTED | 
					
						
							|  |  |  |         self.states = { | 
					
						
							|  |  |  |             State.INITIALIZED   : StateInitialized(self), | 
					
						
							|  |  |  |             State.CAND_SENT     : StateCandSent(self), | 
					
						
							|  |  |  |             State.CAND_RECEIVED : StateCandReceived(self), | 
					
						
							|  |  |  |             State.TRANSFERING   : StateTransfering(self), | 
					
						
							|  |  |  |             State.TRANSPORT_REPLACE : StateTransportReplace(self), | 
					
						
							|  |  |  |             State.CAND_SENT_AND_RECEIVED : StateCandSentAndRecv(self) | 
					
						
							| 
									
										
										
										
											2012-08-22 12:21:45 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2014-04-25 12:48:39 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-15 14:01:55 +02:00
										 |  |  |         if jingle_xtls.PYOPENSSL_PRESENT: | 
					
						
							|  |  |  |             cert_name = os.path.join(configpaths.gajimpaths['MY_CERT'], | 
					
						
							|  |  |  |                                      jingle_xtls.SELF_SIGNED_CERTIFICATE) | 
					
						
							|  |  |  |             if not (os.path.exists(cert_name + '.cert') | 
					
						
							|  |  |  |                     and os.path.exists(cert_name + '.pkey')): | 
					
						
							|  |  |  |                 jingle_xtls.make_certs(cert_name, 'gajim') | 
					
						
							| 
									
										
										
										
											2012-04-04 21:04:23 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def __state_changed(self, nextstate, args=None): | 
					
						
							|  |  |  |         # Executes the next state action and sets the next state | 
					
						
							| 
									
										
										
										
											2012-08-22 18:09:40 +02:00
										 |  |  |         current_state = self.state | 
					
						
							| 
									
										
										
										
											2012-04-04 21:04:23 -04:00
										 |  |  |         st = self.states[nextstate] | 
					
						
							|  |  |  |         st.action(args) | 
					
						
							| 
									
										
										
										
											2012-08-22 18:09:40 +02:00
										 |  |  |         # state can have been changed during the action. Don't go back. | 
					
						
							|  |  |  |         if self.state == current_state: | 
					
						
							|  |  |  |             self.state = nextstate | 
					
						
							| 
									
										
										
										
											2010-08-24 23:12:34 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-06 23:22:52 +08:00
										 |  |  |     def __on_session_initiate(self, stanza, content, error, action): | 
					
						
							| 
									
										
										
										
											2016-04-03 14:28:08 +02:00
										 |  |  |         log.debug("Jingle FT request received") | 
					
						
							| 
									
										
										
										
											2017-08-13 13:18:56 +02:00
										 |  |  |         app.nec.push_incoming_event(FileRequestReceivedEvent(None, | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  |                                                                conn=self.session.connection, | 
					
						
							|  |  |  |                                                                stanza=stanza, | 
					
						
							|  |  |  |                                                                jingle_content=content, | 
					
						
							|  |  |  |                                                                FT_content=self)) | 
					
						
							| 
									
										
										
										
											2012-09-05 19:39:07 -04:00
										 |  |  |         if self.session.request: | 
					
						
							|  |  |  |             # accept the request | 
					
						
							|  |  |  |             self.session.approve_content(self.media, self.name) | 
					
						
							|  |  |  |             self.session.accept_session() | 
					
						
							| 
									
										
										
										
											2012-08-23 17:45:38 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-15 19:37:00 -05:00
										 |  |  |     def __on_session_initiate_sent(self, stanza, content, error, action): | 
					
						
							| 
									
										
										
										
											2012-08-25 11:14:38 -04:00
										 |  |  |         pass | 
					
						
							| 
									
										
										
										
											2012-08-22 11:54:21 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-28 19:54:59 -04:00
										 |  |  |     def __send_hash(self): | 
					
						
							|  |  |  |         # Send hash in a session info | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  |         checksum = nbxmpp.Node(tag='checksum', | 
					
						
							|  |  |  |                                payload=[nbxmpp.Node(tag='file', | 
					
						
							|  |  |  |                                                     payload=[self._compute_hash()])]) | 
					
						
							| 
									
										
										
										
											2017-06-14 20:31:29 +01:00
										 |  |  |         checksum.setNamespace(nbxmpp.NS_JINGLE_FILE_TRANSFER_5) | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  |         self.session.__session_info(checksum) | 
					
						
							| 
									
										
										
										
											2017-08-13 13:18:56 +02:00
										 |  |  |         pjid = app.get_jid_without_resource(self.session.peerjid) | 
					
						
							| 
									
										
										
										
											2012-08-29 15:06:04 -04:00
										 |  |  |         file_info = {'name' : self.file_props.name, | 
					
						
							| 
									
										
										
										
											2012-09-02 12:59:55 -04:00
										 |  |  |                      'file-name' : self.file_props.file_name, | 
					
						
							| 
									
										
										
										
											2012-08-29 15:06:04 -04:00
										 |  |  |                      'hash' : self.file_props.hash_, | 
					
						
							|  |  |  |                      'size' : self.file_props.size, | 
					
						
							| 
									
										
										
										
											2012-09-22 13:25:55 -04:00
										 |  |  |                      'date' : self.file_props.date, | 
					
						
							|  |  |  |                      'peerjid' : pjid | 
					
						
							| 
									
										
										
										
											2012-08-29 15:06:04 -04:00
										 |  |  |                     } | 
					
						
							| 
									
										
										
										
											2012-09-22 22:16:03 -04:00
										 |  |  |         self.session.connection.set_file_info(file_info) | 
					
						
							| 
									
										
										
										
											2012-08-29 15:06:04 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  |     def _compute_hash(self): | 
					
						
							| 
									
										
										
										
											2012-05-28 19:54:59 -04:00
										 |  |  |         # Caculates the hash and returns a xep-300 hash stanza | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  |         if self.file_props.algo is None: | 
					
						
							| 
									
										
										
										
											2012-01-15 19:37:00 -05:00
										 |  |  |             return | 
					
						
							|  |  |  |         try: | 
					
						
							| 
									
										
										
										
											2013-01-05 10:09:15 +01:00
										 |  |  |             file_ = open(self.file_props.file_name, 'rb') | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  |         except IOError: | 
					
						
							| 
									
										
										
										
											2012-01-24 16:51:26 -05:00
										 |  |  |             # can't open file | 
					
						
							| 
									
										
										
										
											2012-01-15 19:37:00 -05:00
										 |  |  |             return | 
					
						
							| 
									
										
										
										
											2017-06-14 20:29:52 +01:00
										 |  |  |         h = nbxmpp.Hashes2() | 
					
						
							| 
									
										
										
										
											2012-08-24 20:13:25 -04:00
										 |  |  |         hash_ = h.calculateHash(self.file_props.algo, file_) | 
					
						
							| 
									
										
										
										
											2013-01-05 10:09:15 +01:00
										 |  |  |         file_.close() | 
					
						
							| 
									
										
										
										
											2012-05-27 21:05:43 -04:00
										 |  |  |         # DEBUG | 
					
						
							| 
									
										
										
										
											2012-09-18 00:13:31 -04:00
										 |  |  |         #hash_ = '1294809248109223' | 
					
						
							| 
									
										
										
										
											2012-01-24 16:51:26 -05:00
										 |  |  |         if not hash_: | 
					
						
							|  |  |  |             # Hash alogrithm not supported | 
					
						
							|  |  |  |             return | 
					
						
							| 
									
										
										
										
											2012-06-14 12:27:23 -04:00
										 |  |  |         self.file_props.hash_ = hash_ | 
					
						
							| 
									
										
										
										
											2012-08-24 20:13:25 -04:00
										 |  |  |         h.addHash(hash_, self.file_props.algo) | 
					
						
							| 
									
										
										
										
											2012-05-28 19:54:59 -04:00
										 |  |  |         return h | 
					
						
							| 
									
										
										
										
											2012-08-22 11:54:21 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-12-04 18:43:28 +01:00
										 |  |  |     def on_cert_received(self): | 
					
						
							|  |  |  |         self.session.approve_session() | 
					
						
							|  |  |  |         self.session.approve_content('file', name=self.name) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-06 23:22:52 +08:00
										 |  |  |     def __on_session_accept(self, stanza, content, error, action): | 
					
						
							|  |  |  |         log.info("__on_session_accept") | 
					
						
							| 
									
										
										
										
											2011-07-22 16:15:34 -04:00
										 |  |  |         con = self.session.connection | 
					
						
							| 
									
										
										
										
											2010-07-22 16:20:14 +08:00
										 |  |  |         security = content.getTag('security') | 
					
						
							|  |  |  |         if not security: # responder can not verify our fingerprint | 
					
						
							|  |  |  |             self.use_security = False | 
					
						
							| 
									
										
										
										
											2013-12-04 18:43:28 +01:00
										 |  |  |         else: | 
					
						
							|  |  |  |             fingerprint = security.getTag('fingerprint') | 
					
						
							|  |  |  |             if fingerprint: | 
					
						
							|  |  |  |                 fingerprint = fingerprint.getData() | 
					
						
							|  |  |  |                 self.x509_fingerprint = fingerprint | 
					
						
							| 
									
										
										
										
											2017-08-13 13:18:56 +02:00
										 |  |  |                 if not jingle_xtls.check_cert(app.get_jid_without_resource( | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  |                         self.session.responder), fingerprint): | 
					
						
							| 
									
										
										
										
											2013-12-04 18:43:28 +01:00
										 |  |  |                     id_ = jingle_xtls.send_cert_request(con, | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  |                                                         self.session.responder) | 
					
						
							| 
									
										
										
										
											2013-12-04 18:43:28 +01:00
										 |  |  |                     jingle_xtls.key_exchange_pend(id_, | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  |                                                   self.continue_session_accept, | 
					
						
							|  |  |  |                                                   [stanza]) | 
					
						
							| 
									
										
										
										
											2013-12-04 18:43:28 +01:00
										 |  |  |                     raise nbxmpp.NodeProcessed | 
					
						
							|  |  |  |         self.continue_session_accept(stanza) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def continue_session_accept(self, stanza): | 
					
						
							|  |  |  |         con = self.session.connection | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  |         if self.state == State.TRANSPORT_REPLACE: | 
					
						
							| 
									
										
										
										
											2012-09-15 10:39:35 -04:00
										 |  |  |             # If we are requesting we don't have the file | 
					
						
							|  |  |  |             if self.session.werequest: | 
					
						
							| 
									
										
										
										
											2012-12-09 21:37:51 +01:00
										 |  |  |                 raise nbxmpp.NodeProcessed | 
					
						
							| 
									
										
										
										
											2011-06-28 18:31:07 -04:00
										 |  |  |             # We send the file | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  |             self.__state_changed(State.TRANSFERING) | 
					
						
							| 
									
										
										
										
											2012-12-09 21:37:51 +01:00
										 |  |  |             raise nbxmpp.NodeProcessed | 
					
						
							| 
									
										
										
										
											2012-06-14 12:27:23 -04:00
										 |  |  |         self.file_props.streamhosts = self.transport.remote_candidates | 
					
						
							| 
									
										
										
										
											2012-08-25 11:14:38 -04:00
										 |  |  |         # Calculate file hash in a new thread | 
					
						
							|  |  |  |         # if we haven't sent the hash already. | 
					
						
							| 
									
										
										
										
											2012-10-13 14:31:16 -04:00
										 |  |  |         if self.file_props.hash_ is None and self.file_props.algo and \ | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  |                 not self.werequest: | 
					
						
							|  |  |  |             self.hash_thread = threading.Thread(target=self.__send_hash) | 
					
						
							|  |  |  |             self.hash_thread.start() | 
					
						
							| 
									
										
										
										
											2012-06-14 12:27:23 -04:00
										 |  |  |         for host in self.file_props.streamhosts: | 
					
						
							| 
									
										
										
										
											2012-01-08 20:44:15 +01:00
										 |  |  |             host['initiator'] = self.session.initiator | 
					
						
							|  |  |  |             host['target'] = self.session.responder | 
					
						
							| 
									
										
										
										
											2012-06-14 12:27:23 -04:00
										 |  |  |             host['sid'] = self.file_props.sid | 
					
						
							| 
									
										
										
										
											2011-07-22 16:15:34 -04:00
										 |  |  |         fingerprint = None | 
					
						
							|  |  |  |         if self.use_security: | 
					
						
							|  |  |  |             fingerprint = 'client' | 
					
						
							| 
									
										
										
										
											2012-08-22 12:55:57 +02:00
										 |  |  |         if self.transport.type_ == TransportType.SOCKS5: | 
					
						
							| 
									
										
										
										
											2017-08-16 15:27:35 +02:00
										 |  |  |             sid = self.file_props.transport_sid | 
					
						
							| 
									
										
										
										
											2017-08-13 13:18:56 +02:00
										 |  |  |             app.socks5queue.connect_to_hosts(self.session.connection.name, | 
					
						
							| 
									
										
										
										
											2017-08-16 15:27:35 +02:00
										 |  |  |                                                sid, | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  |                                                self.on_connect, | 
					
						
							|  |  |  |                                                self._on_connect_error, | 
					
						
							|  |  |  |                                                fingerprint=fingerprint, | 
					
						
							|  |  |  |                                                receiving=False) | 
					
						
							| 
									
										
										
										
											2013-12-04 18:43:28 +01:00
										 |  |  |             raise nbxmpp.NodeProcessed | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  |         self.__state_changed(State.TRANSFERING) | 
					
						
							| 
									
										
										
										
											2012-12-09 21:37:51 +01:00
										 |  |  |         raise nbxmpp.NodeProcessed | 
					
						
							| 
									
										
										
										
											2010-06-06 23:22:52 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def __on_session_terminate(self, stanza, content, error, action): | 
					
						
							|  |  |  |         log.info("__on_session_terminate") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-15 19:37:00 -05:00
										 |  |  |     def __on_session_info(self, stanza, content, error, action): | 
					
						
							|  |  |  |         pass | 
					
						
							| 
									
										
										
										
											2012-08-22 11:54:21 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-06 23:22:52 +08:00
										 |  |  |     def __on_transport_accept(self, stanza, content, error, action): | 
					
						
							|  |  |  |         log.info("__on_transport_accept") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __on_transport_replace(self, stanza, content, error, action): | 
					
						
							|  |  |  |         log.info("__on_transport_replace") | 
					
						
							| 
									
										
										
										
											2010-08-24 23:12:34 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-06 23:22:52 +08:00
										 |  |  |     def __on_transport_reject(self, stanza, content, error, action): | 
					
						
							|  |  |  |         log.info("__on_transport_reject") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __on_transport_info(self, stanza, content, error, action): | 
					
						
							|  |  |  |         log.info("__on_transport_info") | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  |         cand_error = content.getTag('transport').getTag('candidate-error') | 
					
						
							|  |  |  |         cand_used = content.getTag('transport').getTag('candidate-used') | 
					
						
							|  |  |  |         if (cand_error or cand_used) and \ | 
					
						
							|  |  |  |                 self.state >= State.CAND_SENT_AND_RECEIVED: | 
					
						
							| 
									
										
										
										
											2015-05-17 22:38:26 +02:00
										 |  |  |             raise nbxmpp.NodeProcessed | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  |         if cand_error: | 
					
						
							| 
									
										
										
										
											2017-08-13 13:18:56 +02:00
										 |  |  |             if not app.socks5queue.listener.connections: | 
					
						
							|  |  |  |                 app.socks5queue.listener.disconnect() | 
					
						
							| 
									
										
										
										
											2011-08-14 23:59:39 -04:00
										 |  |  |             self.nominated_cand['peer-cand'] = False | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  |             if self.state == State.CAND_SENT: | 
					
						
							| 
									
										
										
										
											2011-08-14 23:59:39 -04:00
										 |  |  |                 if not self.nominated_cand['our-cand'] and \ | 
					
						
							|  |  |  |                    not self.nominated_cand['peer-cand']: | 
					
						
							|  |  |  |                     if not self.weinitiate: | 
					
						
							|  |  |  |                         return | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  |                     self.__state_changed(State.TRANSPORT_REPLACE) | 
					
						
							| 
									
										
										
										
											2011-08-24 23:53:36 +02:00
										 |  |  |                 else: | 
					
						
							|  |  |  |                     response = stanza.buildReply('result') | 
					
						
							| 
									
										
										
										
											2011-12-29 14:08:35 +01:00
										 |  |  |                     response.delChild(response.getQuery()) | 
					
						
							| 
									
										
										
										
											2011-08-24 23:53:36 +02:00
										 |  |  |                     self.session.connection.connection.send(response) | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  |                     self.__state_changed(State.TRANSFERING) | 
					
						
							| 
									
										
										
										
											2012-12-09 21:37:51 +01:00
										 |  |  |                     raise nbxmpp.NodeProcessed | 
					
						
							| 
									
										
										
										
											2011-08-14 23:59:39 -04:00
										 |  |  |             else: | 
					
						
							| 
									
										
										
										
											2017-08-16 15:27:35 +02:00
										 |  |  |                 args = {'candError' : True} | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  |                 self.__state_changed(State.CAND_RECEIVED, args) | 
					
						
							| 
									
										
										
										
											2011-07-05 14:05:16 -04:00
										 |  |  |             return | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  |         if cand_used: | 
					
						
							|  |  |  |             streamhost_cid = cand_used.getAttr('cid') | 
					
						
							| 
									
										
										
										
											2012-08-30 11:09:39 +02:00
										 |  |  |             streamhost_used = None | 
					
						
							|  |  |  |             for cand in self.transport.candidates: | 
					
						
							|  |  |  |                 if cand['candidate_id'] == streamhost_cid: | 
					
						
							|  |  |  |                     streamhost_used = cand | 
					
						
							|  |  |  |                     break | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  |             if streamhost_used is None or streamhost_used['type'] == 'proxy': | 
					
						
							| 
									
										
										
										
											2017-08-13 13:18:56 +02:00
										 |  |  |                 if app.socks5queue.listener and \ | 
					
						
							|  |  |  |                 not app.socks5queue.listener.connections: | 
					
						
							|  |  |  |                     app.socks5queue.listener.disconnect() | 
					
						
							| 
									
										
										
										
											2011-10-29 00:09:45 -04:00
										 |  |  |         if content.getTag('transport').getTag('activated'): | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  |             self.state = State.TRANSFERING | 
					
						
							| 
									
										
										
										
											2017-08-13 13:18:56 +02:00
										 |  |  |             jid = app.get_jid_without_resource(self.session.ourjid) | 
					
						
							|  |  |  |             app.socks5queue.send_file(self.file_props, | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  |                                         self.session.connection.name, 'client') | 
					
						
							| 
									
										
										
										
											2011-10-29 00:09:45 -04:00
										 |  |  |             return | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  |         args = {'content': content, | 
					
						
							|  |  |  |                 'sendCand': False} | 
					
						
							|  |  |  |         if self.state == State.CAND_SENT: | 
					
						
							|  |  |  |             self.__state_changed(State.CAND_SENT_AND_RECEIVED, args) | 
					
						
							|  |  |  |             self.__state_changed(State.TRANSFERING) | 
					
						
							| 
									
										
										
										
											2012-12-09 21:37:51 +01:00
										 |  |  |             raise nbxmpp.NodeProcessed | 
					
						
							| 
									
										
										
										
											2010-07-13 10:38:31 +08:00
										 |  |  |         else: | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  |             self.__state_changed(State.CAND_RECEIVED, args) | 
					
						
							| 
									
										
										
										
											2011-08-24 10:42:16 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-03 16:22:47 +08:00
										 |  |  |     def __on_iq_result(self, stanza, content, error, action): | 
					
						
							|  |  |  |         log.info("__on_iq_result") | 
					
						
							| 
									
										
										
										
											2010-08-24 23:12:34 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  |         if self.state == State.NOT_STARTED: | 
					
						
							|  |  |  |             self.__state_changed(State.INITIALIZED) | 
					
						
							|  |  |  |         elif self.state == State.CAND_SENT_AND_RECEIVED: | 
					
						
							| 
									
										
										
										
											2011-08-14 23:59:39 -04:00
										 |  |  |             if not self.nominated_cand['our-cand'] and \ | 
					
						
							| 
									
										
										
										
											2011-08-24 10:42:16 +02:00
										 |  |  |             not self.nominated_cand['peer-cand']: | 
					
						
							|  |  |  |                 if not self.weinitiate: | 
					
						
							| 
									
										
										
										
											2011-08-14 23:59:39 -04:00
										 |  |  |                     return | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  |                 self.__state_changed(State.TRANSPORT_REPLACE) | 
					
						
							| 
									
										
										
										
											2011-08-24 10:42:16 +02:00
										 |  |  |                 return | 
					
						
							| 
									
										
										
										
											2011-08-14 23:59:39 -04:00
										 |  |  |             # initiate transfer | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  |             self.__state_changed(State.TRANSFERING) | 
					
						
							| 
									
										
										
										
											2012-08-22 11:54:21 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-08 20:44:15 +01:00
										 |  |  |     def __transport_setup(self, stanza=None, content=None, error=None, | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  |                           action=None): | 
					
						
							| 
									
										
										
										
											2012-01-06 23:18:50 -05:00
										 |  |  |         # Sets up a few transport specific things for the file transfer | 
					
						
							| 
									
										
										
										
											2012-08-22 12:55:57 +02:00
										 |  |  |         if self.transport.type_ == TransportType.IBB: | 
					
						
							| 
									
										
										
										
											2012-04-07 00:56:44 -04:00
										 |  |  |             # No action required, just set the state to transfering | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  |             self.state = State.TRANSFERING | 
					
						
							| 
									
										
										
										
											2012-08-30 11:09:39 +02:00
										 |  |  |         else: | 
					
						
							|  |  |  |             self._listen_host() | 
					
						
							| 
									
										
										
										
											2012-08-22 11:54:21 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-04 21:04:23 -04:00
										 |  |  |     def on_connect(self, streamhost): | 
					
						
							| 
									
										
										
										
											2010-07-05 13:46:53 +08:00
										 |  |  |         """
 | 
					
						
							|  |  |  |         send candidate-used stanza | 
					
						
							|  |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2010-08-24 23:12:34 +02:00
										 |  |  |         log.info('send_candidate_used') | 
					
						
							| 
									
										
										
										
											2010-07-05 13:46:53 +08:00
										 |  |  |         if streamhost is None: | 
					
						
							|  |  |  |             return | 
					
						
							| 
									
										
										
										
											2012-04-04 21:04:23 -04:00
										 |  |  |         args = {'streamhost' : streamhost, | 
					
						
							|  |  |  |                 'sendCand'   : True} | 
					
						
							| 
									
										
										
										
											2011-08-14 23:59:39 -04:00
										 |  |  |         self.nominated_cand['our-cand'] = streamhost | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  |         self.__send_candidate(args) | 
					
						
							| 
									
										
										
										
											2011-08-14 23:59:39 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-29 00:09:45 -04:00
										 |  |  |     def _on_connect_error(self, sid): | 
					
						
							| 
									
										
										
										
											2012-04-04 21:04:23 -04:00
										 |  |  |         log.info('connect error, sid=' + sid) | 
					
						
							| 
									
										
										
										
											2012-04-17 20:57:34 -04:00
										 |  |  |         args = {'candError' : True, | 
					
						
							| 
									
										
										
										
											2012-04-17 20:47:52 -04:00
										 |  |  |                 'sendCand'  : True} | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  |         self.__send_candidate(args) | 
					
						
							| 
									
										
										
										
											2012-04-07 00:56:44 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  |     def __send_candidate(self, args): | 
					
						
							|  |  |  |         if self.state == State.CAND_RECEIVED: | 
					
						
							|  |  |  |             self.__state_changed(State.CAND_SENT_AND_RECEIVED, args) | 
					
						
							| 
									
										
										
										
											2011-08-14 23:59:39 -04:00
										 |  |  |         else: | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  |             self.__state_changed(State.CAND_SENT, args) | 
					
						
							| 
									
										
										
										
											2011-08-24 10:42:16 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-03 16:22:47 +08:00
										 |  |  |     def _store_socks5_sid(self, sid, hash_id): | 
					
						
							|  |  |  |         # callback from socsk5queue.start_listener | 
					
						
							| 
									
										
										
										
											2012-06-14 12:27:23 -04:00
										 |  |  |         self.file_props.hash_ = hash_id | 
					
						
							| 
									
										
										
										
											2011-08-24 10:42:16 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-06 23:18:50 -05:00
										 |  |  |     def _listen_host(self): | 
					
						
							| 
									
										
										
										
											2012-06-14 12:27:23 -04:00
										 |  |  |         receiver = self.file_props.receiver | 
					
						
							|  |  |  |         sender = self.file_props.sender | 
					
						
							|  |  |  |         sha_str = helpers.get_auth_sha(self.file_props.sid, sender, | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  |                                        receiver) | 
					
						
							| 
									
										
										
										
											2012-06-14 12:27:23 -04:00
										 |  |  |         self.file_props.sha_str = sha_str | 
					
						
							| 
									
										
										
										
											2017-08-13 13:18:56 +02:00
										 |  |  |         port = app.config.get('file_transfers_port') | 
					
						
							| 
									
										
										
										
											2011-08-08 19:43:07 -04:00
										 |  |  |         fingerprint = None | 
					
						
							|  |  |  |         if self.use_security: | 
					
						
							|  |  |  |             fingerprint = 'server' | 
					
						
							| 
									
										
										
										
											2017-08-13 13:18:56 +02:00
										 |  |  |         listener = app.socks5queue.start_listener(port, sha_str, | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  |                                                     self._store_socks5_sid, | 
					
						
							|  |  |  |                                                     self.file_props, | 
					
						
							|  |  |  |                                                     fingerprint=fingerprint, | 
					
						
							|  |  |  |                                                     typ='sender' if self.weinitiate else 'receiver') | 
					
						
							| 
									
										
										
										
											2011-08-08 19:43:07 -04:00
										 |  |  |         if not listener: | 
					
						
							| 
									
										
										
										
											2012-01-08 20:44:15 +01:00
										 |  |  |             # send error message, notify the user | 
					
						
							| 
									
										
										
										
											2011-08-08 19:43:07 -04:00
										 |  |  |             return | 
					
						
							| 
									
										
										
										
											2012-08-23 17:45:38 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  |     def is_our_candidate_used(self): | 
					
						
							| 
									
										
										
										
											2011-08-21 19:02:58 -04:00
										 |  |  |         '''
 | 
					
						
							|  |  |  |         If this method returns true then the candidate we nominated will be | 
					
						
							|  |  |  |         used, if false, the candidate nominated by peer will be used | 
					
						
							|  |  |  |         '''
 | 
					
						
							| 
									
										
										
										
											2011-08-24 10:42:16 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  |         if not self.nominated_cand['peer-cand']: | 
					
						
							| 
									
										
										
										
											2011-08-14 23:59:39 -04:00
										 |  |  |             return True | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  |         if not self.nominated_cand['our-cand']: | 
					
						
							| 
									
										
										
										
											2011-08-14 23:59:39 -04:00
										 |  |  |             return False | 
					
						
							|  |  |  |         peer_pr = int(self.nominated_cand['peer-cand']['priority']) | 
					
						
							|  |  |  |         our_pr = int(self.nominated_cand['our-cand']['priority']) | 
					
						
							|  |  |  |         if peer_pr != our_pr: | 
					
						
							| 
									
										
										
										
											2011-08-22 23:57:29 -04:00
										 |  |  |             return our_pr > peer_pr | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  |         return self.weinitiate | 
					
						
							| 
									
										
										
										
											2011-08-24 10:42:16 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  |     def start_ibb_transfer(self): | 
					
						
							| 
									
										
										
										
											2012-09-15 10:39:35 -04:00
										 |  |  |         if self.file_props.type_ == 's': | 
					
						
							| 
									
										
										
										
											2017-02-08 02:49:33 +00:00
										 |  |  |             self.__state_changed(State.TRANSFERING) | 
					
						
							| 
									
										
										
										
											2012-09-15 10:39:35 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-24 10:42:16 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-08 16:39:44 +08:00
										 |  |  | def get_content(desc): | 
					
						
							|  |  |  |     return JingleFileTransfer | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-14 20:31:29 +01:00
										 |  |  | contents[nbxmpp.NS_JINGLE_FILE_TRANSFER_5] = get_content |