From 62d8749e7404f247494fd091f8a17a1c58735606 Mon Sep 17 00:00:00 2001 From: Calum Lind Date: Sat, 25 Apr 2020 12:44:04 +0100 Subject: [#3348] Fix TypeError adding peers to torrents Python3 has stricter type checking and passing a port as string results in libtorrent raising a TypeError. Fixed by casting port to int, along with refactoring to ensure ipv6 is correctly parsing and a useful error is output to user with invalid ip or port details. https://dev.deluge-torrent.org/ticket/3348 --- deluge/core/torrent.py | 4 ++-- deluge/tests/test_torrent.py | 8 ++++++++ deluge/ui/gtk3/common.py | 29 ++++++++++++++++++++++++++++- deluge/ui/gtk3/peers_tab.py | 21 +++++++++------------ 4 files changed, 47 insertions(+), 15 deletions(-) diff --git a/deluge/core/torrent.py b/deluge/core/torrent.py index f40b58834..b69909cbb 100644 --- a/deluge/core/torrent.py +++ b/deluge/core/torrent.py @@ -1212,8 +1212,8 @@ class Torrent(object): bool: True is successful, otherwise False """ try: - self.handle.connect_peer((peer_ip, peer_port), 0) - except RuntimeError as ex: + self.handle.connect_peer((peer_ip, int(peer_port)), 0) + except (RuntimeError, ValueError) as ex: log.debug('Unable to connect to peer: %s', ex) return False return True diff --git a/deluge/tests/test_torrent.py b/deluge/tests/test_torrent.py index 70fec4771..3d47a8ae3 100644 --- a/deluge/tests/test_torrent.py +++ b/deluge/tests/test_torrent.py @@ -345,3 +345,11 @@ class TorrentTestCase(BaseTestCase): result = self.torrent.rename_files([[0, 'new_рбачёв']]) self.assertIsNone(result) + + def test_connect_peer_port(self): + """Test to ensure port is int for libtorrent""" + atp = self.get_torrent_atp('test_torrent.file.torrent') + handle = self.session.add_torrent(atp) + self.torrent = Torrent(handle, {}) + self.assertFalse(self.torrent.connect_peer('127.0.0.1', 'text')) + self.assertTrue(self.torrent.connect_peer('127.0.0.1', '1234')) diff --git a/deluge/ui/gtk3/common.py b/deluge/ui/gtk3/common.py index 855f6680e..0be3bff35 100644 --- a/deluge/ui/gtk3/common.py +++ b/deluge/ui/gtk3/common.py @@ -29,7 +29,7 @@ from gi.repository.Gtk import ( SortType, ) -from deluge.common import PY2, get_pixmap, osx_check, windows_check +from deluge.common import PY2, get_pixmap, is_ip, osx_check, windows_check log = logging.getLogger(__name__) @@ -393,3 +393,30 @@ def get_clipboard_text(): def windowing(like): return like.lower() in str(type(Display.get_default())).lower() + + +def parse_ip_port(text): + """Return an IP and port from text. + + Parses both IPv4 and IPv6. + + Params: + text (str): Text to be parsed for IP and port. + + Returns: + tuple: (ip (str), port (int)) + + """ + if '.' in text: + # ipv4 + ip, __, port = text.rpartition(':') + elif '[' in text: + # ipv6 + ip, __, port = text.partition('[')[2].partition(']:') + else: + return None, None + + if ip and is_ip(ip) and port.isdigit(): + return ip, int(port) + else: + return None, None diff --git a/deluge/ui/gtk3/peers_tab.py b/deluge/ui/gtk3/peers_tab.py index 33395b9ba..fa79d84a1 100644 --- a/deluge/ui/gtk3/peers_tab.py +++ b/deluge/ui/gtk3/peers_tab.py @@ -32,6 +32,7 @@ from .common import ( icon_downloading, icon_seeding, load_pickled_state_file, + parse_ip_port, save_pickled_state_file, ) from .torrentdetails import Tab @@ -376,19 +377,15 @@ class PeersTab(Tab): peer_dialog = builder.get_object('connect_peer_dialog') txt_ip = builder.get_object('txt_ip') response = peer_dialog.run() + if response: value = txt_ip.get_text() - if value and ':' in value: - if ']' in value: - # ipv6 - ip = value.split(']')[0][1:] - port = value.split(']')[1][1:] - else: - # ipv4 - ip = value.split(':')[0] - port = value.split(':')[1] - if deluge.common.is_ip(ip): - log.debug('adding peer %s to %s', value, self.torrent_id) - client.core.connect_peer(self.torrent_id, ip, port) + ip, port = parse_ip_port(value) + if ip and port: + log.info('Adding peer IP: %s port: %s to %s', ip, port, self.torrent_id) + client.core.connect_peer(self.torrent_id, ip, port) + else: + log.error('Error parsing peer "%s"', value) + peer_dialog.destroy() return True -- cgit