Skip to content

Commit

Permalink
[Hostlist] Support IPv6 in host lists
Browse files Browse the repository at this point in the history
socket.gethostbyname does not support IPv6 name resolution, and
getaddrinfo() should be used instead for IPv4/v6 dual stack support.

Closes: #376
  • Loading branch information
doadin authored and cas-- committed Feb 18, 2022
1 parent 5f8acab commit c89a366
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 26 deletions.
4 changes: 2 additions & 2 deletions deluge/ui/gtk3/connectionmanager.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import logging
import os
from socket import gaierror, gethostbyname
from socket import gaierror, getaddrinfo
from urllib.parse import urlparse

from gi.repository import Gtk
Expand Down Expand Up @@ -222,7 +222,7 @@ def _update_widget_buttons(self):
__, host, port, __, __, status, __, __ = model[row]

try:
gethostbyname(host)
getaddrinfo(host, None)
except gaierror as ex:
log.error(
'Error resolving host %s to ip: %s', row[HOSTLIST_COL_HOST], ex.args[1]
Expand Down
53 changes: 29 additions & 24 deletions deluge/ui/hostlist.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import logging
import os
import uuid
from socket import gaierror, gethostbyname
from socket import gaierror, getaddrinfo

from twisted.internet import defer

Expand All @@ -22,7 +22,7 @@

DEFAULT_HOST = '127.0.0.1'
DEFAULT_PORT = 58846
LOCALHOST = ('127.0.0.1', 'localhost')
LOCALHOST = ('127.0.0.1', 'localhost', '::1')


def default_hostlist():
Expand All @@ -44,7 +44,7 @@ def validate_host_info(hostname, port):
"""

try:
gethostbyname(hostname)
getaddrinfo(hostname, None)
except gaierror as ex:
raise ValueError('Host %s: %s', hostname, ex.args[1])

Expand Down Expand Up @@ -216,30 +216,35 @@ def on_connect_failed(reason, host_id):
return defer.succeed(status_offline)

try:
ip = gethostbyname(host)
except gaierror as ex:
ips = list({addrinfo[4][0] for addrinfo in getaddrinfo(host, None)})
except (gaierror, IndexError) as ex:
log.warning('Unable to resolve host %s to IP: %s', host, ex.args[1])
return defer.succeed(status_offline)

host_conn_info = (
ip,
port,
'localclient' if not user and host in LOCALHOST else user,
)
if client.connected() and host_conn_info == client.connection_info():
# Currently connected to host_id daemon.
def on_info(info, host_id):
log.debug('Client connected, query info: %s', info)
return host_id, 'Connected', info

return client.daemon.info().addCallback(on_info, host_id)
else:
# Attempt to connect to daemon with host_id details.
c = Client()
d = c.connect(host, port, skip_authentication=True)
d.addCallback(on_connect, c, host_id)
d.addErrback(on_connect_failed, host_id)
return d
host_conn_list = [
(
host_ip,
port,
'localclient' if not user and host_ip in LOCALHOST else user,
)
for host_ip in ips
]

for host_conn_info in host_conn_list:
if client.connected() and host_conn_info == client.connection_info():
# Currently connected to host_id daemon.
def on_info(info, host_id):
log.debug('Client connected, query info: %s', info)
return host_id, 'Connected', info

return client.daemon.info().addCallback(on_info, host_id)
else:
# Attempt to connect to daemon with host_id details.
c = Client()
d = c.connect(host, port, skip_authentication=True)
d.addCallback(on_connect, c, host_id)
d.addErrback(on_connect_failed, host_id)
return d

def update_host(self, host_id, hostname, port, username, password):
"""Update the supplied host id with new connection details.
Expand Down

0 comments on commit c89a366

Please sign in to comment.