Skip to content

Commit

Permalink
Improve listen address config in Setup Wizard #1016
Browse files Browse the repository at this point in the history
- Also make 127.0.0.1 the default listen address
- Fallback to 0.0.0.0 if no other local address works
  • Loading branch information
MoojMidge committed Dec 14, 2024
1 parent ac3bffc commit d663fe3
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,9 @@ class XbmcContext(AbstractContext):
'history.remove': 15015,
'history.reset.resume_point': 30674,
'home': 10000,
'httpd': 30628,
'httpd.not.running': 30699,
'httpd.connect.failed': 1001,
'inputstreamhelper.is_installed': 30625,
'isa.enable.check': 30579,
'key.requirement': 30731,
Expand Down
2 changes: 2 additions & 0 deletions resources/lib/youtube_plugin/kodion/network/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
get_client_ip_address,
get_connect_address,
get_http_server,
get_listen_addresses,
httpd_status,
)
from .ip_api import Locator
Expand All @@ -23,6 +24,7 @@
'get_client_ip_address',
'get_connect_address',
'get_http_server',
'get_listen_addresses',
'httpd_status',
'BaseRequestsClass',
'InvalidJSONError',
Expand Down
72 changes: 51 additions & 21 deletions resources/lib/youtube_plugin/kodion/network/http_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,25 +73,30 @@ def __init__(self, *args, **kwargs):
self.whitelist_ips = self._context.get_settings().httpd_whitelist()
super(RequestHandler, self).__init__(*args, **kwargs)

def connection_allowed(self, method):
client_ip = self.client_address[0]
is_whitelisted = client_ip in self.whitelist_ips
conn_allowed = is_whitelisted
def ip_address_status(self, ip_address):
is_whitelisted = ip_address in self.whitelist_ips
ip_allowed = is_whitelisted

if not conn_allowed:
octets = validate_ip_address(client_ip)
if not ip_allowed:
octets = validate_ip_address(ip_address)
for ip_range in self.local_ranges:
if ((any(octets)
and isinstance(ip_range, tuple)
and ip_range[0] <= octets <= ip_range[1])
or client_ip == ip_range):
in_local_range = True
conn_allowed = True
or ip_address == ip_range):
is_local = True
ip_allowed = True
break
else:
in_local_range = False
is_local = False
else:
in_local_range = 'Undetermined'
is_local = None

return ip_allowed, is_local, is_whitelisted

def connection_allowed(self, method):
client_ip = self.client_address[0]
ip_allowed, is_local, is_whitelisted = self.ip_address_status(client_ip)

path_parts = urlsplit(self.path)
if path_parts.query:
Expand Down Expand Up @@ -129,17 +134,19 @@ def connection_allowed(self, method):
'\n\tParams: |{params}|'
'\n\tAddress: |{client_ip}|'
'\n\tWhitelisted: {is_whitelisted}'
'\n\tLocal range: {in_local_range}'
'\n\tLocal range: {is_local}'
'\n\tStatus: {status}'
.format(method=method,
path=path['path'],
params=path['log_params'],
client_ip=client_ip,
is_whitelisted=is_whitelisted,
in_local_range=in_local_range,
status='Allowed' if conn_allowed else 'Blocked'))
is_local=('Undetermined'
if is_local is None else
is_local),
status='Allowed' if ip_allowed else 'Blocked'))
self._context.log_debug(msg)
return conn_allowed, path
return ip_allowed, path

# noinspection PyPep8Naming
def do_GET(self):
Expand Down Expand Up @@ -644,8 +651,8 @@ def get_http_server(address, port, context):
return None


