From 1a3d60c63791416afeb30bf739bb96ea17c7e4c3 Mon Sep 17 00:00:00 2001 From: Yann Leboulanger Date: Tue, 28 Feb 2017 22:28:49 +0100 Subject: [PATCH 01/11] check for errors when adding a transport contact. Fixes #8196 --- src/dialogs.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/dialogs.py b/src/dialogs.py index 2058455f2..549bb05e2 100644 --- a/src/dialogs.py +++ b/src/dialogs.py @@ -1271,6 +1271,11 @@ class AddNewContactWindow: def _nec_gateway_prompt_received(self, obj): if self.adding_jid: jid, transport, type_ = self.adding_jid + if obj.stanza.getError(): + ErrorDialog(_('Error while adding transport contact'), + _('This error occured while adding a contact for transport ' + '%s:\n\n%s') % (transport, obj.stanza.getErrorMsg())) + return if obj.prompt_jid: self._add_jid(obj.prompt_jid, type_) else: From 3bc6173a1176081043f7b7f57331e6b87a04afd1 Mon Sep 17 00:00:00 2001 From: Yann Leboulanger Date: Wed, 1 Mar 2017 22:10:30 +0100 Subject: [PATCH 02/11] Close IBB stream with correct SID. See #8555 --- src/common/protocol/bytestream.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/protocol/bytestream.py b/src/common/protocol/bytestream.py index a3d0069dc..9f82cb721 100644 --- a/src/common/protocol/bytestream.py +++ b/src/common/protocol/bytestream.py @@ -825,7 +825,7 @@ class ConnectionIBBytestream(ConnectionBytestream): self.connection.send(nbxmpp.Protocol('iq', file_props.direction[1:], 'set', payload=[nbxmpp.Node(nbxmpp.NS_IBB + ' close', - {'sid':file_props.sid})])) + {'sid':file_props.transport_sid})])) if file_props.session_type == 'jingle': peerjid = \ file_props.receiver if file_props.type_ == 's' else file_props.sender From fde2ac731bd5686429ef4d9b617aa1e563b508d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20H=C3=B6rist?= Date: Wed, 29 Mar 2017 18:27:59 +0200 Subject: [PATCH 03/11] Close IBB Stream correctly --- src/common/protocol/bytestream.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/common/protocol/bytestream.py b/src/common/protocol/bytestream.py index 9f82cb721..be4adcab2 100644 --- a/src/common/protocol/bytestream.py +++ b/src/common/protocol/bytestream.py @@ -826,7 +826,9 @@ class ConnectionIBBytestream(ConnectionBytestream): file_props.direction[1:], 'set', payload=[nbxmpp.Node(nbxmpp.NS_IBB + ' close', {'sid':file_props.transport_sid})])) - if file_props.session_type == 'jingle': + if file_props.completed: + gajim.socks5queue.complete_transfer_cb(self.name, file_props) + elif file_props.session_type == 'jingle': peerjid = \ file_props.receiver if file_props.type_ == 's' else file_props.sender session = self.get_jingle_session(peerjid, file_props.sid, 'file') @@ -872,6 +874,8 @@ class ConnectionIBBytestream(ConnectionBytestream): if not file_props.direction: # it's socks5 bytestream continue + if file_props.completed: + self.CloseIBBStream(file_props) sid = file_props.sid if file_props.direction[:2] == '|>': # We waitthat other part accept stream @@ -899,17 +903,12 @@ class ConnectionIBBytestream(ConnectionBytestream): file_props.elapsed_time += current_time - file_props.last_time file_props.last_time = current_time file_props.received_len += len(chunk) + if file_props.size == file_props.received_len: + file_props.completed = True gajim.socks5queue.progress_transfer_cb(self.name, file_props) else: - # notify the other side about stream closing - # notify the local user about sucessfull send - # delete the local stream - self.connection.send(nbxmpp.Protocol('iq', - file_props.direction[1:], 'set', - payload=[nbxmpp.Node(nbxmpp.NS_IBB + ' close', - {'sid': file_props.transport_sid})])) - file_props.completed = True + log.debug('Nothing to read, but file not completed') def IBBMessageHandler(self, conn, stanza): """ From 21700051f8aa1cb559ce1fa12aa376896b8f5cbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20H=C3=B6rist?= Date: Wed, 29 Mar 2017 17:56:03 +0200 Subject: [PATCH 04/11] Read/Write file in binary mode --- src/common/jingle_ftstates.py | 2 +- src/common/protocol/bytestream.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/common/jingle_ftstates.py b/src/common/jingle_ftstates.py index 3d5d6b9dc..5c305f78a 100644 --- a/src/common/jingle_ftstates.py +++ b/src/common/jingle_ftstates.py @@ -146,7 +146,7 @@ class StateTransfering(JingleFileTransferStates): def _start_ibb_transfer(self, con): self.jft.file_props.transport_sid = self.jft.transport.sid - fp = open(self.jft.file_props.file_name, 'r') + fp = open(self.jft.file_props.file_name, 'rb') con.OpenStream(self.jft.file_props.sid, self.jft.session.peerjid, fp, blocksize=4096) diff --git a/src/common/protocol/bytestream.py b/src/common/protocol/bytestream.py index be4adcab2..1f6ec2bbd 100644 --- a/src/common/protocol/bytestream.py +++ b/src/common/protocol/bytestream.py @@ -251,7 +251,7 @@ class ConnectionBytestream: if field.getValue() == nbxmpp.NS_IBB: sid = file_props.sid file_props.transport_sid = sid - fp = open(file_props.file_name, 'r') + fp = open(file_props.file_name, 'rb') self.OpenStream(sid, file_props.receiver, fp) raise nbxmpp.NodeProcessed @@ -815,7 +815,7 @@ class ConnectionIBBytestream(ConnectionBytestream): file_props.disconnect_cb = None file_props.continue_cb = None file_props.syn_id = stanza.getID() - file_props.fp = open(file_props.file_name, 'w') + file_props.fp = open(file_props.file_name, 'wb') conn.send(rep) def CloseIBBStream(self, file_props): From 8c51eb72b9b873633ed90f32c82f82176f9ba84d Mon Sep 17 00:00:00 2001 From: Andrey Gursky Date: Thu, 15 Dec 2016 23:41:14 +0100 Subject: [PATCH 05/11] finish jingle file transfer session for files without hash --- src/gui_interface.py | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/src/gui_interface.py b/src/gui_interface.py index d1589062c..e1a89d3cf 100644 --- a/src/gui_interface.py +++ b/src/gui_interface.py @@ -988,11 +988,6 @@ class Interface: session = gajim.connections[account].get_jingle_session(jid=None, sid=file_props.sid) ft_win = self.instances['file_transfers'] - if not file_props.hash_: - # We disn't get the hash, sender probably don't support that - jid = file_props.sender - self.popup_ft_result(account, jid, file_props) - ft_win.set_status(file_props, 'ok') h = Hashes() try: file_ = open(file_props.file_name, 'rb') @@ -1027,14 +1022,25 @@ class Interface: if file_props.stalled or file_props.paused: return - if file_props.type_ == 'r' and file_props.hash_: # we receive a file + if file_props.type_ == 'r': # we receive a file gajim.socks5queue.remove_receiver(file_props.sid, True, True) - # we compare hashes if file_props.session_type == 'jingle': - # Compare hashes in a new thread - self.hashThread = Thread(target=self.__compare_hashes, - args=(account, file_props)) - self.hashThread.start() + if file_props.hash_: + # We compare hashes in a new thread + self.hashThread = Thread(target=self.__compare_hashes, + args=(account, file_props)) + self.hashThread.start() + else: + # We disn't get the hash, sender probably don't support that + jid = file_props.sender + self.popup_ft_result(account, jid, file_props) + ft.set_status(file_props, 'ok') + session = gajim.connections[account].get_jingle_session(jid=None, + sid=file_props.sid) + # End jingle session + # TODO: only if there are no other parallel downloads in this session + if session: + session.end_session() else: # we send a file jid = file_props.receiver gajim.socks5queue.remove_sender(file_props.sid, True, True) From 2ede0224228ed42dd77dcaa4ba7fb1d9627c2759 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20H=C3=B6rist?= Date: Wed, 29 Mar 2017 20:29:50 +0200 Subject: [PATCH 06/11] Dont hash file on filetransfer error --- src/gui_interface.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/gui_interface.py b/src/gui_interface.py index e1a89d3cf..7a5ba2e0a 100644 --- a/src/gui_interface.py +++ b/src/gui_interface.py @@ -1025,7 +1025,7 @@ class Interface: if file_props.type_ == 'r': # we receive a file gajim.socks5queue.remove_receiver(file_props.sid, True, True) if file_props.session_type == 'jingle': - if file_props.hash_: + if file_props.hash_ and file_props.error == 0: # We compare hashes in a new thread self.hashThread = Thread(target=self.__compare_hashes, args=(account, file_props)) @@ -1034,7 +1034,8 @@ class Interface: # We disn't get the hash, sender probably don't support that jid = file_props.sender self.popup_ft_result(account, jid, file_props) - ft.set_status(file_props, 'ok') + if file_props.error == 0: + ft.set_status(file_props, 'ok') session = gajim.connections[account].get_jingle_session(jid=None, sid=file_props.sid) # End jingle session From 0d8c00876489a0726fa40cea1850c154c85f2811 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20H=C3=B6rist?= Date: Wed, 29 Mar 2017 20:30:31 +0200 Subject: [PATCH 07/11] Fix typo in event type --- src/common/events.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/events.py b/src/common/events.py index 9322679fd..3896cc69b 100644 --- a/src/common/events.py +++ b/src/common/events.py @@ -163,7 +163,7 @@ class FileStoppedEvent(FileRequestEvent): type_ = 'file-stopped' class FileHashErrorEvent(FileRequestEvent): - type_ = 'file-hash-rror' + type_ = 'file-hash-error' class JingleIncomingEvent(Event): type_ = 'jingle-incoming' From 3e592c980eaac66d8bf701a5a7de66e4434aa6dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20H=C3=B6rist?= Date: Wed, 29 Mar 2017 20:59:31 +0200 Subject: [PATCH 08/11] Only make pause button active on pause-able transfers --- src/filetransfers_window.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/filetransfers_window.py b/src/filetransfers_window.py index 7ad4fc23e..b008c1c33 100644 --- a/src/filetransfers_window.py +++ b/src/filetransfers_window.py @@ -70,8 +70,7 @@ class FileTransfersWindow: 'notify_ft_complete_checkbox') shall_notify = gajim.config.get('notify_on_file_complete') - self.notify_ft_checkbox.set_active(shall_notify - ) + self.notify_ft_checkbox.set_active(shall_notify) self.model = Gtk.ListStore(GdkPixbuf.Pixbuf, str, str, str, str, int, int, str) self.tree.set_model(self.model) @@ -841,7 +840,7 @@ class FileTransfersWindow: if not is_row_selected: # no selection, disable the buttons self.set_all_insensitive() - elif not is_stopped: + elif not is_stopped and file_props.continue_cb: if is_transfer_active(file_props): # file transfer is active self.toggle_pause_continue(True) From 385d6c3081730f486807dddb3cd41eca1b7d007a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20H=C3=B6rist?= Date: Thu, 30 Mar 2017 00:49:21 +0200 Subject: [PATCH 09/11] On IBB cancel set correct 'to' attr --- src/common/protocol/bytestream.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/common/protocol/bytestream.py b/src/common/protocol/bytestream.py index 1f6ec2bbd..c18ef7f24 100644 --- a/src/common/protocol/bytestream.py +++ b/src/common/protocol/bytestream.py @@ -822,8 +822,11 @@ class ConnectionIBBytestream(ConnectionBytestream): file_props.connected = False file_props.fp.close() file_props.stopped = True - self.connection.send(nbxmpp.Protocol('iq', - file_props.direction[1:], 'set', + to = file_props.receiver + if file_props.direction == '<': + to = file_props.sender + self.connection.send( + nbxmpp.Protocol('iq', to, 'set', payload=[nbxmpp.Node(nbxmpp.NS_IBB + ' close', {'sid':file_props.transport_sid})])) if file_props.completed: @@ -846,7 +849,7 @@ class ConnectionIBBytestream(ConnectionBytestream): base64 encoding that increases size of data by 1/3. """ file_props = FilesProp.getFilePropBySid(sid) - file_props.direction = '|>' + to + file_props.direction = '|>' file_props.block_size = blocksize file_props.fp = fp file_props.seq = 0 @@ -897,7 +900,7 @@ class ConnectionIBBytestream(ConnectionBytestream): if file_props.seq == 65536: file_props.seq = 0 self.last_sent_ibb_id = self.connection.send( - nbxmpp.Protocol(name='iq', to=file_props.direction[1:], + nbxmpp.Protocol(name='iq', to=file_props.receiver, typ='set', payload=[datanode])) current_time = time.time() file_props.elapsed_time += current_time - file_props.last_time From 7cb7bcaae6a7b34a3806f3865f3178191cea9566 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20H=C3=B6rist?= Date: Thu, 30 Mar 2017 03:33:51 +0200 Subject: [PATCH 10/11] Refactor IBB Handlers - Move handling of Data IQs into IBBIqHandler - Call SendHandler with file_props - Save last sent id in file_props.syn_id - Remove some useless checks, now that we call SendHandler with file_props - Send item-not-found error on invalid session id --- src/common/protocol/bytestream.py | 113 +++++++++++++----------------- 1 file changed, 49 insertions(+), 64 deletions(-) diff --git a/src/common/protocol/bytestream.py b/src/common/protocol/bytestream.py index c18ef7f24..28528663c 100644 --- a/src/common/protocol/bytestream.py +++ b/src/common/protocol/bytestream.py @@ -759,7 +759,6 @@ class ConnectionIBBytestream(ConnectionBytestream): def __init__(self): ConnectionBytestream.__init__(self) self._streams = {} - self.last_sent_ibb_id = None def IBBIqHandler(self, conn, stanza): """ @@ -767,12 +766,22 @@ class ConnectionIBBytestream(ConnectionBytestream): """ typ = stanza.getType() log.debug('IBBIqHandler called typ->%s' % typ) - if typ == 'set' and stanza.getTag('open', namespace=nbxmpp.NS_IBB): + if typ == 'set' and stanza.getTag('open'): self.StreamOpenHandler(conn, stanza) - elif typ == 'set' and stanza.getTag('close', namespace=nbxmpp.NS_IBB): + elif typ == 'set' and stanza.getTag('close'): self.StreamCloseHandler(conn, stanza) - elif typ == 'result': - self.SendHandler() + elif typ == 'set' and stanza.getTag('data'): + sid = stanza.getTagAttr('data', 'sid') + file_props = FilesProp.getFilePropByTransportSid(self.name, sid) + if not file_props: + conn.send(nbxmpp.Error(stanza, nbxmpp.ERR_ITEM_NOT_FOUND)) + elif file_props.connected and self.IBBMessageHandler(conn, + stanza): + reply = stanza.buildReply('result') + reply.delChild('data') + conn.send(reply) + elif not file_props.connected: + log.debug('Received IQ for closed filetransfer, IQ dropped') elif typ == 'error': gajim.socks5queue.error_cb() else: @@ -849,7 +858,7 @@ class ConnectionIBBytestream(ConnectionBytestream): base64 encoding that increases size of data by 1/3. """ file_props = FilesProp.getFilePropBySid(sid) - file_props.direction = '|>' + file_props.direction = '>' file_props.block_size = blocksize file_props.fp = fp file_props.seq = 0 @@ -868,50 +877,41 @@ class ConnectionIBBytestream(ConnectionBytestream): file_props.syn_id = syn.getID() return file_props - def SendHandler(self): + def SendHandler(self, file_props): """ Send next portion of data if it is time to do it. Used internally. """ log.debug('SendHandler called') - for file_props in FilesProp.getAllFileProp(): - if not file_props.direction: - # it's socks5 bytestream - continue - if file_props.completed: - self.CloseIBBStream(file_props) - sid = file_props.sid - if file_props.direction[:2] == '|>': - # We waitthat other part accept stream - continue - if file_props.direction[0] == '>': - if file_props.paused: - continue - if not file_props.connected: - #TODO: Reply with out of order error - continue - chunk = file_props.fp.read(file_props.block_size) - if chunk: - datanode = nbxmpp.Node(nbxmpp.NS_IBB + ' data', { - 'sid': file_props.transport_sid, - 'seq': file_props.seq}, base64.b64encode(chunk.encode( - 'utf-8')).decode('utf-8')) - file_props.seq += 1 - file_props.started = True - if file_props.seq == 65536: - file_props.seq = 0 - self.last_sent_ibb_id = self.connection.send( - nbxmpp.Protocol(name='iq', to=file_props.receiver, - typ='set', payload=[datanode])) - current_time = time.time() - file_props.elapsed_time += current_time - file_props.last_time - file_props.last_time = current_time - file_props.received_len += len(chunk) - if file_props.size == file_props.received_len: - file_props.completed = True - gajim.socks5queue.progress_transfer_cb(self.name, - file_props) - else: - log.debug('Nothing to read, but file not completed') + if file_props.completed: + self.CloseIBBStream(file_props) + if file_props.paused: + return + if not file_props.connected: + #TODO: Reply with out of order error + return + chunk = file_props.fp.read(file_props.block_size) + if chunk: + datanode = nbxmpp.Node(nbxmpp.NS_IBB + ' data', { + 'sid': file_props.transport_sid, + 'seq': file_props.seq}, + base64.b64encode(chunk).decode('ascii')) + file_props.seq += 1 + file_props.started = True + if file_props.seq == 65536: + file_props.seq = 0 + file_props.syn_id = self.connection.send( + nbxmpp.Protocol(name='iq', to=file_props.receiver, + typ='set', payload=[datanode])) + current_time = time.time() + file_props.elapsed_time += current_time - file_props.last_time + file_props.last_time = current_time + file_props.received_len += len(chunk) + if file_props.size == file_props.received_len: + file_props.completed = True + gajim.socks5queue.progress_transfer_cb(self.name, + file_props) + else: + log.debug('Nothing to read, but file not completed') def IBBMessageHandler(self, conn, stanza): """ @@ -980,6 +980,7 @@ class ConnectionIBBytestream(ConnectionBytestream): else: conn.send(nbxmpp.Error(stanza, nbxmpp.ERR_ITEM_NOT_FOUND)) + def IBBAllIqHandler(self, conn, stanza): """ Handle remote side reply about if it agree or not to receive our @@ -1001,25 +1002,9 @@ class ConnectionIBBytestream(ConnectionBytestream): else: conn.Event('IBB', 'ERROR ON SEND', file_props) elif stanza.getType() == 'result': - if file_props.direction[0] == '|': - file_props.direction = file_props.direction[1:] - self.SendHandler() - else: - conn.send(nbxmpp.Error(stanza, - nbxmpp.ERR_UNEXPECTED_REQUEST)) + self.SendHandler(file_props) break - else: - if stanza.getTag('data'): - sid = stanza.getTagAttr('data', 'sid') - file_props = FilesProp.getFilePropByTransportSid(self.name, sid) - if file_props.connected and self.IBBMessageHandler(conn, - stanza): - reply = stanza.buildReply('result') - reply.delChild('data') - conn.send(reply) - raise nbxmpp.NodeProcessed - elif syn_id == self.last_sent_ibb_id: - self.SendHandler() + class ConnectionSocks5BytestreamZeroconf(ConnectionSocks5Bytestream): From 3fb12148b99190780609b33c8ec924259adda41a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20H=C3=B6rist?= Date: Sat, 29 Apr 2017 16:51:12 +0200 Subject: [PATCH 11/11] Remove not working proxys --- src/common/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/config.py b/src/common/config.py index 4df5634ef..2ea157d31 100644 --- a/src/common/config.py +++ b/src/common/config.py @@ -380,7 +380,7 @@ class Config: 'http_auth': [opt_str, 'ask'], # yes, no, ask 'dont_ack_subscription': [opt_bool, False, _('Jabberd2 workaround')], # proxy65 for FT - 'file_transfer_proxies': [opt_str, 'proxy.eu.jabber.org, proxy.jabber.ru, proxy.jabbim.cz'], + 'file_transfer_proxies': [opt_str, ''], 'use_ft_proxies': [opt_bool, False, _('If checked, Gajim will use your IP and proxies defined in file_transfer_proxies option for file transfer.'), True], 'test_ft_proxies_on_startup': [opt_bool, False, _('If True, Gajim will test file transfer proxies on startup to be sure it works. Openfire\'s proxies are known to fail this test even if they work.')], 'msgwin-x-position': [opt_int, -1], # Default is to let the wm decide