[DNS-SD] Implement Basic DNS SD CAPI 31/58331/3
authorSaurav Babu <saurav.babu@samsung.com>
Fri, 29 Jan 2016 10:23:53 +0000 (15:53 +0530)
committerYu Jiung <jiung.yu@samsung.com>
Fri, 5 Feb 2016 02:25:06 +0000 (11:25 +0900)
Change-Id: Ie7fd341515aeebe62f006fb7212b06f60d5290eb
Signed-off-by: Saurav Babu <saurav.babu@samsung.com>
14 files changed:
CMakeLists.txt
packaging/capi-network-nsd.manifest [new file with mode: 0644]
packaging/capi-network-nsd.spec
packaging/libnsd-dns-sd.manifest [new file with mode: 0644]
packaging/nsd-tests.manifest [new file with mode: 0644]
pkgconfig/CMakeLists.txt [new file with mode: 0644]
pkgconfig/nsd-dns-sd/CMakeLists.txt [new file with mode: 0644]
pkgconfig/nsd-dns-sd/nsd-dns-sd.pc.in [new file with mode: 0644]
src/CMakeLists.txt [new file with mode: 0644]
src/dns-sd/CMakeLists.txt [new file with mode: 0644]
src/dns-sd/dns-sd-util.h [new file with mode: 0644]
src/dns-sd/dns-sd.c [new file with mode: 0644]
test/CMakeLists.txt [new file with mode: 0644]
test/dns-sd-test.c [new file with mode: 0644]

index fbeed9c..af3f383 100644 (file)
@@ -98,3 +98,6 @@ SET(TARGET_NSD_TESTS "nsd-tests")
 
 
 ADD_SUBDIRECTORY(include)
+ADD_SUBDIRECTORY(src)
+ADD_SUBDIRECTORY(pkgconfig)
+ADD_SUBDIRECTORY(test)
diff --git a/packaging/capi-network-nsd.manifest b/packaging/capi-network-nsd.manifest
new file mode 100644 (file)
index 0000000..a76fdba
--- /dev/null
@@ -0,0 +1,5 @@
+<manifest>
+       <request>
+               <domain name="_" />
+       </request>
+</manifest>
index d89bc7b..74179b1 100644 (file)
@@ -5,6 +5,9 @@ Release:    1
 Group:      System/Network
 License:    Apache-2.0
 Source0:    %{name}-%{version}.tar.gz
+Source1001:    capi-network-nsd.manifest
+Source1002:    libnsd-dns-sd.manifest
+Source1003:    nsd-tests.manifest
 BuildRequires:  cmake
 BuildRequires:  pkgconfig(capi-base-common)
 BuildRequires:  pkgconfig(dlog)
@@ -39,6 +42,12 @@ Network Service Discovery library for DNS-SD
 
 %prep
 %setup -q
+chmod 644 %{SOURCE1001}
+chmod 644 %{SOURCE1002}
+chmod 644 %{SOURCE1003}
+cp -a %{SOURCE1001} .
+cp -a %{SOURCE1002} .
+cp -a %{SOURCE1003} .
 
 %build
 %if 0%{?sec_build_binary_debug_enable}
@@ -69,10 +78,19 @@ rm -rf %{buildroot}
 %postun -n libnsd-dns-sd -p /sbin/ldconfig
 
 %files
