2 * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 using System.Threading;
21 using System.Runtime.InteropServices;
22 using System.Collections.Generic;
24 namespace Tizen.Network.Nsd
26 internal class DnssdInitializer
28 internal DnssdInitializer()
30 Globals.DnssdInitialize();
35 int ret = Interop.Nsd.Dnssd.Deinitialize();
36 if (ret != (int)DnssdError.None)
38 Log.Error(Globals.LogTag, "Failed to deinitialize Dnssd, Error - " + (DnssdError)ret);
43 /// This class is used for managing the local service registration and its properties using DNS-SD.
45 /// <since_tizen> 4 </since_tizen>
46 public class DnssdService : INsdService
48 private uint _serviceHandle;
49 private string _serviceType;
50 private ushort _dnsRecordtype = 16;
51 private Interop.Nsd.Dnssd.ServiceRegisteredCallback _serviceRegisteredCallback;
54 /// The constructor to create the DnssdService instance that sets the serviceType to a given value.
56 /// <since_tizen> 4 </since_tizen>
57 /// <param name="serviceType">The DNS-SD service type. It is expressed as a type followed by the protocol, separated by a dot (For example, "_ftp._tcp").
58 /// It must begin with an underscore followed by 1-15 characters, which may be letters, digits, or hyphens.
60 /// <feature>http://tizen.org/feature/network.service_discovery.dnssd</feature>
61 /// <exception cref="NotSupportedException">Thrown while setting this property when DNS-SD is not supported.</exception>
62 /// <exception cref="ArgumentException">Thrown when the serviceType is set to null.</exception>
63 public DnssdService(string serviceType)
65 _serviceType = serviceType;
66 DnssdInitializeCreateService();
69 internal DnssdService(uint service)
71 _serviceHandle = service;
74 internal void DnssdInitializeCreateService()
76 DnssdInitializer dnssdInit = Globals.s_threadDns.Value;
77 Log.Info(Globals.LogTag, "Initialize ThreadLocal<DnssdInitializer> instance = " + dnssdInit);
78 int ret = Interop.Nsd.Dnssd.CreateService(_serviceType, out _serviceHandle);
79 if (ret != (int)DnssdError.None)
81 Log.Error(Globals.LogTag, "Failed to create a local Dnssd service handle, Error - " + (DnssdError)ret);
82 NsdErrorFactory.ThrowDnssdException(ret);
87 /// Name of the DNS-SD service.
90 /// Set the name for only an unregistered service created locally.
91 /// It may be up to 63 bytes.
92 /// In case of an error, null will be returned during get and exception will be thrown during set.
94 /// <since_tizen> 4 </since_tizen>
95 /// <feature>http://tizen.org/feature/network.service_discovery.dnssd</feature>
96 /// <exception cref="NotSupportedException">Thrown while setting this property when DNS-SD is not supported.</exception>
97 /// <exception cref="ArgumentException">Thrown when the name value is set to null.</exception>
98 /// <exception cref="InvalidOperationException">Thrown while setting this property when any other error occurred.</exception>
104 int ret = Interop.Nsd.Dnssd.GetName(_serviceHandle, out name);
105 if (ret != (int)DnssdError.None)
107 Log.Error(Globals.LogTag, "Failed to get name of service, Error: " + (DnssdError)ret);
116 if (!Globals.s_threadDns.IsValueCreated)
118 DnssdInitializeCreateService();
121 int ret = Interop.Nsd.Dnssd.SetName(_serviceHandle, value);
122 if (ret != (int)DnssdError.None)
124 Log.Error(Globals.LogTag, "Failed to set name of service, Error: " + (DnssdError)ret);
125 NsdErrorFactory.ThrowDnssdException(ret);
131 /// Type of the DNS-SD local or remote service.
134 /// It is expressed as a type followed by the protocol, separated by a dot (For example, "_ftp._tcp").
135 /// It must begin with an underscore followed by 1-15 characters, which may be letters, digits, or hyphens.
136 /// In case of an error, null will be returned.
138 /// <since_tizen> 4 </since_tizen>
144 int ret = Interop.Nsd.Dnssd.GetType(_serviceHandle, out type);
145 if (ret != (int)DnssdError.None)
147 Log.Error(Globals.LogTag, "Failed to get type of service, Error: " + (DnssdError)ret);
156 /// Port number of the DNS-SD local or remote service.
159 /// Set the port for only an unregistered service created locally. The default value of the port is 0.
160 /// In case of an error, -1 will be returned during get and exception will be thrown during set.
162 /// <since_tizen> 4 </since_tizen>
163 /// <feature>http://tizen.org/feature/network.service_discovery.dnssd</feature>
164 /// <exception cref="NotSupportedException">Thrown while setting this property when DNS-SD is not supported.</exception>
165 /// <exception cref="ArgumentException">Thrown if the value of port is set to less than 0 or more than 65535.</exception>
166 /// <exception cref="InvalidOperationException">Thrown while setting this property when any other error occurred.</exception>
172 int ret = Interop.Nsd.Dnssd.GetPort(_serviceHandle, out port);
173 if (ret != (int)DnssdError.None)
175 Log.Error(Globals.LogTag, "Failed to get port number of Dnssd service, Error: " + (DnssdError)ret);
184 if (!Globals.s_threadDns.IsValueCreated)
186 DnssdInitializeCreateService();
189 int ret = Interop.Nsd.Dnssd.SetPort(_serviceHandle, value);
190 if (ret != (int)DnssdError.None)
192 Log.Error(Globals.LogTag, "Failed to set port number of Dnssd service, Error: " + (DnssdError)ret);
193 NsdErrorFactory.ThrowDnssdException(ret);
199 /// IP address of the DNS-SD remote service.
202 /// If the remote service has no IPv4 Address, then IPv4Address would contain null and if it has no IPv6 Address, then IPv6Address would contain null.
203 /// In case of an error, null object will be returned.
205 /// <since_tizen> 4 </since_tizen>
206 public IPAddressInformation IP
211 int ret = Interop.Nsd.Dnssd.GetIP(_serviceHandle, out IPv4, out IPv6);
212 if (ret != (int)DnssdError.None)
214 Log.Error(Globals.LogTag, "Failed to get the IP of Dnssd remote service, Error: " + (DnssdError)ret);
218 IPAddressInformation IPAddressInstance = new IPAddressInformation(IPv4, IPv6);
219 return IPAddressInstance;
224 /// Returns raw TXT records.
226 /// <returns>Returns empty bytes array in case TXT record has not been set, else returns raw TXT record.</returns>
227 /// <since_tizen> 9 </since_tizen>
228 /// <feature>http://tizen.org/feature/network.service_discovery.dnssd</feature>
229 /// <exception cref="NotSupportedException">Thrown when DNS-SD is not supported.</exception>
230 /// <exception cref="InvalidOperationException">Thrown when any other error occurred.</exception>
231 public byte[] GetRawTXTRecords()
233 int ret = Interop.Nsd.Dnssd.GetAllTxtRecord(_serviceHandle, out ushort length, out IntPtr data);
234 if (ret != (int)DnssdError.None)
236 Log.Error(Globals.LogTag, "Failed to get the TXT record, Error: " + (DnssdError)ret);
237 NsdErrorFactory.ThrowDnssdException(ret);
239 byte[] value = Array.Empty<byte>();
242 value = new byte[length];
243 Marshal.Copy(data, value, 0, length);
244 Interop.Libc.Free(data);
250 /// Adds the TXT record.
253 /// TXT record should be added after registering the local service using RegisterService().
255 /// <since_tizen> 4 </since_tizen>
256 /// <param name="key">The key of the TXT record. It must be a null-terminated string with 9 characters or fewer excluding null. It is case insensitive.</param>
257 /// <param name="value">The value of the TXT record. If null, then "key" will be added with no value. If non-null but the value_length is zero, then "key=" will be added with an empty value.</param>
258 /// <feature>http://tizen.org/feature/network.service_discovery.dnssd</feature>
259 /// <exception cref="NotSupportedException">Thrown when DNS-SD is not supported.</exception>
260 /// <exception cref="ArgumentException">Thrown when the value of the key is null.</exception>
261 /// <exception cref="InvalidOperationException">Thrown when any other error occurred.</exception>
262 public void AddTXTRecord(string key, string value)
264 byte[] byteValue = Encoding.UTF8.GetBytes(value);
265 ushort length = Convert.ToUInt16(byteValue.Length);
266 int ret = Interop.Nsd.Dnssd.AddTxtRecord(_serviceHandle, key, length, byteValue);
267 if (ret != (int)DnssdError.None)
269 Log.Error(Globals.LogTag, "Failed to add the TXT record, Error: " + (DnssdError)ret);
270 NsdErrorFactory.ThrowDnssdException(ret);
272 byte[] txtValue = GetRawTXTRecords();
273 ret = Interop.Nsd.Dnssd.SetRecord(_serviceHandle, _dnsRecordtype, (ushort)txtValue.Length, txtValue);
274 if (ret != (int)DnssdError.None)
276 Log.Error(Globals.LogTag, "Failed to set the DNS resource record, Error: " + (DnssdError)ret);
277 NsdErrorFactory.ThrowDnssdException(ret);
281 /// Removes the TXT record.
283 /// <since_tizen> 4 </since_tizen>
284 /// <param name="key">The key of the TXT record to be removed.</param>
285 /// <feature>http://tizen.org/feature/network.service_discovery.dnssd</feature>
286 /// <exception cref="NotSupportedException">Thrown when DNS-SD is not supported.</exception>
287 /// <exception cref="ArgumentException">Thrown when the value of the key is null.</exception>
288 /// <exception cref="InvalidOperationException">Thrown when any other error occurred.</exception>
289 public void RemoveTXTRecord(string key)
291 int ret = Interop.Nsd.Dnssd.RemoveTxtRecord(_serviceHandle, key);
292 if (ret != (int)DnssdError.None)
294 Log.Error(Globals.LogTag, "Failed to remove the TXT record, Error: " + (DnssdError)ret);
295 NsdErrorFactory.ThrowDnssdException(ret);
300 /// Registers the DNS-SD local service for publishing.
302 /// Name of the service must be set.
303 /// <since_tizen> 4 </since_tizen>
304 /// <privilege>http://tizen.org/privilege/internet</privilege>
305 /// <feature>http://tizen.org/feature/network.service_discovery.dnssd</feature>
306 /// <exception cref="InvalidOperationException">Thrown when any other error occurred.</exception>
307 /// <exception cref="NotSupportedException">Thrown when DNS-SD is not supported.</exception>
308 /// <exception cref="UnauthorizedAccessException">Thrown when the permission is denied.</exception>
309 public void RegisterService()
311 if (!Globals.s_threadDns.IsValueCreated)
313 DnssdInitializeCreateService();
316 _serviceRegisteredCallback = (DnssdError result, uint service, IntPtr userData) =>
318 if (result != DnssdError.None)
320 Log.Error(Globals.LogTag, "Failed to finish the registration of Dnssd local service, Error: " + result);
321 NsdErrorFactory.ThrowDnssdException((int)result);
325 int ret = Interop.Nsd.Dnssd.RegisterService(_serviceHandle, _serviceRegisteredCallback, IntPtr.Zero);
326 if (ret != (int)DnssdError.None)
328 Log.Error(Globals.LogTag, "Failed to register the Dnssd local service, Error: " + (DnssdError)ret);
329 NsdErrorFactory.ThrowDnssdException(ret);
334 /// Deregisters the DNS-SD local service.
337 /// A local service registered using RegisterService() must be passed.
339 /// <since_tizen> 4 </since_tizen>
340 /// <feature>http://tizen.org/feature/network.service_discovery.dnssd</feature>
341 /// <exception cref="InvalidOperationException">Thrown when any other error occurred.</exception>
342 /// <exception cref="NotSupportedException">Thrown when DNS-SD is not supported.</exception>
343 public void DeregisterService()
345 int ret = Interop.Nsd.Dnssd.DeregisterService(_serviceHandle);
346 if (ret != (int)DnssdError.None)
348 Log.Error(Globals.LogTag, "Failed to deregister the Dnssd local service, Error: " + (DnssdError)ret);
349 NsdErrorFactory.ThrowDnssdException(ret);
353 #region IDisposable Support
354 private bool _disposedValue = false; // To detect redundant calls
356 private void Dispose(bool disposing)
362 if (_serviceHandle != 0)
364 int ret = Interop.Nsd.Dnssd.DestroyService(_serviceHandle);
365 if (ret != (int)DnssdError.None)
367 Log.Error(Globals.LogTag, "Failed to destroy the local Dnssd service handle, Error - " + (DnssdError)ret);
372 _disposedValue = true;
377 /// Destroys the DnssdService object.
385 /// Disposes the memory allocated to unmanaged resources.
387 /// <since_tizen> 4 </since_tizen>
388 public void Dispose()
391 GC.SuppressFinalize(this);
397 /// This class manages the IP address properties of the DNS-SD service.
399 /// <since_tizen> 4 </since_tizen>
400 public class IPAddressInformation
402 private string _ipv4, _ipv6;
403 internal IPAddressInformation()
407 internal IPAddressInformation(string ipv4, string ipv6)
414 /// The IP version 4 address of the DNS-SD service.
416 /// <since_tizen> 4 </since_tizen>
417 public IPAddress IPv4Address
422 return IPAddress.Parse("0.0.0.0");
423 return IPAddress.Parse(_ipv4);
428 /// The IP version 6 address of the DNS-SD service.
430 /// <since_tizen> 4 </since_tizen>
431 public IPAddress IPv6Address
436 return IPAddress.Parse("0:0:0:0:0:0:0:0");
437 return IPAddress.Parse(_ipv6);