[#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
This commit is contained in:
Calum Lind 2020-04-25 12:44:04 +01:00
parent 76f0bf2e04
commit 62d8749e74
4 changed files with 47 additions and 15 deletions

View File

@ -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

View File

@ -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'))

View File

@ -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

View File

@ -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