def httpd_status(context):
netloc = get_connect_address(context, as_netloc=True)
def httpd_status(context, address=None):
netloc = get_connect_address(context, as_netloc=True, address=address)
url = urlunsplit((
'http',
netloc,
Expand Down Expand Up @@ -687,10 +694,13 @@ def get_client_ip_address(context):
return ip_address


def get_connect_address(context, as_netloc=False):
settings = context.get_settings()
listen_address = settings.httpd_listen()
listen_port = settings.httpd_port()
def get_connect_address(context, as_netloc=False, address=None):
if address is None:
settings = context.get_settings()
listen_address = settings.httpd_listen()
listen_port = settings.httpd_port()
else:
listen_address, listen_port = address

try:
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
Expand Down Expand Up @@ -734,3 +744,23 @@ def get_connect_address(context, as_netloc=False):
if as_netloc:
return ':'.join((connect_address, str(listen_port)))
return listen_address, listen_port


def get_listen_addresses():
local_ranges = (
((10, 0, 0, 0), (10, 255, 255, 255)),
((172, 16, 0, 0), (172, 31, 255, 255)),
((192, 168, 0, 0), (192, 168, 255, 255)),
)
addresses = ['127.0.0.1', xbmc.getIPAddress()]
for interface in socket.getaddrinfo(socket.gethostname(), None):
address = interface[4][0]
if interface[0] != socket.AF_INET or address in addresses:
continue
octets = validate_ip_address(address)
if not any(octets):
continue
if any(lo <= octets <= hi for lo, hi in local_ranges):
addresses.append(address)
addresses.append('0.0.0.0')
return addresses
27 changes: 8 additions & 19 deletions resources/lib/youtube_plugin/kodion/script_actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
from __future__ import absolute_import, division, unicode_literals

import os
import socket

from .compatibility import parse_qsl, urlsplit, xbmc, xbmcaddon, xbmcvfs
from .constants import (
Expand All @@ -23,8 +22,13 @@
WAIT_END_FLAG,
)
from .context import XbmcContext
from .network import Locator, get_client_ip_address, httpd_status
from .utils import rm_dir, validate_ip_address
from .network import (
Locator,
get_client_ip_address,
get_listen_addresses,
httpd_status,
)
from .utils import rm_dir
from ..youtube import Provider


Expand Down Expand Up @@ -100,22 +104,7 @@ def _config_actions(context, action, *_args):
settings.set_subtitle_download(result == 1)

elif action == 'listen_ip':
local_ranges = (
((10, 0, 0, 0), (10, 255, 255, 255)),
((172, 16, 0, 0), (172, 31, 255, 255)),
((192, 168, 0, 0), (192, 168, 255, 255)),
)
addresses = [xbmc.getIPAddress()]
for interface in socket.getaddrinfo(socket.gethostname(), None):
address = interface[4][0]
if interface[0] != socket.AF_INET or address in addresses:
continue
octets = validate_ip_address(address)
if not any(octets):
continue
if any(lo <= octets <= hi for lo, hi in local_ranges):
addresses.append(address)
addresses += ['127.0.0.1', '0.0.0.0']
addresses = get_listen_addresses()
selected_address = ui.on_select(localize('select.listen.ip'), addresses)
if selected_address != -1:
settings.httpd_listen(addresses[selected_address])
Expand Down
17 changes: 14 additions & 3 deletions resources/lib/youtube_plugin/youtube/helper/yt_setup_wizard.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

from ...kodion.compatibility import urlencode, xbmcvfs
from ...kodion.constants import ADDON_ID, DATA_PATH, WAIT_END_FLAG
from ...kodion.network import httpd_status
from ...kodion.network import httpd_status, get_listen_addresses
from ...kodion.sql_store import PlaybackHistory, SearchHistory
from ...kodion.utils import to_unicode
from ...kodion.utils.datetime_parser import strptime
Expand Down Expand Up @@ -72,9 +72,10 @@ def process_geo_location(context, step, steps, **_kwargs):
def process_default_settings(context, step, steps, **_kwargs):
localize = context.localize
settings = context.get_settings()
ui = context.get_ui()

step += 1
if context.get_ui().on_yes_no_input(
if ui.on_yes_no_input(
'{youtube} - {setup_wizard} ({step}/{steps})'.format(
youtube=localize('youtube'),
setup_wizard=localize('setup_wizard'),
Expand All @@ -100,7 +101,17 @@ def process_default_settings(context, step, steps, **_kwargs):
if settings.cache_size() < 20:
settings.cache_size(20)
if not httpd_status(context):
settings.httpd_listen('0.0.0.0')
port = settings.httpd_port()
for address in get_listen_addresses():
if httpd_status(context, (address, port)):
settings.httpd_listen(address)
break
else:
ui.show_notification(
localize('httpd.connect.failed'),
header=localize('httpd'),
)
settings.httpd_listen('0.0.0.0')
return step


Expand Down
2 changes: 1 addition & 1 deletion resources/settings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1084,7 +1084,7 @@
<group id="http_server" label="30628">
<setting id="kodion.http.listen" type="string" label="30643" help="">
<level>0</level>
<default>0.0.0.0</default>
<default>127.0.0.1</default>
<control format="ip" type="edit">
<heading>30643</heading>
</control>
Expand Down

0 comments on commit d663fe3

Please sign in to comment.