-
Notifications
You must be signed in to change notification settings - Fork 78
/
ServiceProfile.cs
172 lines (159 loc) · 5.95 KB
/
ServiceProfile.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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace Makaretu.Dns
{
/// <summary>
/// Defines a specific service that can be discovered.
/// </summary>
/// <seealso cref="ServiceDiscovery.Advertise(ServiceProfile)"/>
public class ServiceProfile
{
// Enforce multicast defaults, especially TTL.
static ServiceProfile()
{
// Make sure MulticastService is inited.
MulticastService.ReferenceEquals(null, null);
}
/// <summary>
/// Creates a new instance of the <see cref="ServiceProfile"/> class.
/// </summary>
/// <remarks>
/// All details must be filled in by the caller, especially the <see cref="Resources"/>.
/// </remarks>
public ServiceProfile()
{
}
/// <summary>
/// Creates a new instance of the <see cref="ServiceProfile"/> class
/// with the specified details.
/// </summary>
/// <param name="instanceName">
/// A unique identifier for the specific service instance.
/// </param>
/// <param name="serviceName">
/// The <see cref="ServiceName">name</see> of the service.
/// </param>
/// <param name="port">
/// The TCP/UDP port of the service.
/// </param>
/// <param name="addresses">
/// The IP addresses of the specific service instance. If <b>null</b> then
/// <see cref="MulticastService.GetIPAddresses"/> is used.
/// </param>
/// <remarks>
/// The SRV, TXT and A/AAAA resoruce records are added to the <see cref="Resources"/>.
/// </remarks>
public ServiceProfile(string instanceName, string serviceName, ushort port, IEnumerable<IPAddress> addresses = null)
{
InstanceName = instanceName;
ServiceName = serviceName;
var fqn = FullyQualifiedName;
var simpleServiceName = ServiceName
.Replace("._tcp", "")
.Replace("._udp", "")
.TrimStart('_');
HostName = $"{InstanceName}.{simpleServiceName}.{Domain}";
Resources.Add(new SRVRecord
{
Name = fqn,
Port = port,
Target = HostName
});
Resources.Add(new TXTRecord
{
Name = fqn,
Strings = { "txtvers=1" }
});
foreach (var address in addresses ?? MulticastService.GetLinkLocalAddresses())
{
Resources.Add(AddressRecord.Create(HostName, address));
}
}
/// <summary>
/// The domain name of the service.
/// </summary>
/// <value>
/// Defaults to "local".
/// </value>
public string Domain { get; } = "local";
/// <summary>
/// A unique name for the service.
/// </summary>
/// <value>
/// Typically of the form "_<i>service</i>._tcp".
/// </value>
/// <remarks>
/// It consists of a pair of DNS labels, following the
/// <see href="https://www.ietf.org/rfc/rfc2782.txt">SRV records</see> convention.
/// The first label of the pair is an underscore character (_) followed by
/// the <see href="https://tools.ietf.org/html/rfc6335">service name</see>.
/// The second label is either "_tcp" (for application
/// protocols that run over TCP) or "_udp" (for all others).
/// </remarks>
public string ServiceName { get; set; }
/// <summary>
/// A unique identifier for the service instance.
/// </summary>
/// <value>
/// Some unique value.
/// </value>
public string InstanceName { get; set; }
/// <summary>
/// The service name and domain.
/// </summary>
/// <value>
/// <see cref="ServiceName"/>.<see cref="Domain"/>
/// </value>
public string QualifiedServiceName => $"{ServiceName}.{Domain}";
/// <summary>
/// The fully qualified name of the instance's host.
/// </summary>
/// <remarks>
/// This can be used to query the address records (A and AAAA)
/// of the service instance.
/// </remarks>
public string HostName { get; set; }
/// <summary>
/// The instance name, service name and domain.
/// </summary>
/// <value>
/// <see cref="InstanceName"/>.<see cref="ServiceName"/>.<see cref="Domain"/>
/// </value>
public string FullyQualifiedName => $"{InstanceName}.{QualifiedServiceName}";
/// <summary>
/// DNS resource records that are used to locate the service instance.
/// </summary>
/// <remarks>
/// All records should have the <see cref="ResourceRecord.Name"/> equal
/// to the <see cref="FullyQualifiedName"/>.
/// <para>
/// At a minimum the SRV and TXT records must be present. Typically A/AAAA
/// records are also present.
/// </para>
/// </remarks>
public List<ResourceRecord> Resources { get; set; } = new List<ResourceRecord>();
/// <summary>
/// Add a property of the service to the TXT record.
/// </summary>
/// <param name="key">
/// The name of the property.
/// </param>
/// <param name="value">
/// The value of the property.
/// </param>
public void AddProperty(string key, string value)
{
var txt = Resources.OfType<TXTRecord>().FirstOrDefault();
if (txt == null)
{
txt = new TXTRecord { Name = FullyQualifiedName };
Resources.Add(txt);
}
txt.Strings.Add(key + "=" + value);
}
}
}