Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add socket-activated systemd service for discovery #218

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions etc/firewalld/services/wsdd.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<short>Web Services Dynamic Discovery host daemon</short>
<description>wsdd implements a Web Service Discovery host daemon. This enables (Samba) hosts, like your local NAS device, to be found by Web Service Discovery Clients like Windows.</description>
<port port="3702" protocol="udp"/>
<port port="37020" protocol="udp"/>
<destination ipv4="239.255.255.250" ipv6="FF02::C"/>
<include service="wsdd-http"/>
</service>
17 changes: 17 additions & 0 deletions etc/systemd/wsdd-discovery.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[Unit]
Description=Web Services Dynamic Discovery service
Documentation=man:wsdd(8)
Requires=wsdd-discovery.socket

[Service]
Type=simple
; Use /etc/default/wsdd for defaults, if it exists
EnvironmentFile=-/etc/default/wsdd
; The service is put into an empty runtime directory chroot,
; i.e. the runtime directory which usually resides under /run
ExecStart=/usr/bin/wsdd --shortlog --chroot=/run/wsdd-discovery --source-port=37020 --no-host --discovery $WSDD_DISCOVERY_PARAMS
DynamicUser=yes
User=wsdd-discovery
Group=wsdd-discovery
RuntimeDirectory=wsdd-discovery
AmbientCapabilities=CAP_SYS_CHROOT
9 changes: 9 additions & 0 deletions etc/systemd/wsdd-discovery.socket
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[Unit]
Description=Web Services Dynamic Discovery API socket
Documentation=man:wsdd(8)

[Socket]
ListenStream=%t/wsdd.socket

[Install]
WantedBy=sockets.target
1 change: 1 addition & 0 deletions etc/systemd/wsdd.defaults
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
# Refer to the wsdd(8) man page for details

WSDD_PARAMS=""
WSDD_DISCOVERY_PARAMS=""
2 changes: 1 addition & 1 deletion etc/ufw/applications.d/wsdd
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[Wsdd]
title=Wsdd
description=Web Service Discovery host daemon implementation
ports=3702/udp|5357/tcp
ports=3702/udp|37020/udp|5357/tcp
19 changes: 18 additions & 1 deletion src/wsdd.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@
except ModuleNotFoundError:
from xml.etree.ElementTree import fromstring as ETfromString

try:
import systemd.daemon
except ModuleNotFoundError:
# Non-systemd host
pass

WSDD_VERSION: str = '0.8'

Expand Down Expand Up @@ -1137,7 +1142,10 @@ async def create_server(self, aio_loop: asyncio.AbstractEventLoop, listen_addres
# It appears mypy is not able to check the argument to create_task and the return value of start_server
# correctly. The docs say start_server returns a coroutine and the create_task takes a coro. And: It works.
# Thus, we ignore type errors here.
if isinstance(listen_address, int) or listen_address.isnumeric():
if isinstance(listen_address, socket.SocketType):
self.server = await aio_loop.create_task(asyncio.start_unix_server( # type: ignore
self.on_connect, sock=listen_address))
elif isinstance(listen_address, int) or listen_address.isnumeric():
self.server = await aio_loop.create_task(asyncio.start_server( # type: ignore
self.on_connect, host='localhost', port=int(listen_address), reuse_address=True,
reuse_port=True))
Expand Down Expand Up @@ -2010,6 +2018,15 @@ def main() -> int:
api_server = None
if args.listen:
api_server = ApiServer(aio_loop, args.listen, nm)
else:
fds = []
try:
fds = systemd.daemon.listen_fds()
except NameError:
# Non-systemd host
pass
if fds:
api_server = ApiServer(aio_loop, socket.socket(fileno=fds[0]), nm)

# get uid:gid before potential chroot'ing
if args.user is not None:
Expand Down
Loading