+%manifest capi-network-nsd.manifest
 %license LICENSE
 
 %files devel
 %{_includedir}/nsd/*.h
+%{_libdir}/pkgconfig/*.pc
+%{_libdir}/*.so
+
+%files tests
+%manifest nsd-tests.manifest
+%attr(755,root,root) %{_bindir}/dns-sd-test
 
 %files -n libnsd-dns-sd
+%manifest libnsd-dns-sd.manifest
 %license LICENSE
+%{_libdir}/libnsd-dns-sd.so.*
diff --git a/packaging/libnsd-dns-sd.manifest b/packaging/libnsd-dns-sd.manifest
new file mode 100644 (file)
index 0000000..50eefc9
--- /dev/null
@@ -0,0 +1,5 @@
+<manifest>
+       <request>
+               <domain name="_" />
+       </request>
+</manifest>
\ No newline at end of file
diff --git a/packaging/nsd-tests.manifest b/packaging/nsd-tests.manifest
new file mode 100644 (file)
index 0000000..50eefc9
--- /dev/null
@@ -0,0 +1,5 @@
+<manifest>
+       <request>
+               <domain name="_" />
+       </request>
+</manifest>
\ No newline at end of file
diff --git a/pkgconfig/CMakeLists.txt b/pkgconfig/CMakeLists.txt
new file mode 100644 (file)
index 0000000..31347e3
--- /dev/null
@@ -0,0 +1,18 @@
+# Copyright (c) 2014-2015 Samsung Electronics Co., Ltd All Rights Reserved
+#
+#    Licensed under the Apache License, Version 2.0 (the "License");
+#    you may not use this file except in compliance with the License.
+#    You may obtain a copy of the License at
+#
+#        http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+#
+# @file        CMakeLists.txt
+#
+
+ADD_SUBDIRECTORY(nsd-dns-sd)
diff --git a/pkgconfig/nsd-dns-sd/CMakeLists.txt b/pkgconfig/nsd-dns-sd/CMakeLists.txt
new file mode 100644 (file)
index 0000000..3a5b257
--- /dev/null
@@ -0,0 +1,24 @@
+# Copyright (c) 2014-2015 Samsung Electronics Co., Ltd All Rights Reserved
+#
+#    Licensed under the Apache License, Version 2.0 (the "License");
+#    you may not use this file except in compliance with the License.
+#    You may obtain a copy of the License at
+#
+#        http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+#
+# @file        CMakeLists.txt
+#
+
+CONFIGURE_FILE(nsd-dns-sd.pc.in nsd-dns-sd.pc @ONLY)
+
+INSTALL(FILES
+    ${CMAKE_BINARY_DIR}/pkgconfig/nsd-dns-sd/nsd-dns-sd.pc
+    DESTINATION
+    ${LIB_DIR}/pkgconfig
+    )
diff --git a/pkgconfig/nsd-dns-sd/nsd-dns-sd.pc.in b/pkgconfig/nsd-dns-sd/nsd-dns-sd.pc.in
new file mode 100644 (file)
index 0000000..210dbf8
--- /dev/null
@@ -0,0 +1,11 @@
+prefix=@CMAKE_INSTALL_PREFIX@
+exec_prefix=${prefix}
+libdir=@LIB_DIR@
+includedir=${prefix}/include
+
+Name: nsd-dns-sd
+Description: nsd-dns-sd package
+Version: @VERSION@
+Requires: capi-base-common
+Libs: -L${libdir} -lnsd-dns-sd
+Cflags: -I${includedir}/nsd
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
new file mode 100644 (file)
index 0000000..a455fd8
--- /dev/null
@@ -0,0 +1,24 @@
+# Copyright (c) 2014-2015 Samsung Electronics Co., Ltd All Rights Reserved
+#
+#    Licensed under the Apache License, Version 2.0 (the "License");
+#    you may not use this file except in compliance with the License.
+#    You may obtain a copy of the License at
+#
+#        http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+#
+# @file        CMakeLists.txt
+#
+
+SET(NSD_PATH ${PROJECT_SOURCE_DIR}/src)
+
+INCLUDE_DIRECTORIES(
+    ${CMAKE_SOURCE_DIR}/include
+    )
+
+ADD_SUBDIRECTORY(dns-sd)
diff --git a/src/dns-sd/CMakeLists.txt b/src/dns-sd/CMakeLists.txt
new file mode 100644 (file)
index 0000000..2740807
--- /dev/null
@@ -0,0 +1,45 @@
+# Copyright (c) 2014-2015 Samsung Electronics Co., Ltd All Rights Reserved
+#
+#    Licensed under the Apache License, Version 2.0 (the "License");
+#    you may not use this file except in compliance with the License.
+#    You may obtain a copy of the License at
+#
+#        http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+#
+# @file        CMakeLists.txt
+#
+
+SET(LIB_DNS_SD_PATH ${NSD_PATH}/dns-sd)
+
+INCLUDE_DIRECTORIES(
+    ${LIB_DNS_SD_PATH}
+    ${NSD_PATH}/include
+    )
+
+SET(LIB_DNS_SD_SOURCES
+    ${LIB_DNS_SD_PATH}/dns-sd.c
+    )
+
+ADD_DEFINITIONS("-fvisibility=default")
+
+ADD_LIBRARY(${TARGET_LIB_NSD_DNS_SD} SHARED ${LIB_DNS_SD_SOURCES})
+
+SET_TARGET_PROPERTIES(
+    ${TARGET_LIB_NSD_DNS_SD}
+    PROPERTIES
+        SOVERSION ${MAJORVER}
+        VERSION ${FULLVER}
+    )
+
+TARGET_LINK_LIBRARIES(${TARGET_LIB_NSD_DNS_SD}
+    ${NSD_DEPS_LIBRARIES}
+    dl
+    )
+
+INSTALL(TARGETS ${TARGET_LIB_NSD_DNS_SD} DESTINATION ${LIB_DIR})
diff --git a/src/dns-sd/dns-sd-util.h b/src/dns-sd/dns-sd-util.h
new file mode 100644 (file)
index 0000000..323682c
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __TIZEN_NET_DNSSD_UTIL_H__
+#define __TIZEN_NET_DNSSD_UTIL_H__
+
+#include <dlog.h>
+#include <dns_sd.h>
+#include <dns-sd.h>
+
+#undef LOG_TAG
+#define LOG_TAG "CAPI_NETWORK_DNSSD"
+
+#define DNSSD_LOGD(format, args...) LOGD(format, ##args)
+#define DNSSD_LOGI(format, args...) LOGI(format, ##args)
+#define DNSSD_LOGW(format, args...) LOGW(format, ##args)
+#define DNSSD_LOGE(format, args...) LOGE(format, ##args)
+
+#define __DNSSD_LOG_FUNC_ENTER__ LOGD("Enter")
+#define __DNSSD_LOG_FUNC_EXIT__ LOGD("Quit")
+
+#define NETWORK_SERVICE_DISCOVERY_FEATURE      "http://tizen.org/feature/network.service_discovery"
+
+#if 0
+#define CHECK_FEATURE_SUPPORTED(feature_name)\
+       do {\
+               bool feature_supported = FALSE;\
+               if (!system_info_get_platform_bool(feature_name,\
+                                       &feature_supported)) {\
+                       if(feature_supported == FALSE){\
+                               DNSSD_LOGE("%s feature is disabled",\
+                                               feature_name);\
+                               __DNSSD_LOG_FUNC_EXIT__;\
+                               return DNSSD_ERROR_NOT_SUPPORTED;\
+                       }\
+               } else {\
+                       DNSSD_LOGE("Error - Feature getting from System Info");\
+                       __DNSSD_LOG_FUNC_EXIT__;\
+                       return DNSSD_ERROR_OPERATION_FAILED;\
+               }\
+       } while(0)
+
+#else
+#define CHECK_FEATURE_SUPPORTED(feature_name)
+#endif
+
+#define IPV4_LEN 4
+#define IPV6_LEN 16
+
+typedef enum {
+       DNSSD_TYPE_UNKNOWN = 0  /**<DNS-SD service type unknown */,
+       DNSSD_TYPE_REGISTER = 1 /**<DNS-SD service type register */,
+       DNSSD_TYPE_BROWSE = 2   /**<DNS-SD service type browse */,
+       DNSSD_TYPE_FOUND = 3    /**<DNS-SD service type found */,
+} dnssd_type_e;
+
+typedef struct _dnssd_found_data_s {
+       unsigned int browse_handler;
+       char *service_name;
+       char *txt_record;
+       unsigned int txt_len;
+       char *host;
+       int port;
+       unsigned char ip_v4_addr[IPV4_LEN];
+       unsigned char ip_v6_addr[IPV6_LEN];
+} dnssd_found_data_s;
+
+typedef struct _dnssd_register_data_s {
+       DNSRecordRef record_ref;
+       TXTRecordRef txt_ref;
+       char *service_name;
+       char *host;
+       int port;
+       dnssd_registered_cb callback;
+       void *user_data;
+} dnssd_register_data_s;
+
+typedef struct _dnssd_browse_data_s {
+       dnssd_found_cb callback;
+       void *user_data;
+} dnssd_browse_data_s;
+
+typedef struct _dnssd_handle_s {
+       DNSServiceRef sd_ref;
+       dnssd_type_e op_type;
+       unsigned int service_handler;
+       char *service_type;
+       char domain[255];
+       unsigned int flags;
+       unsigned int if_index;
+       char data[0];
+} dnssd_handle_s;
+
+typedef struct _resolve_reply_data {
+       dnssd_handle_s *dnssd_handle;
+       DNSServiceRef sd_ref;
+} resolve_reply_data;
+
+#endif /* __TIZEN_NET_DNSSD_UTIL_H__ */
diff --git a/src/dns-sd/dns-sd.c b/src/dns-sd/dns-sd.c
new file mode 100644 (file)
index 0000000..b51a821
--- /dev/null
@@ -0,0 +1,1396 @@
+/*
+* Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#include <net/if.h>
+#include <dlog.h>
+#include <glib.h>
+#include <stdio.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <dns_sd.h>
+#include "dns-sd-util.h"
+#include "dns-sd.h"
+
+#define GET_REG_DATA_P(a) ((dnssd_register_data_s *)((a)->data))
+#define GET_BROWSE_DATA_P(a) ((dnssd_browse_data_s *)((a)->data))
+#define GET_FOUND_DATA_P(a) ((dnssd_found_data_s *)((a)->data))
+
+#define REG_SIZE (sizeof(dnssd_handle_s) + sizeof(dnssd_register_data_s))
+#define BROWSE_SIZE (sizeof(dnssd_handle_s) + sizeof(dnssd_browse_data_s))
+#define FOUND_SIZE (sizeof(dnssd_handle_s) + sizeof(dnssd_found_data_s))
+
+static __thread GSList *dnssd_handle_list = NULL;
+static __thread GSList *resolve_handle_list = NULL;
+static __thread bool g_is_init = false;
+
+static const char *dnssd_error_to_string(dnssd_error_e error)
+{
+       switch (error) {
+       case DNSSD_ERROR_NONE:
+               return "DNSSD_ERROR_NONE";
+       case DNSSD_ERROR_OUT_OF_MEMORY:
+               return "DNSSD_ERROR_OUT_OF_MEMORY";
+       case DNSSD_ERROR_INVALID_PARAMETER:
+               return "DNSSD_ERROR_INVALID_PARAMETER";
+       case DNSSD_ERROR_NOT_SUPPORTED:
+               return "DNSSD_ERROR_NOT_SUPPORTED";
+       case DNSSD_ERROR_NOT_INITIALIZED:
+               return "DNSSD_ERROR_NOT_INITIALIZED";
+       case DNSSD_ERROR_ALREADY_REGISTERED:
+               return "DNSSD_ERROR_ALREADY_REGISTERED";
+       case DNSSD_ERROR_NAME_CONFLICT:
+               return "DNSSD_ERROR_NAME_CONFLICT";
+       case DNSSD_ERROR_SERVICE_NOT_RUNNING:
+               return "DNSSD_ERROR_SERVICE_NOT_RUNNING";
+       case DNSSD_ERROR_OPERATION_FAILED:
+               return "DNSSD_ERROR_OPERATION_FAILED";
+       default:
+               return "UNSUPPORTED_ERROR";
+       }
+}
+
+static bool __dnssd_is_init(void)
+{
+       return g_is_init;
+}
+
+int dnssd_initialize(void)
+{
+       __DNSSD_LOG_FUNC_ENTER__;
+
+       CHECK_FEATURE_SUPPORTED(NETWORK_SERVICE_DISCOVERY_FEATURE);
+
+       if (__dnssd_is_init() == true) {
+               DNSSD_LOGE("Already initialized");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_INVALID_OPERATION;
+       }
+
+       g_is_init = true;
+
+       __DNSSD_LOG_FUNC_EXIT__;
+       return DNSSD_ERROR_NONE;
+}
+
+int dnssd_deinitialize(void)
+{
+       __DNSSD_LOG_FUNC_ENTER__;
+
+       CHECK_FEATURE_SUPPORTED(NETWORK_SERVICE_DISCOVERY_FEATURE);
+
+       if (__dnssd_is_init() == false) {
+               DNSSD_LOGE("Not initialized");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_NOT_INITIALIZED;
+       }
+
+       __DNSSD_LOG_FUNC_EXIT__;
+       return DNSSD_ERROR_NONE;
+}
+
+static dnssd_handle_s *__dnssd_check_handle_validity(
+               dnssd_service_h dnssd_service)
+{
+       __DNSSD_LOG_FUNC_ENTER__;
+       dnssd_handle_s *local_handle = NULL;
+       GSList *list;
+
+       for (list = dnssd_handle_list; list; list = list->next) {
+               local_handle = (dnssd_handle_s *)list->data;
+               if (local_handle && local_handle->service_handler ==
+                               dnssd_service) {
+                       DNSSD_LOGD("Service found with handler %u",
+                                       dnssd_service);
+                       __DNSSD_LOG_FUNC_EXIT__;
+                       return local_handle;
+               }
+       }
+
+       __DNSSD_LOG_FUNC_EXIT__;
+       return NULL;
+}
+
+int dnssd_create_local_service(const char *service_type,
+               dnssd_service_h *dnssd_service)
+{
+       __DNSSD_LOG_FUNC_ENTER__;
+       dnssd_handle_s *local_handle;
+       unsigned int handler;
+
+       CHECK_FEATURE_SUPPORTED(NETWORK_SERVICE_DISCOVERY_FEATURE);
+
+       if (__dnssd_is_init() == false) {
+               DNSSD_LOGE("Not initialized");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_NOT_INITIALIZED;
+       }
+
+       if(dnssd_service == NULL || service_type == NULL ||
+                       __dnssd_check_handle_validity(*dnssd_service) != NULL) {
+               DNSSD_LOGE("Invalid Parameter");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_INVALID_PARAMETER;
+       }
+
+       local_handle = (dnssd_handle_s *)g_try_malloc0(REG_SIZE);
+       if (local_handle == NULL) {
+               DNSSD_LOGE("Failed to Allocate Memory");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_OUT_OF_MEMORY;
+       }
+
+       handler = (unsigned int)local_handle & 0xffffffff;
+       *dnssd_service = handler;
+       local_handle->service_handler = handler;
+       local_handle->op_type = DNSSD_TYPE_REGISTER;
+       local_handle->service_type = g_strdup(service_type);
+       g_strlcpy(local_handle->domain, "", sizeof(local_handle->domain));
+       local_handle->flags = 0;
+       local_handle->if_index = kDNSServiceInterfaceIndexAny;
+
+       DNSSD_LOGD("New handle created [%p]->[%u] type %s", local_handle,
+                       *dnssd_service, local_handle->service_type);
+
+       dnssd_handle_list = g_slist_prepend(dnssd_handle_list, local_handle);
+
+       __DNSSD_LOG_FUNC_EXIT__;
+       return DNSSD_ERROR_NONE;
+}
+
+int dnssd_destroy_local_service(dnssd_service_h dnssd_service)
+{
+       __DNSSD_LOG_FUNC_ENTER__;
+       dnssd_handle_s *local_handle = NULL;
+
+       CHECK_FEATURE_SUPPORTED(NETWORK_SERVICE_DISCOVERY_FEATURE);
+
+       if (__dnssd_is_init() == false) {
+               DNSSD_LOGE("Not initialized");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_NOT_INITIALIZED;
+       }
+
+       local_handle = __dnssd_check_handle_validity(dnssd_service);
+       if (local_handle == NULL) {
+               DNSSD_LOGD("Service Handler not found");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_INVALID_PARAMETER;
+       }
+
+       if (local_handle->op_type != DNSSD_TYPE_REGISTER) {
+               DNSSD_LOGD("DNSSD service is not a local service");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_INVALID_PARAMETER;
+       }
+
+       DNSSD_LOGD("Destroy handle: [%p]->[%u]", local_handle, dnssd_service);
+
+       dnssd_handle_list = g_slist_remove(dnssd_handle_list, local_handle);
+       g_free(local_handle->service_type);
+       dnssd_register_data_s *reg = GET_REG_DATA_P(local_handle);
+       g_free(reg->service_name);
+       g_free(local_handle);
+       local_handle = NULL;
+
+       __DNSSD_LOG_FUNC_EXIT__;
+       return DNSSD_ERROR_NONE;
+}
+
+int dnssd_service_set_name(dnssd_service_h local_service,
+               const char *service_name)
+{
+       __DNSSD_LOG_FUNC_ENTER__;
+       dnssd_handle_s *local_handle = NULL;
+       dnssd_register_data_s *reg = NULL;
+
+       CHECK_FEATURE_SUPPORTED(NETWORK_SERVICE_DISCOVERY_FEATURE);
+
+       if (__dnssd_is_init() == false) {
+               DNSSD_LOGE("Not initialized");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_NOT_INITIALIZED;
+       }
+
+       if (service_name == NULL) {
+               DNSSD_LOGD("Service name is NULL");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_INVALID_PARAMETER;
+       }
+
+       local_handle = __dnssd_check_handle_validity(local_service);
+       if (local_handle == NULL) {
+               DNSSD_LOGD("Service Handler not found");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_INVALID_PARAMETER;
+       }
+
+       if (local_handle->op_type != DNSSD_TYPE_REGISTER) {
+               DNSSD_LOGD("DNSSD service is not a local service");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_INVALID_PARAMETER;
+       }
+
+       reg = GET_REG_DATA_P(local_handle);
+       g_free(reg->service_name);
+       reg->service_name = g_strdup(service_name);
+
+       DNSSD_LOGD("Successfully set service name %s", service_name);
+
+       __DNSSD_LOG_FUNC_EXIT__;
+       return DNSSD_ERROR_NONE;
+}
+
+int dnssd_service_set_port(dnssd_service_h local_service, int port)
+{
+       __DNSSD_LOG_FUNC_ENTER__;
+       dnssd_handle_s *local_handle = NULL;
+       dnssd_register_data_s *reg = NULL;
+
+       CHECK_FEATURE_SUPPORTED(NETWORK_SERVICE_DISCOVERY_FEATURE);
+
+       if (__dnssd_is_init() == false) {
+               DNSSD_LOGE("Not initialized");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_NOT_INITIALIZED;
+       }
+
+       if (port < 0 || port > 65535) {
+               DNSSD_LOGD("Invalid port range");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_INVALID_PARAMETER;
+       }
+
+       local_handle = __dnssd_check_handle_validity(local_service);
+       if (local_handle == NULL) {
+               DNSSD_LOGD("Service Handler not found");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_INVALID_PARAMETER;
+       }
+
+       if (local_handle->op_type != DNSSD_TYPE_REGISTER) {
+               DNSSD_LOGD("DNSSD service is not a local service");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_INVALID_PARAMETER;
+       }
+
+       reg = GET_REG_DATA_P(local_handle);
+       reg->port = port;
+
+       DNSSD_LOGD("Successfully set port %d", port);
+
+       __DNSSD_LOG_FUNC_EXIT__;
+       return DNSSD_ERROR_NONE;
+}
+
+int dnssd_service_add_txt_record(dnssd_service_h local_service,
+               const char *key, unsigned short length, const void *value)
+{
+       __DNSSD_LOG_FUNC_ENTER__;
+       int ret;
+       TXTRecordRef *txt_record;
+       dnssd_handle_s *local_handle = NULL;
+       dnssd_register_data_s *reg = NULL;
+
+       CHECK_FEATURE_SUPPORTED(NETWORK_SERVICE_DISCOVERY_FEATURE);
+
+       if (__dnssd_is_init() == false) {
+               DNSSD_LOGE("Not initialized");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_NOT_INITIALIZED;
+       }
+
+       local_handle = __dnssd_check_handle_validity(local_service);
+       if (local_handle == NULL) {
+               DNSSD_LOGD("Service Handler not found");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_INVALID_PARAMETER;
+       }
+
+       if (local_handle->op_type != DNSSD_TYPE_REGISTER) {
+               DNSSD_LOGD("DNSSD service is not a local service");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_INVALID_PARAMETER;
+       }
+
+       if (key == NULL) {
+               DNSSD_LOGE("key is NULL");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_INVALID_PARAMETER;
+       }
+
+       if (length == 0 || value == NULL)
+               DNSSD_LOGD("Value size is 0 or NULL value passed");
+
+       reg = GET_REG_DATA_P(local_handle);
+       txt_record = &(reg->txt_ref);
+
+       TXTRecordCreate(txt_record, 0, NULL);
+
+       ret = TXTRecordSetValue(txt_record, key, length, value);
+       if (ret != DNSSD_ERROR_NONE) {
+               DNSSD_LOGE("Failed to add value to key, error[%s]",
+                               dnssd_error_to_string(ret));
+               __DNSSD_LOG_FUNC_EXIT__;
+               return ret;
+       } else {
+               DNSSD_LOGD("Succeeded to add value to key");
+       }
+
+       __DNSSD_LOG_FUNC_EXIT__;
+       return DNSSD_ERROR_NONE;
+}
+
+int dnssd_service_remove_txt_record(dnssd_service_h local_service,
+               const char *key)
+{
+       __DNSSD_LOG_FUNC_ENTER__;
+       int ret;
+       TXTRecordRef *txt_record;
+       dnssd_handle_s *local_handle;
+       dnssd_register_data_s *reg = NULL;
+       unsigned short txt_len;
+
+       CHECK_FEATURE_SUPPORTED(NETWORK_SERVICE_DISCOVERY_FEATURE);
+
+       if (__dnssd_is_init() == false) {
+               DNSSD_LOGE("Not initialized");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_NOT_INITIALIZED;
+       }
+
+       local_handle = __dnssd_check_handle_validity(local_service);
+       if (local_handle == NULL) {
+               DNSSD_LOGD("Service Handler not found");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_INVALID_PARAMETER;
+       }
+
+       if (local_handle->op_type != DNSSD_TYPE_REGISTER) {
+               DNSSD_LOGD("DNSSD service is not a local service");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_INVALID_PARAMETER;
+       }
+
+       if (key == NULL) {
+               DNSSD_LOGE("key is NULL");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_INVALID_PARAMETER;
+       }
+
+       reg = GET_REG_DATA_P(local_handle);
+       txt_record = &(reg->txt_ref);
+
+       ret = TXTRecordRemoveValue(txt_record, key);
+       if (ret != DNSSD_ERROR_NONE) {
+               DNSSD_LOGE("Failed to remove value from key, error[%s]",
+                               dnssd_error_to_string(ret));
+               __DNSSD_LOG_FUNC_EXIT__;
+               return ret;
+       } else {
+               DNSSD_LOGD("Succeeded to remove value from key");
+       }
+
+       txt_len = TXTRecordGetLength(txt_record);
+
+       if (TXTRecordGetCount(txt_len, txt_record) == 0) {
+               DNSSD_LOGD("No more key exists in TXT Record");
+               /* Free TXT Record */
+               TXTRecordDeallocate(txt_record);
+       }
+
+       __DNSSD_LOG_FUNC_EXIT__;
+       return DNSSD_ERROR_NONE;
+}
+
+int dnssd_service_set_record(dnssd_service_h local_service, unsigned short type,
+               unsigned short length, const void *data)
+{
+       __DNSSD_LOG_FUNC_ENTER__;
+       int ret;
+       dnssd_handle_s *local_handle = NULL;
+       dnssd_register_data_s *reg;
+       DNSServiceRef sd_ref;
+       DNSRecordRef record_client;
+
+       CHECK_FEATURE_SUPPORTED(NETWORK_SERVICE_DISCOVERY_FEATURE);
+
+       if (__dnssd_is_init() == false) {
+               DNSSD_LOGE("Not initialized");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_NOT_INITIALIZED;
+       }
+
+       local_handle = __dnssd_check_handle_validity(local_service);
+       if (local_handle == NULL) {
+               DNSSD_LOGD("Service Handler not found");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_INVALID_PARAMETER;
+       }
+
+       if (local_handle->op_type != DNSSD_TYPE_REGISTER) {
+               DNSSD_LOGD("DNSSD service is not a local service");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_INVALID_PARAMETER;
+       }
+
+       reg = GET_REG_DATA_P(local_handle);
+       sd_ref = local_handle->sd_ref;
+       record_client = reg->record_ref;
+       DNSSD_LOGD("Record Type %d Record len %d", type, length);
+
+       if (record_client == NULL) {
+               DNSSD_LOGD("Adding DNS Service Record");
+               ret = DNSServiceAddRecord(sd_ref, &(reg->record_ref),
+                               local_handle->flags, type, length, data, 0);
+       } else {
+               DNSSD_LOGD("Updating DNS Service Record");
+               ret = DNSServiceUpdateRecord(sd_ref, record_client,
+                               local_handle->flags, length, data, 0);
+       }
+       if (ret < 0) {
+               DNSSD_LOGE("Failed to Add Record for DNS Service, error[%s]",
+                               dnssd_error_to_string(ret));
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_OPERATION_FAILED;
+       }
+
+       DNSSD_LOGD("Successfully added record for DNS Service");
+
+       __DNSSD_LOG_FUNC_EXIT__;
+       return DNSSD_ERROR_NONE;
+}
+
+int dnssd_service_unset_record(dnssd_service_h local_service,
+               unsigned short type)
+{
+       __DNSSD_LOG_FUNC_ENTER__;
+       int ret;
+       dnssd_handle_s *local_handle;
+       dnssd_register_data_s *reg;
+       DNSServiceRef sd_ref;
+       DNSRecordRef record_client;
+
+       CHECK_FEATURE_SUPPORTED(NETWORK_SERVICE_DISCOVERY_FEATURE);
+
+       if (__dnssd_is_init() == false) {
+               DNSSD_LOGE("Not initialized");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_NOT_INITIALIZED;
+       }
+
+       local_handle = __dnssd_check_handle_validity(local_service);
+       if (local_handle == NULL) {
+               DNSSD_LOGD("Service Handler not found");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_INVALID_PARAMETER;
+       }
+
+       if (local_handle->op_type != DNSSD_TYPE_REGISTER) {
+               DNSSD_LOGD("DNSSD service is not a local service");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_INVALID_PARAMETER;
+       }
+
+       reg = GET_REG_DATA_P(local_handle);
+       sd_ref = local_handle->sd_ref;
+       record_client = reg->record_ref;
+
+       if(NULL == record_client) {
+               DNSSD_LOGE("Invalid DNS SD Client");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_INVALID_PARAMETER;
+       }
+
+       ret = DNSServiceRemoveRecord(sd_ref, record_client,
+                       local_handle->flags);
+       if(ret < 0) {
+               DNSSD_LOGE("Failed to Remove Record for DNS Service, error[%s]",
+                               dnssd_error_to_string(ret));
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_OPERATION_FAILED;
+       }
+
+       reg->record_ref = NULL;
+
+       DNSSD_LOGD("Successfully removed record for DNS Service");
+
+       __DNSSD_LOG_FUNC_EXIT__;
+       return DNSSD_ERROR_NONE;
+}
+
+static void __dnssd_register_reply_cb(DNSServiceRef sd_ref, unsigned int flags,
+               DNSServiceErrorType error_code, const char *service_name,
+               const char *service_type, const char *domain, void *user_data)
+{
+       dnssd_handle_s *dnssd_handle;
+       dnssd_register_data_s *reg = NULL;
+       GSList *list;
+       dnssd_registered_cb callback;
+       void *data;
+
+       DNSSD_LOGD("Received Registration Reply");
+
+       if (error_code != DNSSD_ERROR_NONE)
+               DNSSD_LOGE("Failed to register, error code %d -> %s",
+                               error_code,
+                               dnssd_error_to_string(error_code));
+
+       for (list = dnssd_handle_list; list; list = list->next) {
+               dnssd_handle = (dnssd_handle_s *) list->data;
+               if (dnssd_handle->sd_ref == sd_ref) {
+                       DNSSD_LOGD("Registration Callback set for [%p]",
+                                       dnssd_handle);
+                       /* Update domain and flags for any future use */
+                       g_strlcpy(dnssd_handle->domain, domain,
+                                       sizeof(dnssd_handle->domain));
+                       dnssd_handle->flags = flags;
+                       DNSSD_LOGD("Domain/Interface/Flags : %s/%d/0x%x",
+                                       dnssd_handle->domain,
+                                       dnssd_handle->if_index,
+                                       dnssd_handle->flags);
+
+                       reg = GET_REG_DATA_P(dnssd_handle);
+                       callback = reg->callback;
+                       data = reg->user_data;
+                       if (callback)
+                               callback(error_code,
+                                               dnssd_handle->service_handler,
+                                               data);
+                       break;
+               }
+       }
+}
+
+int dnssd_register_local_service(dnssd_service_h local_service,
+               dnssd_registered_cb register_cb, void *user_data)
+{
+       __DNSSD_LOG_FUNC_ENTER__;
+       int ret;
+       dnssd_handle_s *local_handle = NULL;
+       dnssd_register_data_s *reg = NULL;
+       DNSServiceRef *sd_ref;
+
+       CHECK_FEATURE_SUPPORTED(NETWORK_SERVICE_DISCOVERY_FEATURE);
+
+       if (__dnssd_is_init() == false) {
+               DNSSD_LOGE("Not initialized");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_NOT_INITIALIZED;
+       }
+
+       local_handle = __dnssd_check_handle_validity(local_service);
+       if (local_handle == NULL) {
+               DNSSD_LOGD("Service Handler not found");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_INVALID_PARAMETER;
+       }
+
+       if (register_cb == NULL) {
+               DNSSD_LOGE("No callback provided");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_INVALID_PARAMETER;
+       }
+
+       if (local_handle->op_type != DNSSD_TYPE_REGISTER) {
+               DNSSD_LOGD("DNSSD service is not a local service");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_INVALID_PARAMETER;
+       }
+
+       reg = GET_REG_DATA_P(local_handle);
+       sd_ref = &(local_handle->sd_ref);
+
+       if (reg->service_name == NULL) {
+               DNSSD_LOGD("No Service Name Provided");
+               reg->service_name = g_strdup("");
+       } else
+               DNSSD_LOGD("Service Name is %s", reg->service_name);
+
+       DNSSD_LOGD("Domain/Interface/Flags : %s/%d/0x%x", local_handle->domain,
+                       local_handle->if_index, local_handle->flags);
+
+       ret = DNSServiceRegister(sd_ref, local_handle->flags,
+                       local_handle->if_index, reg->service_name,
+                       local_handle->service_type, local_handle->domain,
+                       NULL, reg->port, 1, "", __dnssd_register_reply_cb,
+                       NULL);
+       if(ret < 0) {
+               DNSSD_LOGE("Failed to register for dns service, error[%s]",
+                               dnssd_error_to_string(ret));
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_OPERATION_FAILED;
+       }
+
+       reg->callback = register_cb;
+       reg->user_data = user_data;
+       DNSServiceHandleEvents(sd_ref);
+
+       DNSSD_LOGD("Succeeded to register for dns service");
+       __DNSSD_LOG_FUNC_EXIT__;
+       return DNSSD_ERROR_NONE;
+}
+
+int dnssd_deregister_local_service(dnssd_service_h local_service)
+{
+       __DNSSD_LOG_FUNC_ENTER__;
+       dnssd_handle_s *local_handle = NULL;
+       dnssd_register_data_s *reg;
+       DNSServiceRef sd_ref;
+       DNSRecordRef record_client;
+       int ret;
+
+       CHECK_FEATURE_SUPPORTED(NETWORK_SERVICE_DISCOVERY_FEATURE);
+
+       if (__dnssd_is_init() == false) {
+               DNSSD_LOGE("Not initialized");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_NOT_INITIALIZED;
+       }
+
+       local_handle = __dnssd_check_handle_validity(local_service);
+       if (local_handle == NULL) {
+               DNSSD_LOGD("Service Handler not found");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_INVALID_PARAMETER;
+       }
+
+       if (local_handle->op_type != DNSSD_TYPE_REGISTER) {
+               DNSSD_LOGD("DNSSD service is not a local service");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_INVALID_PARAMETER;
+       }
+
+       sd_ref = local_handle->sd_ref;
+       if(NULL == sd_ref) {
+               DNSSD_LOGE("Invalid DNS SD Client");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_INVALID_PARAMETER;
+       }
+
+       reg = GET_REG_DATA_P(local_handle);
+       record_client = reg->record_ref;
+       if (record_client) {
+               ret = DNSServiceRemoveRecord(sd_ref, record_client,
+                               local_handle->flags);
+               if(ret < 0)
+                       DNSSD_LOGE("Failed to Remove Record for DNS Service, "
+                                       "error[%s]", dnssd_error_to_string(ret));
+               else
+                       reg->record_ref = NULL;
+       }
+
+       DNSServiceRefDeallocate(sd_ref);
+       sd_ref = NULL;
+       __DNSSD_LOG_FUNC_EXIT__;
+       return DNSSD_ERROR_NONE;
+}
+
+static void __dnssd_getaddrinfo_reply_cb(DNSServiceRef sd_ref,
+               unsigned int flags, unsigned int if_index,
+               DNSServiceErrorType error_code, const char *host_name,
+               const struct sockaddr *address, unsigned int ttl,
+               void *user_data)
+{
+       dnssd_handle_s *dnssd_handle = NULL;
+       dnssd_handle_s *local_handle = NULL;
+       dnssd_browse_data_s *browse = NULL;
+       dnssd_found_data_s *found = NULL;
+       dnssd_found_cb callback;
+       void *data;
+
+       if(user_data == NULL) {
+               DNSSD_LOGD("Invalid found handle");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return;
+       }
+
+       local_handle = (dnssd_handle_s *)user_data;
+       found = GET_FOUND_DATA_P(local_handle);
+       /* Update interface and flags for any future use */
+       local_handle->if_index = if_index;
+       local_handle->flags = flags;
+       DNSSD_LOGD("Domain/Interface/Flags : %s/%d/0x%x",
+                       local_handle->domain,
+                       local_handle->if_index,
+                       local_handle->flags);
+
+       dnssd_handle = __dnssd_check_handle_validity(found->browse_handler);
+       if(dnssd_handle == NULL) {
+               DNSSD_LOGD("Invalid browse handle");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return;
+       }
+       DNSSD_LOGD("GetAddrInfo Callback set for [%p]",
+                       dnssd_handle);
+
+       browse = GET_BROWSE_DATA_P(dnssd_handle);
+       callback = browse->callback;
+       data = browse->user_data;
+
+       if (address && address->sa_family == AF_INET) {
+
+               const unsigned char *addr =
+                       (const unsigned char *) &
+                       ((struct sockaddr_in *)address)->sin_addr;
+               memcpy(&(found->ip_v4_addr), addr, IPV4_LEN);
+       } else if (address && address->sa_family == AF_INET6) {
+
+               const struct sockaddr_in6 *s6 =
+                       (const struct sockaddr_in6 *)address;
+               const unsigned char *addr =
+                       (const unsigned char *)&s6->sin6_addr;
+               memcpy(&(found->ip_v6_addr), addr, IPV6_LEN);
+       }
+
+       if (callback) {
+               callback(DNSSD_SERVICE_STATE_AVAILABLE,
+                               local_handle->service_handler, data);
+               DNSSD_LOGD("Finished executing Browse "
+                               "Available Callback");
+       }
+
+}
+
+static int __dnssd_getaddrinfo(dnssd_handle_s *dnssd_handle, unsigned int flags,
+               unsigned int if_index, const char *host_name,
+               const char *fullname, const char *txt_record,
+               unsigned short txt_len, int port)
+{
+       int ret;
+       DNSServiceRef *sd_ref;
+       dnssd_handle_s *local_handle = NULL;
+       dnssd_found_data_s *found = NULL;
+       char *name;
+       char *domain;
+       int dns_protocol = kDNSServiceProtocol_IPv4 | kDNSServiceProtocol_IPv6;
+
+       if(dnssd_handle == NULL) {
+               DNSSD_LOGD("Invalid browse handle");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_OUT_OF_MEMORY;
+       }
+
+       /* fullname is of the form <servicename>.<protocol>.<domain>
+        * Extract servicename and domain from fullname */
+       name = g_strdup(fullname);
+       domain = strtok(name, ".");
+       domain = strtok(NULL, ".");
+       domain = strtok(NULL, ".");
+       domain = strtok(NULL, ".");
+
+       local_handle = g_try_malloc0(FOUND_SIZE);
+       if(local_handle == NULL) {
+               DNSSD_LOGD("g_try_malloc failed");
+               g_free(name);
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_OUT_OF_MEMORY;
+       }
+
+       found = GET_FOUND_DATA_P(local_handle);
+
+       local_handle->op_type = DNSSD_TYPE_FOUND;
+       local_handle->service_handler = (unsigned int)local_handle & 0xffffffff;
+       g_strlcpy(local_handle->domain, domain, sizeof(local_handle->domain));
+       local_handle->if_index = if_index;
+       local_handle->flags= flags;
+       if(dnssd_handle->service_type)
+               local_handle->service_type = g_strdup(dnssd_handle->service_type);
+
+       found->browse_handler = dnssd_handle->service_handler;
+       found->service_name = g_strdup(name);
+       g_free(name);
+       if(txt_record != NULL) {
+               found->txt_record = g_strdup(txt_record);
+               found->txt_len = txt_len;
+       }
+       found->host = g_strdup(host_name);
+       found->port = port;
+
+       DNSSD_LOGD("Create found handle [%u]", local_handle->service_handler);
+
+       dnssd_handle_list = g_slist_prepend(dnssd_handle_list, local_handle);
+
+       DNSSD_LOGD("g_slist length [%d]", g_slist_length(dnssd_handle_list));
+
+       sd_ref = &(local_handle->sd_ref);
+
+       ret = DNSServiceGetAddrInfo(sd_ref, flags, if_index,
+                       dns_protocol, host_name,
+                       __dnssd_getaddrinfo_reply_cb, local_handle);
+       if(ret < 0) {
+               DNSSD_LOGE("Failed to GetAddrInfo, error[%s]",
+                               dnssd_error_to_string(ret));
+               return ret;
+       }
+
+       DNSServiceHandleEvents(sd_ref);
+
+       DNSSD_LOGD("Succeeded to GetAddrInfo");
+
+       return DNSSD_ERROR_NONE;
+}
+
+static void __dnssd_resolve_reply_cb(DNSServiceRef sd_ref, unsigned int flags,
+               unsigned int if_index, DNSServiceErrorType error_code,
+               const char *fullname, const char *host_name,
+               unsigned short port, unsigned short txt_len,
+               const unsigned char *txt_record, void *user_data)
+{
+       resolve_reply_data *resolve_data = user_data;
+       DNSSD_LOGD("Received Resolve Reply");
+       /* Get Address Info details and send browse callback */
+       __dnssd_getaddrinfo(resolve_data->dnssd_handle, flags, if_index,
+                       host_name, fullname, (const char *) txt_record,
+                       txt_len, port);
+}
+
+static int __dnssd_resolve_dns_service(dnssd_handle_s *dnssd_handle,
+               unsigned int flags, unsigned int if_index,
+               const char *service_name, const char *type, const char *domain)
+{
+       __DNSSD_LOG_FUNC_ENTER__;
+       int ret;
+       resolve_reply_data *data;
+       DNSServiceRef *sd_ref;
+
+       data = g_try_malloc0(sizeof(resolve_reply_data));
+       if (data == NULL) {
+               DNSSD_LOGD("g_try_malloc failed");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_OUT_OF_MEMORY;
+       }
+
+       data->dnssd_handle =  dnssd_handle;
+
+       resolve_handle_list = g_slist_prepend(resolve_handle_list, data);
+
+       sd_ref = &(data->sd_ref);
+
+       ret = DNSServiceResolve(sd_ref, flags, if_index, service_name,
+                       type, domain, __dnssd_resolve_reply_cb, data);
+       if(ret < 0) {
+               DNSSD_LOGE("Failed to Resolve DNS Service, error[%s]",
+                               dnssd_error_to_string(ret));
+               __DNSSD_LOG_FUNC_EXIT__;
+               return ret;
+       }
+
+       DNSServiceHandleEvents(sd_ref);
+
+       DNSSD_LOGD("Succeeded to Resolve DNS Service");
+
+       __DNSSD_LOG_FUNC_EXIT__;
+       return DNSSD_ERROR_NONE;
+}
+
+static dnssd_handle_s *__dnssd_get_found_handle(dnssd_service_h browse_service,
+               const char *service_name)
+{
+       __DNSSD_LOG_FUNC_ENTER__;
+       dnssd_handle_s *local_handle = NULL;
+       dnssd_found_data_s *found_data;
+       GSList *list;
+
+       for (list = dnssd_handle_list; list; list = list->next) {
+               local_handle = (dnssd_handle_s *)list->data;
+               if (local_handle && local_handle->op_type != DNSSD_TYPE_FOUND)
+                       continue;
+
+               found_data = GET_FOUND_DATA_P(local_handle);
+               if ((found_data->browse_handler == browse_service) &&
+                               (g_strcmp0(found_data->service_name,
+                                          service_name) == 0)) {
+                       DNSSD_LOGD("Service handler 0x%x",
+                                       local_handle->service_handler);
+                       return local_handle;
+               }
+       }
+
+       DNSSD_LOGD("Service handler not found");
+       __DNSSD_LOG_FUNC_EXIT__;
+       return NULL;
+}
+
+static void __dnssd_broswe_reply_cb(DNSServiceRef sd_ref, unsigned int flags,
+               unsigned int if_index, DNSServiceErrorType error_code,
+               const char *service_name, const char *service_type,
+               const char *domain, void *user_data)
+{
+       __DNSSD_LOG_FUNC_ENTER__;
+       dnssd_handle_s *dnssd_handle;
+       GSList *list;
+       void *data;
+
+       DNSSD_LOGD("Received Browse Reply");
+
+       if (error_code != DNSSD_ERROR_NONE) {
+               DNSSD_LOGE("Failed to browse, error code %s",
+                               dnssd_error_to_string(error_code));
+               __DNSSD_LOG_FUNC_EXIT__;
+               return;
+       }
+
+       for (list = dnssd_handle_list; list; list = list->next) {
+               dnssd_handle = (dnssd_handle_s *) list->data;
+               if(dnssd_handle == NULL)
+                       continue;
+
+               if (dnssd_handle->sd_ref == sd_ref) {
+                       DNSSD_LOGD("Browse Callback set for [%p]", dnssd_handle);
+
+                       /* Update domain, interface and flags */
+                       g_strlcpy(dnssd_handle->domain, domain,
+                                       sizeof(dnssd_handle->domain));
+                       dnssd_handle->flags = flags;
+                       dnssd_handle->if_index = if_index;
+                       DNSSD_LOGD("Domain/Interface/Flags : %s/%d/0x%x",
+                                       dnssd_handle->domain,
+                                       dnssd_handle->if_index,
+                                       dnssd_handle->flags);
+
+                       if (flags & kDNSServiceFlagsAdd) {
+                               /* Resolve address and send callback later */
+                               __dnssd_resolve_dns_service(dnssd_handle, flags,
+                                               if_index, service_name,
+                                               service_type, domain);
+                       } else {
+
+                               dnssd_browse_data_s *browse = NULL;
+                               dnssd_found_cb callback;
+                               dnssd_handle_s *found_handle;
+
+                               browse = GET_BROWSE_DATA_P(dnssd_handle);
+                               callback = browse->callback;
+                               data = browse->user_data;
+
+                               found_handle = __dnssd_get_found_handle(
+                                               dnssd_handle->service_handler,
+                                               service_name);
+
+                               if (callback)
+                                       callback(DNSSD_SERVICE_STATE_UNAVAILABLE,
+                                               found_handle->service_handler,
+                                               data);
+                       }
+
+                       DNSSD_LOGD("Finished executing Browse Callback");
+               }
+       }
+       __DNSSD_LOG_FUNC_EXIT__;
+}
+
+int dnssd_start_browsing_service(const char *service_type,
+               dnssd_browser_h *dnssd_service, dnssd_found_cb found_cb,
+               void *user_data)
+{
+       __DNSSD_LOG_FUNC_ENTER__;
+       int ret;
+       dnssd_handle_s *local_handle;
+       dnssd_browse_data_s *browse;
+       DNSServiceRef *sd_ref;
+       unsigned int handler;
+
+       CHECK_FEATURE_SUPPORTED(NETWORK_SERVICE_DISCOVERY_FEATURE);
+
+       if (__dnssd_is_init() == false) {
+               DNSSD_LOGE("Not initialized");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_NOT_INITIALIZED;
+       }
+
+       if(dnssd_service == NULL || service_type == NULL ||
+                       __dnssd_check_handle_validity(*dnssd_service) != NULL) {
+               DNSSD_LOGE("Invalid Parameter");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_INVALID_PARAMETER;
+       }
+
+       if (found_cb == NULL) {
+               DNSSD_LOGE("Callback Not Provided");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_INVALID_PARAMETER;
+       }
+
+       local_handle = (dnssd_handle_s *)g_try_malloc0(BROWSE_SIZE);
+       if (local_handle == NULL) {
+               DNSSD_LOGE("Failed to Allocate Memory");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_OUT_OF_MEMORY;
+       }
+
+       handler = (unsigned int)local_handle & 0xffffffff;
+       *dnssd_service = handler;
+       local_handle->service_handler = handler;
+       local_handle->op_type = DNSSD_TYPE_BROWSE;
+       local_handle->service_type = g_strdup(service_type);
+       g_strlcpy(local_handle->domain, "", sizeof(local_handle->domain));
+       local_handle->flags = 0;
+       local_handle->if_index = kDNSServiceInterfaceIndexAny;
+       browse = GET_BROWSE_DATA_P(local_handle);
+       sd_ref = &(local_handle->sd_ref);
+
+       DNSSD_LOGD("New browse handle created [%p]->[%u] type %s", local_handle,
+                       *dnssd_service, local_handle->service_type);
+
+       ret = DNSServiceBrowse(sd_ref, local_handle->flags,
+                       local_handle->if_index, local_handle->service_type,
+                       local_handle->domain, __dnssd_broswe_reply_cb,
+                       NULL);
+       if(ret < 0) {
+               DNSSD_LOGE("Failed to browse for dns service, error[%s]",
+                               dnssd_error_to_string(ret));
+               g_free(local_handle->service_type);
+               g_free(local_handle);
+               __DNSSD_LOG_FUNC_EXIT__;
+               return ret;
+       }
+
+       browse->callback = found_cb;
+       browse->user_data = user_data;
+       dnssd_handle_list = g_slist_prepend(dnssd_handle_list, local_handle);
+       DNSServiceHandleEvents(sd_ref);
+
+       DNSSD_LOGD("Succeeded to browse for dns service");
+       __DNSSD_LOG_FUNC_EXIT__;
+       return DNSSD_ERROR_NONE;
+}
+
+static void __dnssd_remove_found_service(gpointer data, gpointer user_data)
+{
+       __DNSSD_LOG_FUNC_ENTER__;
+       dnssd_handle_s *found_handle;
+       dnssd_found_data_s *found_data;
+       dnssd_service_h *handler = NULL;
+
+       found_handle = (dnssd_handle_s *)data;
+       handler = (dnssd_service_h *)user_data;
+
+       if(found_handle->op_type != DNSSD_TYPE_FOUND)
+               return;
+
+       found_data = GET_FOUND_DATA_P(found_handle);
+       if(found_data->browse_handler != *handler)
+               return;
+
+       DNSSD_LOGD("handle [0x%x]", found_handle->service_handler);
+       dnssd_handle_list = g_slist_remove(dnssd_handle_list,
+                       found_handle);
+
+       DNSServiceRefDeallocate(found_handle->sd_ref);
+
+       g_free(found_handle->service_type);
+       g_free(found_data->service_name);
+       g_free(found_data->host);
+       g_free(found_data->txt_record);
+       g_free(found_handle);
+
+       __DNSSD_LOG_FUNC_EXIT__;
+       return;
+}
+
+int dnssd_stop_browsing_service(dnssd_browser_h dnssd_service)
+{
+       __DNSSD_LOG_FUNC_ENTER__;
+       dnssd_handle_s *local_handle;
+       DNSServiceRef sd_ref;
+       GSList *list;
+       resolve_reply_data *resolve_data;
+
+       CHECK_FEATURE_SUPPORTED(NETWORK_SERVICE_DISCOVERY_FEATURE);
+
+       if (__dnssd_is_init() == false) {
+               DNSSD_LOGE("Not initialized");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_NOT_INITIALIZED;
+       }
+
+       local_handle = __dnssd_check_handle_validity(dnssd_service);
+       if (local_handle == NULL) {
+               DNSSD_LOGD("Service Handler 0x%x not found", dnssd_service);
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_INVALID_PARAMETER;
+       }
+
+       if (local_handle->op_type != DNSSD_TYPE_BROWSE) {
+               DNSSD_LOGD("DNS SD service is not browser service");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_INVALID_PARAMETER;
+       }
+
+       sd_ref = local_handle->sd_ref;
+       if(NULL == sd_ref) {
+               DNSSD_LOGE("Invalid DNS SD Client");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_INVALID_PARAMETER;
+       }
+
+       g_slist_foreach(dnssd_handle_list, (GFunc)__dnssd_remove_found_service,
+                       &(local_handle->service_handler));
+
+       list = resolve_handle_list;
+       while (list) {
+               resolve_data = list->data;
+               list = list->next;
+
+               if (resolve_data->dnssd_handle == local_handle) {
+                       resolve_handle_list = g_slist_remove(resolve_handle_list,
+                                       resolve_data);
+
+                       DNSServiceRefDeallocate(resolve_data->sd_ref);
+
+                       g_free(resolve_data);
+               }
+       }
+
+       DNSServiceRefDeallocate(sd_ref);
+       sd_ref = NULL;
+
+       DNSSD_LOGD("g_slist length [%d]", g_slist_length(dnssd_handle_list));
+       __DNSSD_LOG_FUNC_EXIT__;
+       return DNSSD_ERROR_NONE;
+}
+
+int dnssd_service_get_type(dnssd_service_h dnssd_service, char **service_type)
+{
+       __DNSSD_LOG_FUNC_ENTER__;
+       dnssd_handle_s *local_handle = NULL;
+
+       CHECK_FEATURE_SUPPORTED(NETWORK_SERVICE_DISCOVERY_FEATURE);
+
+       if (__dnssd_is_init() == false) {
+               DNSSD_LOGE("Not initialized");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_NOT_INITIALIZED;
+       }
+
+       if (service_type == NULL) {
+               DNSSD_LOGE("Invalid Parameter");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_INVALID_PARAMETER;
+       }
+
+       local_handle = __dnssd_check_handle_validity(dnssd_service);
+       if (local_handle == NULL) {
+               DNSSD_LOGD("Service Handler not found");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_INVALID_PARAMETER;
+       } else {
+               *service_type = g_strdup(local_handle->service_type);
+               DNSSD_LOGD("Service Type %s", *service_type);
+       }
+
+       __DNSSD_LOG_FUNC_EXIT__;
+       return DNSSD_ERROR_NONE;
+}
+
+int dnssd_service_get_name(dnssd_service_h dnssd_service, char **service_name)
+{
+       __DNSSD_LOG_FUNC_ENTER__;
+       dnssd_handle_s *local_handle = NULL;
+
+       CHECK_FEATURE_SUPPORTED(NETWORK_SERVICE_DISCOVERY_FEATURE);
+
+       if (__dnssd_is_init() == false) {
+               DNSSD_LOGE("Not initialized");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_NOT_INITIALIZED;
+       }
+
+       if (service_name == NULL) {
+               DNSSD_LOGE("Invalid Parameter");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_INVALID_PARAMETER;
+       }
+
+       local_handle = __dnssd_check_handle_validity(dnssd_service);
+       if (local_handle == NULL) {
+               DNSSD_LOGD("Service Handler not found");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_INVALID_PARAMETER;
+       }
+
+       if(local_handle->op_type == DNSSD_TYPE_FOUND) {
+               dnssd_found_data_s *found = NULL;
+               found = GET_FOUND_DATA_P(local_handle);
+               *service_name = g_strdup(found->service_name);
+       } else if(local_handle->op_type == DNSSD_TYPE_REGISTER) {
+               dnssd_register_data_s *reg = NULL;
+               reg = GET_REG_DATA_P(local_handle);
+               *service_name = g_strdup(reg->service_name);
+       } else {
+               *service_name = NULL;
+               DNSSD_LOGD("Invalid DNS SD service");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_INVALID_PARAMETER;
+       }
+
+       DNSSD_LOGD("Service Name %s", *service_name);
+
+       __DNSSD_LOG_FUNC_EXIT__;
+       return DNSSD_ERROR_NONE;
+}
+
+
+int dnssd_service_get_ip(dnssd_service_h dnssd_service, char **ip_v4_address,
+               char **ip_v6_address)
+{
+       __DNSSD_LOG_FUNC_ENTER__;
+       dnssd_handle_s *local_handle = NULL;
+       dnssd_found_data_s *found = NULL;
+       unsigned char *addr = NULL;
+
+       CHECK_FEATURE_SUPPORTED(NETWORK_SERVICE_DISCOVERY_FEATURE);
+
+       if (__dnssd_is_init() == false) {
+               DNSSD_LOGE("Not initialized");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_NOT_INITIALIZED;
+       }
+
+       if (ip_v4_address == NULL && ip_v6_address == NULL) {
+               DNSSD_LOGE("Invalid Parameter");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_INVALID_PARAMETER;
+       }
+
+       local_handle = __dnssd_check_handle_validity(dnssd_service);
+       if (local_handle == NULL) {
+               DNSSD_LOGD("Service Handler not found");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_INVALID_PARAMETER;
+       }
+
+       if(local_handle->op_type != DNSSD_TYPE_FOUND) {
+               DNSSD_LOGD("Invalid DNS SD Service");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_INVALID_PARAMETER;
+       }
+
+       found = GET_FOUND_DATA_P(local_handle);
+
+       addr = found->ip_v4_addr;
+       *ip_v4_address = g_strdup_printf("%d.%d.%d.%d",
+                       addr[0], addr[1], addr[2], addr[3]);
+
+       addr = found->ip_v6_addr;
+       *ip_v6_address = g_strdup_printf("%02X%02X:"
+                       "%02X%02X:%02X%02X:%02X%02X:"
+                       "%02X%02X:%02X%02X:%02X%02X:"
+                       "%02X%02X", addr[0], addr[1],
+                       addr[2], addr[3], addr[4],
+                       addr[5], addr[6], addr[7],
+                       addr[8], addr[9], addr[10],
+                       addr[11], addr[12], addr[14],
+                       addr[14], addr[15]);
+
+       __DNSSD_LOG_FUNC_EXIT__;
+       return DNSSD_ERROR_NONE;
+}
+
+int dnssd_service_get_port(dnssd_service_h dnssd_service, int *port)
+{
+       __DNSSD_LOG_FUNC_ENTER__;
+       dnssd_handle_s *local_handle = NULL;
+
+       CHECK_FEATURE_SUPPORTED(NETWORK_SERVICE_DISCOVERY_FEATURE);
+
+       if (__dnssd_is_init() == false) {
+               DNSSD_LOGE("Not initialized");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_NOT_INITIALIZED;
+       }
+
+       if (port == NULL) {
+               DNSSD_LOGE("Invalid Parameter");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_INVALID_PARAMETER;
+       }
+
+       local_handle = __dnssd_check_handle_validity(dnssd_service);
+       if (local_handle == NULL) {
+               DNSSD_LOGD("Service Handler not found");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_INVALID_PARAMETER;
+       }
+
+       if(local_handle->op_type == DNSSD_TYPE_FOUND) {
+               dnssd_found_data_s *found = NULL;
+               found = GET_FOUND_DATA_P(local_handle);
+               *port = found->port;
+       } else if(local_handle->op_type == DNSSD_TYPE_REGISTER) {
+               dnssd_register_data_s *reg = NULL;
+               reg = GET_REG_DATA_P(local_handle);
+               *port = reg->port;
+       } else {
+               *port = 0;
+               DNSSD_LOGD("Invalid DNS SD service");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_INVALID_PARAMETER;
+       }
+       DNSSD_LOGD("Port %d", *port);
+
+       __DNSSD_LOG_FUNC_EXIT__;
+       return DNSSD_ERROR_NONE;
+}
+
+int dnssd_service_get_all_txt_record(dnssd_service_h dnssd_service,
+               unsigned short *length, void **value)
+{
+       __DNSSD_LOG_FUNC_ENTER__;
+       TXTRecordRef *txt_record;
+       dnssd_handle_s *local_handle;
+
+       CHECK_FEATURE_SUPPORTED(NETWORK_SERVICE_DISCOVERY_FEATURE);
+
+       if (__dnssd_is_init() == false) {
+               DNSSD_LOGE("Not initialized");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_NOT_INITIALIZED;
+       }
+
+       local_handle = __dnssd_check_handle_validity(dnssd_service);
+       if (local_handle == NULL) {
+               DNSSD_LOGE("Service Handler not found");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_INVALID_PARAMETER;
+       }
+
+       if (value == NULL || length == NULL) {
+               DNSSD_LOGE("Invalid Parameter");
+               __DNSSD_LOG_FUNC_EXIT__;
+               return DNSSD_ERROR_INVALID_PARAMETER;
+       }
+
+       if(local_handle->op_type == DNSSD_TYPE_FOUND) {
+
+               dnssd_found_data_s *found = NULL;
+               found = GET_FOUND_DATA_P(local_handle);
+
+               *value = g_strdup(found->txt_record);
+               *length = found->txt_len;
+       } else {
+
+               dnssd_register_data_s *reg = NULL;
+               reg = GET_REG_DATA_P(local_handle);
+               txt_record = &(reg->txt_ref);
+
+               *value = TXTRecordGetBytesPtr(txt_record);
+               *length = TXTRecordGetLength(txt_record);
+       }
+
+       __DNSSD_LOG_FUNC_EXIT__;
+       return DNSSD_ERROR_NONE;
+}
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
new file mode 100644 (file)
index 0000000..040bc0f
--- /dev/null
@@ -0,0 +1,22 @@
+SET(INC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../include)
+INCLUDE_DIRECTORIES(${INC_DIR})
+
+INCLUDE(FindPkgConfig)
+pkg_check_modules(TARGET_NSD_TESTS REQUIRED capi-base-common glib-2.0)
+FOREACH(flag ${TARGET_NSD_TESTS_CFLAGS})
+    SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+    MESSAGE(${flag})
+ENDFOREACH()
+
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -Wall -fPIE")
+SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -pie")
+
+aux_source_directory(. sources)
+FOREACH(src ${sources})
+    GET_FILENAME_COMPONENT(src_name ${src} NAME_WE)
+    MESSAGE("${src_name}")
+    ADD_EXECUTABLE(${src_name} ${src})
+    TARGET_LINK_LIBRARIES(${src_name} ${TARGET_LIB_NSD_DNS_SD} ${TARGET_NSD_TESTS_LDFLAGS})
+ENDFOREACH()
+
+INSTALL(TARGETS dns-sd-test RUNTIME DESTINATION ${BIN_DIR})
diff --git a/test/dns-sd-test.c b/test/dns-sd-test.c
new file mode 100644 (file)
index 0000000..363739b
--- /dev/null
@@ -0,0 +1,624 @@
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <glib.h>
+#include <netdb.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "dns-sd.h"
+
+gboolean test_thread(GIOChannel *source, GIOCondition condition, gpointer data);
+
+static bool test_get_user_string(const char *msg, char *buf, int buf_size)
+{
+       if (msg == NULL || buf == NULL || buf_size < 2)
+               return false;
+
+       int i = 0, c;
+       printf("%s\n", msg);
+       memset(buf, 0, buf_size);
+       while (true) {
+               c = getchar();
+               if (i == 0 && c == '\n')
+                       continue;
+
+               if (c == '\n')
+                       break;
+
+               buf[i++] = c;
+               if (i == buf_size-1)
+                       break;
+       }
+
+       buf[i]='\0';
+       return true;
+}
+
+static bool test_get_user_bytes(const char *msg, char *buf, int buf_size)
+{
+       if (msg == NULL || buf == NULL || buf_size < 2)
+               return false;
+
+       int i = 0, c;
+       printf("%s\n", msg);
+       memset(buf, 0, buf_size);
+       while (true) {
+               c = getchar();
+               if (i == 0 && c == '\n')
+                       continue;
+
+               if (c == '\n')
+                       break;
+
+               buf[i++] = c;
+               if (i == buf_size-1)
+                       break;
+       }
+
+       return true;
+}
+
+static const char *dnssd_error_to_string(dnssd_error_e error)
+{
+       switch (error) {
+       case DNSSD_ERROR_NONE:
+               return "DNSSD_ERROR_NONE";
+       case DNSSD_ERROR_OUT_OF_MEMORY:
+               return "DNSSD_ERROR_OUT_OF_MEMORY";
+       case DNSSD_ERROR_INVALID_PARAMETER:
+               return "DNSSD_ERROR_INVALID_PARAMETER";
+       case DNSSD_ERROR_NOT_SUPPORTED:
+               return "DNSSD_ERROR_NOT_SUPPORTED";
+       case DNSSD_ERROR_NOT_INITIALIZED:
+               return "DNSSD_ERROR_NOT_INITIALIZED";
+       case DNSSD_ERROR_ALREADY_REGISTERED:
+               return "DNSSD_ERROR_ALREADY_REGISTERED";
+       case DNSSD_ERROR_NAME_CONFLICT:
+               return "DNSSD_ERROR_NAME_CONFLICT";
+       case DNSSD_ERROR_SERVICE_NOT_RUNNING:
+               return "DNSSD_ERROR_SERVICE_NOT_RUNNING";
+       case DNSSD_ERROR_OPERATION_FAILED:
+               return "DNSSD_ERROR_OPERATION_FAILED";
+       default:
+               return "UNSUPPORTED_ERROR";
+       }
+}
+
+static void show_txt_record(unsigned short txt_len, const char *txt_record)
+{
+       const char *ptr = txt_record;
+       const char *max = txt_record + txt_len;
+       while (ptr < max) {
+               const char *const end = ptr + 1 + ptr[0];
+               if (end > max) {
+                       printf("<< invalid data >>");
+                       break;
+               }
+               if (++ptr < end)
+                       printf(" ");
+               while (ptr < end) {
+                       if (*ptr >= ' ')
+                                  printf("%c", *ptr);
+                       ptr++;
+               }
+       }
+       printf("\n");
+}
+
+
+int test_dnssd_initialize()
+{
+       int rv;
+       printf("Initialize DNS SD CAPI\n");
+
+       rv = dnssd_initialize();
+       if(rv != DNSSD_ERROR_NONE) {
+               printf("Failed to Initialize DNS SD CAPI [%s]\n",
+                               dnssd_error_to_string(rv));
+               return rv;
+       }
+       printf("Successfully Initialized DNS SD CAPI\n");
+       return 1;
+}
+
+int test_dnssd_deinitialize()
+{
+       int rv;
+       printf("De-Initialize DNS SD CAPI\n");
+
+       rv = dnssd_deinitialize();
+       if(rv != DNSSD_ERROR_NONE) {
+               printf("Failed to De-Initialize DNS SD CAPI [%s]\n",
+                               dnssd_error_to_string(rv));
+               return rv;
+       }
+       printf("Successfully De-Initialized DNS SD CAPI\n");
+       return 1;
+}
+
+int test_dnssd_create_local_service()
+{
+       int rv = -1;
+
+       dnssd_service_h service = 0;
+       char service_type[255];
+       printf("Create DNS Service\n");
+       test_get_user_string("Enter type:(Example : _http._tcp, "
+                       "_printer._tcp etc)", service_type, 255);
+       rv = dnssd_create_local_service(service_type, &service);
+       if (rv != DNSSD_ERROR_NONE) {
+               printf("Failed to create DNS SD Service, error [%s]\n",
+                               dnssd_error_to_string(rv));
+               return rv;
+       }
+
+       printf("Successfully created DNS SD Service[%u]\n", service);
+       return 1;
+}
+
+int test_dnssd_destroy_local_service()
+{
+       int rv = -1;
+       dnssd_service_h service = 0;
+       printf("Destroy DNS Service\n");
+       printf("Enter Local Service Handle:\n");
+       rv = scanf("%u", &service);
+       rv = dnssd_destroy_local_service(service);
+       if (rv != DNSSD_ERROR_NONE) {
+               printf("Failed to destroy DNS SD Service, error [%s]\n",
+                               dnssd_error_to_string(rv));
+               return rv;
+       }
+
+       printf("Successfully destroyed DNS SD Service\n");
+       return 1;
+}
+
+static void dnssd_register_reply(dnssd_error_e result,
+               dnssd_service_h local_service, void *user_data)
+{
+       printf("Register Callback\n");
+       printf("Handler  : %u\n", local_service);
+       printf("State : ");
+       switch (result) {
+       case DNSSD_ERROR_NONE:
+               printf("DNSSD_REGISTERED\n");
+               break;
+       case DNSSD_ERROR_ALREADY_REGISTERED:
+               printf("DNSSD_ERROR_ALREADY_REGISTERED\n");
+               break;
+       case DNSSD_ERROR_NAME_CONFLICT:
+               printf("DNSSD_ERROR_NAME_CONFLICT\n");
+               break;
+       default:
+               printf("Unknown State\n");
+       }
+}
+
+int test_dnssd_register_local_service()
+{
+       dnssd_service_h service = 0;
+       int rv;
+       char service_name[255] = {0,};
+       int port;
+
+       printf("Register DNS Service\n");
+       printf("Enter Local Service Handler:\n");
+       rv = scanf("%u", &service);
+
+       test_get_user_string("Enter Service Name:", service_name, 255);
+       rv = dnssd_service_set_name(service, service_name);
+       if (rv != DNSSD_ERROR_NONE) {
+               printf("Failed to set name [%s]\n", dnssd_error_to_string(rv));
+               return 0;
+       }
+
+       printf("Enter port:\n");
+       rv = scanf("%d", &port);
+       rv = dnssd_service_set_port(service, port);
+       if (rv != DNSSD_ERROR_NONE) {
+               printf("Failed to set port [%s]\n", dnssd_error_to_string(rv));
+               return 0;
+       }
+
+       rv = dnssd_register_local_service(service, dnssd_register_reply, NULL);
+       if (rv != DNSSD_ERROR_NONE) {
+               printf("Failed to register for dns service, error [%s]",
+                               dnssd_error_to_string(rv));
+               return 0;
+       }
+       printf("Succeeded to register for dns service");
+       return 1;
+}
+
+int test_dnssd_deregister_local_service()
+{
+       dnssd_service_h service = 0;
+       int rv;
+
+       printf("De-register DNS Service\n");
+       printf("Enter Local Service Handler:\n");
+       rv = scanf("%u", &service);
+
+       rv = dnssd_deregister_local_service(service);
+       if(rv != DNSSD_ERROR_NONE) {
+               printf("Failed to deregister dns service, error [%s]\n",
+                               dnssd_error_to_string(rv));
+               return 0;
+       }
+       printf("Successfully deregistered dns service\n");
+       return 1;
+}
+
+int test_dnssd_service_get_type()
+{
+       int rv = -1;
+       dnssd_service_h service;
+       char * type = NULL;
+       printf("Get DNS-SD service type\n");
+       printf("Enter Service Handler:\n");
+       rv = scanf("%u", &service);
+       rv = dnssd_service_get_type(service, &type);
+       if (rv != DNSSD_ERROR_NONE) {
+               printf("Failed to get DNS SD Service type, error [%s]\n",
+                               dnssd_error_to_string(rv));
+               return rv;
+       }
+
+       if (type)
+               printf("Service type [%s]\n", type);
+       g_free(type);
+       printf("Successfully get DNS SD Service type\n");
+       return 1;
+}
+
+int test_dnssd_service_get_name()
+{
+       int rv = -1;
+       dnssd_service_h service;
+       char * name = NULL;
+       printf("Get DNS-SD Service Name\n");
+       printf("Enter Service Handler:\n");
+       rv = scanf("%u", &service);
+       rv = dnssd_service_get_name(service, &name);
+       if (rv != DNSSD_ERROR_NONE) {
+               printf("Failed to get DNS SD Service name, error [%s]\n",
+                               dnssd_error_to_string(rv));
+               return rv;
+       }
+
+       if (name)
+               printf("Service name [%s]\n", name);
+       g_free(name);
+       printf("Successfully get DNS SD Service name\n");
+       return 1;
+}
+
+int test_dnssd_service_get_ip()
+{
+       int rv = -1;
+       dnssd_service_h service;
+       char * ip_v4_address = NULL;
+       char * ip_v6_address = NULL;
+       printf("Get DNS-SD Service IP\n");
+       printf("Enter Service Handler:\n");
+       rv = scanf("%u", &service);
+       rv = dnssd_service_get_ip(service, &ip_v4_address, &ip_v6_address);
+       if (rv != DNSSD_ERROR_NONE) {
+               printf("Failed to get DNS SD Service IP, error [%s]\n",
+                               dnssd_error_to_string(rv));
+               return rv;
+       }
+
+       printf("Service IP v4 [%s]\n", ip_v4_address);
+       printf("Service IP v6 [%s]\n", ip_v6_address);
+       g_free(ip_v4_address);
+       g_free(ip_v6_address);
+       printf("Successfully get DNS SD Service IP\n");
+       return 1;
+}
+
+int test_dnssd_service_get_port()
+{
+       int rv = -1;
+       dnssd_service_h service;
+       int port = 0;
+       printf("Get DNS-SD Service Port\n");
+       printf("Enter Service Handler:\n");
+       rv = scanf("%u", &service);
+       rv = dnssd_service_get_port(service, &port);
+       if (rv != DNSSD_ERROR_NONE) {
+               printf("Failed to get DNS SD Service port, error [%s]\n",
+                               dnssd_error_to_string(rv));
+               return rv;
+       }
+
+       printf("Service port [%d]\n", port);
+       printf("Successfully get DNS SD Service port\n");
+       return 1;
+}
+
+int test_dnssd_service_set_record()
+{
+       dnssd_service_h service;
+       int rv;
+       unsigned short type, length, buf_len;
+       void *data;
+       char buffer[255];
+       char key[10];
+       printf("Add record to DNS SD Service\n");
+       printf("Enter Local Service Handle:\n");
+       rv = scanf("%u", &service);
+
+       printf("Enter type of Resource Record:\n");
+       rv = scanf("%hu", &type);
+
+       printf("Enter length of Resource Record:\n");
+       rv = scanf("%hu", &buf_len);
+
+       test_get_user_bytes("Enter record data:", buffer, 255);
+       test_get_user_string("Enter TXT Record key:", key, 10);
+
+       rv = dnssd_service_add_txt_record(service, key, buf_len, buffer);
+       if (rv != DNSSD_ERROR_NONE) {
+               printf("Failed to set txt record value\n");
+               return 0;
+       }
+
+       rv = dnssd_service_get_all_txt_record(service, &length, &data);
+       if (rv != DNSSD_ERROR_NONE) {
+               printf("Failed to get txt record value\n");
+               return 0;
+       }
+
+       rv = dnssd_service_set_record(service, type, length, data);
+       if (rv != DNSSD_ERROR_NONE) {
+               printf("Failed to add record\n");
+               return 0;
+       }
+
+       rv = dnssd_service_remove_txt_record(service, key);
+       if (rv != DNSSD_ERROR_NONE) {
+               printf("Failed to unset txt record value\n");
+               return 0;
+       }
+
+       printf("Successfully added record\n");
+
+       return 1;
+}
+
+int test_dnssd_service_unset_record()
+{
+       dnssd_service_h service;
+       int rv;
+       unsigned short type;
+       printf("Remove record from DNS SD Service\n");
+       printf("Enter Local Service Handle:\n");
+       rv = scanf("%u", &service);
+
+       printf("Enter type of Resource Record:\n");
+       rv = scanf("%hu", &type);
+
+       rv = dnssd_service_unset_record(service, type);
+       if (rv != DNSSD_ERROR_NONE) {
+               printf("Failed to remove record\n");
+               return 0;
+       }
+
+       printf("Successfully removed record\n");
+       return 1;
+}
+
+static void dnssd_browse_reply(dnssd_service_state_e service_state,
+               dnssd_service_h remote_service, void *user_data)
+{
+       int rv = 0;
+       printf("Browse Service Callback\n");
+       printf("Handler       : %u\n", remote_service);
+       printf("State         : ");
+       switch (service_state) {
+       case DNSSD_SERVICE_STATE_AVAILABLE:
+               printf("Available\n");
+               break;
+       case DNSSD_SERVICE_STATE_UNAVAILABLE:
+               printf("Un-Available\n");
+               break;
+       case DNSSD_SERVICE_STATE_NAME_LOOKUP_FAILED:
+               printf("Lookup failure for service name\n");
+               break;
+       case DNSSD_SERVICE_STATE_HOST_NAME_LOOKUP_FAILED:
+               printf("Lookup failure for host name and port number\n");
+               break;
+       case DNSSD_SERVICE_STATE_ADDRESS_LOOKUP_FAILED:
+               printf("Lookup failure for IP address\n");
+               break;
+       default:
+               printf("Unknown Browse State\n");
+               break;
+       }
+
+       char *name = NULL;
+       char *type = NULL;
+
+       rv = dnssd_service_get_name(remote_service, &name);
+       if(rv == DNSSD_ERROR_NONE && name != NULL)
+               printf("Service Name  : %s\n", name);
+
+       rv = dnssd_service_get_type(remote_service, &type);
+       if(rv == DNSSD_ERROR_NONE && type != NULL)
+               printf("Service Type  : %s\n", type);
+
+       if(service_state == DNSSD_SERVICE_STATE_AVAILABLE) {
+               char *ip_v4_address = NULL;
+               char *ip_v6_address = NULL;
+               char *txt_record = NULL;
+               unsigned short txt_len = 0;
+               int port = 0;
+
+               rv = dnssd_service_get_ip(remote_service, &ip_v4_address, &ip_v6_address);
+               if(rv  == DNSSD_ERROR_NONE) {
+                       if(ip_v4_address)
+                       printf("IPv4 Address  : %s\n", ip_v4_address);
+                       if(ip_v6_address)
+                       printf("IPv6 Address  : %s\n", ip_v6_address);
+               }
+
+               rv = dnssd_service_get_port(remote_service, &port);
+               printf("Port          : %d\n", port);
+
+               printf("TXT Record    : ");
+               dnssd_service_get_all_txt_record(remote_service, &txt_len,
+                               (void *)&txt_record);
+               show_txt_record(txt_len, txt_record);
+
+               g_free(ip_v4_address);
+               g_free(ip_v6_address);
+               g_free(name);
+               g_free(type);
+               g_free(txt_record);
+       }
+}
+
+int test_dnssd_start_browsing_service()
+{
+       dnssd_service_h service;
+       char service_type[255];
+       int rv;
+
+       printf("Browse DNS Service\n");
+       test_get_user_string("Enter type:(Example : _http._tcp, "
+                       "_printer._tcp etc)", service_type, 255);
+
+       rv = dnssd_start_browsing_service(service_type, &service,
+                       dnssd_browse_reply, NULL);
+       if (rv != DNSSD_ERROR_NONE) {
+               printf("Failed to browse for dns service, error %s",
+                               dnssd_error_to_string(rv));
+               return 0;
+       }
+
+       printf("Succeeded to browse for dns service[%u]\n", service);
+       return 1;
+}
+
+int test_dnssd_stop_browsing_service()
+{
+       dnssd_service_h service;
+       int rv;
+       printf("Enter Browse Service Handle:\n");
+       rv = scanf("%u", &service);
+
+       rv = dnssd_stop_browsing_service(service);
+       if(rv != DNSSD_ERROR_NONE) {
+               printf("Failed to stop browse dns service %s\n",
+                               dnssd_error_to_string(rv));
+               return 0;
+       }
+       printf("Successfully stopped browsing dns service\n");
+       return 1;
+}
+
+static void MenuScreen()
+{
+       printf("_____________________________________\n");
+       printf("|_____________MENU-SCREEN___________|\n");
+       printf("| 0 - EXIT                          |\n");
+       printf("| 1 - Initialize DNS SD             |\n");
+       printf("| 2 - De-Initialize DNS SD             |\n");
+       printf("| 3 - DNS SD Create Service         |\n");
+       printf("| 4 - DNS SD Destroy Service        |\n");
+       printf("| 5 - Register DNS Service          |\n");
+       printf("| 6 - De-Register DNS Service       |\n");
+       printf("| 7 - Add Record to DNS Service     |\n");
+       printf("| 8 - Remove Registered Record      |\n");
+       printf("| 9 - Browse DNS Service            |\n");
+       printf("| a - Stop Browse DNS Service       |\n");
+       printf("|___________________________________|\n");
+}
+
+int test_thread(GIOChannel *source, GIOCondition condition, gpointer data)
+{
+       int rv;
+       char a[10];
+       GMainLoop *mainloop = data;
+
+       printf("Event received from stdin\n");
+
+       rv = read(0, a, 10);
+       if (rv <= 0 || a[0] == '0') {
+               printf("Terminating  Test Application");
+               g_main_loop_quit(mainloop);
+               rv = 1;
+       }
+
+       if (a[0] == '\n' || a[0] == '\r') {
+               printf("\n\n mDNSResponder Test App\n\n");
+               printf("Options..\n");
+               MenuScreen();
+               printf("Press ENTER to show options menu.......\n");
+       }
+
+       switch (a[0]) {
+       case '1':
+               rv = test_dnssd_initialize();
+               break;
+       case '2':
+               rv = test_dnssd_deinitialize();
+               break;
+       case '3':
+               rv = test_dnssd_create_local_service();
+               break;
+       case '4':
+               rv = test_dnssd_destroy_local_service();
+               break;
+       case '5':
+               rv = test_dnssd_register_local_service();
+               break;
+       case '6':
+               rv = test_dnssd_deregister_local_service();
+               break;
+       case '7':
+               rv = test_dnssd_service_set_record();
+               break;
+       case '8':
+               rv = test_dnssd_service_unset_record();
+               break;
+       case '9':
+               rv = test_dnssd_start_browsing_service();
+               break;
+       case 'a':
+               rv = test_dnssd_stop_browsing_service();
+               break;
+       }
+
+       if (rv == 1)
+               printf("\nOperation Succeeded!\n");
+       else
+               printf("\nOperation Failed!\n");
+
+       return TRUE;
+
+}
+
+int main(int argc, char **argv)
+{
+       GMainLoop *mainloop;
+       mainloop = g_main_loop_new (NULL, FALSE);
+
+       GIOChannel *channel = g_io_channel_unix_new(0);
+       g_io_add_watch(channel, (G_IO_IN|G_IO_ERR|G_IO_HUP|G_IO_NVAL),
+                       test_thread, mainloop);
+
+       printf("Test Thread created...\n");
+
+       g_main_loop_run (mainloop);
+
+       printf("Test Application Terminated\n");
+       g_main_loop_unref(mainloop);
+
+       return 0;
+}