From 5517fbd4dd73c868599ebeddf5e7d37fb7699bb2 Mon Sep 17 00:00:00 2001 From: Marcel van der Veldt Date: Sat, 17 May 2025 00:54:41 +0200 Subject: [PATCH] Chore: make webserver IP standout more in log --- music_assistant/controllers/streams.py | 15 +++++++++++++++ music_assistant/controllers/webserver.py | 20 ++++++++++++++++++++ music_assistant/helpers/util.py | 21 ++++++++++++++++++++- music_assistant/helpers/webserver.py | 1 - 4 files changed, 55 insertions(+), 2 deletions(-) diff --git a/music_assistant/controllers/streams.py b/music_assistant/controllers/streams.py index ed6f5200..981bc04d 100644 --- a/music_assistant/controllers/streams.py +++ b/music_assistant/controllers/streams.py @@ -9,6 +9,7 @@ the upnp callbacks and json rpc api for slimproto clients. from __future__ import annotations import asyncio +import logging import os import urllib.parse from collections.abc import AsyncGenerator @@ -266,6 +267,20 @@ class StreamsController(CoreController): # start the webserver self.publish_port = config.get_value(CONF_BIND_PORT) self.publish_ip = config.get_value(CONF_PUBLISH_IP) + # print a big fat message in the log where the streamserver is running + # because this is a common source of issues for people with more complex setups + self.logger.log( + logging.INFO if self.mass.config.onboard_done else logging.WARNING, + "\n\n################################################################################\n" + "Starting streamserver on %s:%s\n" + "This is the IP address that is communicated to players.\n" + "If this is incorrect, audio will not play!\n" + "See the documentation how to configure the publish IP for the Streamserver\n" + "in Settings --> Core modules --> Streamserver\n" + "################################################################################\n", + self.publish_ip, + self.publish_port, + ) await self._server.setup( bind_ip=config.get_value(CONF_BIND_IP), bind_port=self.publish_port, diff --git a/music_assistant/controllers/webserver.py b/music_assistant/controllers/webserver.py index 2a6a4109..69bf5679 100644 --- a/music_assistant/controllers/webserver.py +++ b/music_assistant/controllers/webserver.py @@ -190,6 +190,26 @@ class WebserverController(CoreController): self.publish_port = config.get_value(CONF_BIND_PORT) self.publish_ip = default_publish_ip bind_ip = config.get_value(CONF_BIND_IP) + # print a big fat message in the log where the webserver is running + # because this is a common source of issues for people with more complex setups + if not self.mass.config.onboard_done: + self.logger.warning( + "\n\n################################################################################\n" + "Starting webserver on %s:%s - base url: %s\n" + "If this is incorrect, see the documentation how to configure the Webserver\n" + "in Settings --> Core modules --> Webserver\n" + "################################################################################\n", + bind_ip, + self.publish_port, + base_url, + ) + else: + self.logger.info( + "Starting webserver on %s:%s - base url: %s\n#\n", + bind_ip, + self.publish_port, + base_url, + ) await self._server.setup( bind_ip=bind_ip, bind_port=self.publish_port, diff --git a/music_assistant/helpers/util.py b/music_assistant/helpers/util.py index 6dbbaadf..64d38117 100644 --- a/music_assistant/helpers/util.py +++ b/music_assistant/helpers/util.py @@ -226,6 +226,19 @@ async def get_ip_addresses(include_ipv6: bool = False) -> tuple[str, ...]: def call() -> tuple[str, ...]: result: list[tuple[int, str]] = [] + # try to get the primary IP address + # this is the IP address of the default route + _sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + _sock.settimeout(0) + try: + # doesn't even have to be reachable + _sock.connect(("10.254.254.254", 1)) + primary_ip = _sock.getsockname()[0] + except Exception: + primary_ip = "" + finally: + _sock.close() + # get all IP addresses of all network interfaces adapters = ifaddr.get_adapters() for adapter in adapters: for ip in adapter.ips: @@ -238,7 +251,9 @@ async def get_ip_addresses(include_ipv6: bool = False) -> tuple[str, ...]: if ip_str.startswith(("::1", "::ffff:", "fe80")): # filter out IPv6 loopback/link-local address continue - if ip_str.startswith(("192.168.",)): + if ip_str == primary_ip: + score = 10 + elif ip_str.startswith(("192.168.",)): # we rank the 192.168 range a bit higher as its most # often used as the private network subnet score = 2 @@ -255,6 +270,10 @@ async def get_ip_addresses(include_ipv6: bool = False) -> tuple[str, ...]: return await asyncio.to_thread(call) +async def get_primary_ip_address() -> str | None: + """Return the primary IP address of the system.""" + + async def is_port_in_use(port: int) -> bool: """Check if port is in use.""" diff --git a/music_assistant/helpers/webserver.py b/music_assistant/helpers/webserver.py index 137ad925..4dac602a 100644 --- a/music_assistant/helpers/webserver.py +++ b/music_assistant/helpers/webserver.py @@ -56,7 +56,6 @@ class Webserver: "max_field_size": MAX_LINE_SIZE, }, ) - self.logger.info("Starting server on %s:%s - base url: %s", bind_ip, bind_port, base_url) self._apprunner = web.AppRunner(self._webapp, access_log=None, shutdown_timeout=10) # add static routes if self._static_routes: -- 2.34.1