summaryrefslogtreecommitdiffstats
path: root/sshuttle/sdnotify.py
blob: 72e827b61fd0ccf11f03729dd67569f504323bde (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
"""When sshuttle is run via a systemd service file, we can communicate
to systemd about the status of the sshuttle process. In particular, we
can send READY status to tell systemd that sshuttle has completed
startup and send STOPPING to indicate that sshuttle is beginning
shutdown.

For details, see:
https://www.freedesktop.org/software/systemd/man/sd_notify.html
"""

import socket
import os

from sshuttle.helpers import debug1


def _notify(message):
    """Send a notification message to systemd."""
    addr = os.environ.get("NOTIFY_SOCKET", None)

    if not addr or len(addr) == 1 or addr[0] not in ('/', '@'):
        return False

    addr = '\0' + addr[1:] if addr[0] == '@' else addr

    try:
        sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
    except (OSError, IOError) as e:
        debug1("Error creating socket to notify systemd: %s\n" % e)
        return False

    if not message:
        return False

    assert isinstance(message, bytes)

    try:
        return sock.sendto(message, addr) > 0
    except (OSError, IOError) as e:
        debug1("Error notifying systemd: %s\n" % e)
        return False


def send(*messages):
    """Send multiple messages to systemd."""
    return _notify(b'\n'.join(messages))


def ready():
    """Constructs a message that is appropriate to send upon completion of
sshuttle startup."""
    return b"READY=1"


def stop():
    """Constructs a message that is appropriate to send when sshuttle is
beginning to shutdown."""
    return b"STOPPING=1"


def status(message):
    """Constructs a status message to be sent to systemd."""
    return b"STATUS=%s" % message.encode('utf8')