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;
22 namespace Tizen.Network.Nsd
24 internal class DnssdInitializer
26 internal DnssdInitializer()
28 Globals.DnssdInitialize();
33 int ret = Interop.Nsd.Dnssd.Deinitialize();
34 if (ret != (int)DnssdError.None)
36 Log.Error(Globals.LogTag, "Failed to deinitialize Dnssd, Error - " + (DnssdError)ret);
41 /// This class is used for managing local service registration and its properties using DNSSD.
43 public class DnssdService : INsdService
45 private uint _serviceHandle;
46 private string _serviceType;
47 private ushort _dnsRecordtype = 16;
48 private Interop.Nsd.Dnssd.ServiceRegisteredCallback _serviceRegisteredCallback;
51 /// Constructor to create DnssdService instance that sets the serviceType to a given value.
53 /// <param name="serviceType">The DNSSD service type. It is expressed as type followed by protocol, separated by a dot(e.g. "_ftp._tcp").
54 /// It must begin with an underscore, followed by 1-15 characters which may be letters, digits or hyphens.
56 public DnssdService(string serviceType)
58 _serviceType = serviceType;
59 DnssdInitializeCreateService();
62 internal DnssdService(uint service)
64 _serviceHandle = service;
67 internal void DnssdInitializeCreateService()
69 DnssdInitializer dnssdInit = Globals.s_threadDns.Value;
70 Log.Info(Globals.LogTag, "Initialize ThreadLocal<DnssdInitializer> instance = " + dnssdInit);
71 int ret = Interop.Nsd.Dnssd.CreateService(_serviceType, out _serviceHandle);
72 if (ret != (int)DnssdError.None)
74 Log.Error(Globals.LogTag, "Failed to create a local Dnssd service handle, Error - " + (DnssdError)ret);
75 NsdErrorFactory.ThrowDnssdException(ret);
80 /// Name of DNSSD service.
83 /// Set Name for only unregistered service created locally.
84 /// In case of error, null will be returned during get and exception will be thrown during set.
86 /// <exception cref="NotSupportedException">Thrown while setting this property when DNSSD is not supported.</exception>
87 /// <exception cref="InvalidOperationException">Thrown while setting this property when any other error occured.</exception>
93 int ret = Interop.Nsd.Dnssd.GetName(_serviceHandle, out name);
94 if (ret != (int)DnssdError.None)
96 Log.Error(Globals.LogTag, "Failed to get name of service, Error: " + (DnssdError)ret);
105 if (!Globals.s_threadDns.IsValueCreated)
107 DnssdInitializeCreateService();
110 int ret = Interop.Nsd.Dnssd.SetName(_serviceHandle, value.ToString());
111 if (ret != (int)DnssdError.None)
113 Log.Error(Globals.LogTag, "Failed to set name of service, Error: " + (DnssdError)ret);
114 NsdErrorFactory.ThrowDnssdException(ret);
120 /// Type of DNSSD local/remote service.
123 /// In case of error, null will be returned.
130 int ret = Interop.Nsd.Dnssd.GetType(_serviceHandle, out type);
131 if (ret != (int)DnssdError.None)
133 Log.Error(Globals.LogTag, "Failed to get type of service, Error: " + (DnssdError)ret);
142 /// Port number of DNSSD local/remote service.
145 /// Set Port for only unregistered service created locally.
146 /// In case of error, -1 will be returned during get and exception will be thrown during set.
148 /// <exception cref="NotSupportedException">Thrown while setting this property when DNSSD is not supported.</exception>
149 /// <exception cref="InvalidOperationException">Thrown while setting this property when any other error occured.</exception>
155 int ret = Interop.Nsd.Dnssd.GetPort(_serviceHandle, out port);
156 if (ret != (int)DnssdError.None)
158 Log.Error(Globals.LogTag, "Failed to get port number of Dnssd service, Error: " + (DnssdError)ret);
167 if (!Globals.s_threadDns.IsValueCreated)
169 DnssdInitializeCreateService();
172 int ret = Interop.Nsd.Dnssd.SetPort(_serviceHandle, value);
173 if (ret != (int)DnssdError.None)
175 Log.Error(Globals.LogTag, "Failed to set port number of Dnssd service, Error: " + (DnssdError)ret);
176 NsdErrorFactory.ThrowDnssdException(ret);
182 /// IP of DNSSD remote service.
185 /// If there is no IPv4 Address, then IPV4Address would contain null and if there is no IPv6 Address, then IPV6Address would contain null.
186 /// In case of error, null object will be returned.
188 public IPAddressInformation IP
193 int ret = Interop.Nsd.Dnssd.GetIP(_serviceHandle, out IPv4, out IPv6);
194 if (ret != (int)DnssdError.None)
196 Log.Error(Globals.LogTag, "Failed to get the IP of Dnssd remote service, Error: " + (DnssdError)ret);
200 IPAddressInformation IPAddressInstance = new IPAddressInformation(IPv4, IPv6);
201 return IPAddressInstance;
205 private void GetTxtRecord(out ushort length, out byte[] value)
207 int ret = Interop.Nsd.Dnssd.GetAllTxtRecord(_serviceHandle, out length, out value);
208 if (ret != (int)DnssdError.None)
210 Log.Error(Globals.LogTag, "Failed to get the TXT record, Error: " + (DnssdError)ret);
211 NsdErrorFactory.ThrowDnssdException(ret);
216 /// Adds the TXT record.
219 /// TXT record should be added after registering local service using RegisterService().
221 /// <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>
222 /// <param name="value">The value of the TXT record.If null, then "key" will be added with no value. If non-null but value_length is zero, then "key=" will be added with empty value.</param>
223 /// <exception cref="NotSupportedException">Thrown when DNSSD is not supported.</exception>
224 /// <exception cref="InvalidOperationException">Thrown when any other error occured.</exception>
225 public void AddTXTRecord(string key, string value)
227 byte[] byteValue = Encoding.UTF8.GetBytes(value);
228 ushort length = Convert.ToUInt16(byteValue.Length);
229 int ret = Interop.Nsd.Dnssd.AddTxtRecord(_serviceHandle, key, length, byteValue);
230 if (ret != (int)DnssdError.None)
232 Log.Error(Globals.LogTag, "Failed to add the TXT record, Error: " + (DnssdError)ret);
233 NsdErrorFactory.ThrowDnssdException(ret);
238 GetTxtRecord(out txtLength, out txtValue);
240 ret = Interop.Nsd.Dnssd.SetRecord(_serviceHandle, _dnsRecordtype, txtLength, txtValue);
241 if (ret != (int)DnssdError.None)
243 Log.Error(Globals.LogTag, "Failed to set the DNS resource record, Error: " + (DnssdError)ret);
244 NsdErrorFactory.ThrowDnssdException(ret);
249 /// Removes the TXT record.
251 /// <param name="key">The key of the TXT record to be removed.</param>
252 /// <exception cref="NotSupportedException">Thrown when DNSSD is not supported.</exception>
253 /// <exception cref="InvalidOperationException">Thrown when any other error occured.</exception>
254 public void RemoveTXTRecord(string key)
256 int ret = Interop.Nsd.Dnssd.RemoveTxtRecord(_serviceHandle, key);
257 if (ret != (int)DnssdError.None)
259 Log.Error(Globals.LogTag, "Failed to remove the TXT record, Error: " + (DnssdError)ret);
260 NsdErrorFactory.ThrowDnssdException(ret);
265 GetTxtRecord(out txtLength, out txtValue);
268 ret = Interop.Nsd.Dnssd.UnsetRecord(_serviceHandle, _dnsRecordtype);
269 if (ret != (int)DnssdError.None)
271 Log.Error(Globals.LogTag, "Failed to unset the DNS resource record, Error: " + (DnssdError)ret);
272 NsdErrorFactory.ThrowDnssdException(ret);
277 internal void RegisterService()
279 if (Globals.s_threadDns.IsValueCreated)
281 DnssdInitializeCreateService();
284 _serviceRegisteredCallback = (DnssdError result, uint service, IntPtr userData) =>
286 if (result != DnssdError.None)
288 Log.Error(Globals.LogTag, "Failed to finish the registration of Dnssd local service, Error: " + result);
289 NsdErrorFactory.ThrowDnssdException((int)result);
293 int ret = Interop.Nsd.Dnssd.RegisterService(_serviceHandle, _serviceRegisteredCallback, IntPtr.Zero);
294 if (ret != (int)DnssdError.None)
296 Log.Error(Globals.LogTag, "Failed to register the Dnssd local service, Error: " + (DnssdError)ret);
297 NsdErrorFactory.ThrowDnssdException(ret);
301 internal void DeregisterService()
303 int ret = Interop.Nsd.Dnssd.DeregisterService(_serviceHandle);
304 if (ret != (int)DnssdError.None)
306 Log.Error(Globals.LogTag, "Failed to deregister the Dnssd local service, Error: " + (DnssdError)ret);
307 NsdErrorFactory.ThrowDnssdException(ret);
313 int ret = Interop.Nsd.Dnssd.DestroyService(_serviceHandle);
314 if (ret != (int)DnssdError.None)
316 Log.Error(Globals.LogTag, "Failed to destroy the local Dnssd service handle, Error - " + (DnssdError)ret);
322 /// This class manages the IP address properties of DNSSD service.
324 public class IPAddressInformation
326 private string _ipv4, _ipv6;
327 internal IPAddressInformation()
331 internal IPAddressInformation(string ipv4, string ipv6)
338 /// The IP version 4 address of DNSSD service.
340 public IPAddress IPV4Address
344 return IPAddress.Parse(_ipv4);
349 /// The IP version 6 address of DNSSD service.
351 public IPAddress IPV6Address
355 return IPAddress.Parse(_ipv6);