/
SystemdNotifier.cs
77 lines (64 loc) · 2.25 KB
/
SystemdNotifier.cs
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.Net.Sockets;
using System.Runtime.Versioning;
namespace Microsoft.Extensions.Hosting.Systemd
{
/// <summary>
/// Provides support to notify systemd about the service status.
/// </summary>
[UnsupportedOSPlatform("browser")]
public class SystemdNotifier : ISystemdNotifier
{
private const string NOTIFY_SOCKET = "NOTIFY_SOCKET";
private readonly string? _socketPath;
/// <summary>
/// Instantiates a new <see cref="SystemdNotifier"/> and sets the notify socket path.
/// </summary>
public SystemdNotifier() :
this(GetNotifySocketPath())
{ }
// For testing
internal SystemdNotifier(string? socketPath)
{
_socketPath = socketPath;
}
/// <inheritdoc />
public bool IsEnabled => _socketPath != null;
/// <inheritdoc />
public void Notify(ServiceState state)
{
if (!IsEnabled)
{
return;
}
using (var socket = new Socket(AddressFamily.Unix, SocketType.Dgram, ProtocolType.Unspecified))
{
var endPoint = new UnixDomainSocketEndPoint(_socketPath!);
socket.Connect(endPoint);
// It's safe to do a non-blocking call here: messages sent here are much
// smaller than kernel buffers so we won't get blocked.
socket.Send(state.GetData());
}
}
private static string? GetNotifySocketPath()
{
string? socketPath = Environment.GetEnvironmentVariable(NOTIFY_SOCKET);
if (string.IsNullOrEmpty(socketPath))
{
return null;
}
// Support abstract socket paths.
if (socketPath[0] == '@')
{
socketPath = string.Create(socketPath.Length, socketPath, (buffer, state) =>
{
buffer[0] = '\0';
state.AsSpan(1).CopyTo(buffer.Slice(1));
});
}
return socketPath;
}
}
}