From: Saurav Babu Date: Fri, 29 Jan 2016 10:23:53 +0000 (+0530) Subject: [DNS-SD] Implement Basic DNS SD CAPI X-Git-Tag: accepted/tizen/ivi/20160218.084201~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=fd15594cf0f99277c117019268080706c70c265c;p=platform%2Fcore%2Fapi%2Fnsd.git [DNS-SD] Implement Basic DNS SD CAPI Change-Id: Ie7fd341515aeebe62f006fb7212b06f60d5290eb Signed-off-by: Saurav Babu --- diff --git a/CMakeLists.txt b/CMakeLists.txt index fbeed9c..af3f383 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 index 0000000..a76fdba --- /dev/null +++ b/packaging/capi-network-nsd.manifest @@ -0,0 +1,5 @@ + + + + + diff --git a/packaging/capi-network-nsd.spec b/packaging/capi-network-nsd.spec index d89bc7b..74179b1 100644 --- a/packaging/capi-network-nsd.spec +++ b/packaging/capi-network-nsd.spec @@ -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 index 0000000..50eefc9 --- /dev/null +++ b/packaging/libnsd-dns-sd.manifest @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/packaging/nsd-tests.manifest b/packaging/nsd-tests.manifest new file mode 100644 index 0000000..50eefc9 --- /dev/null +++ b/packaging/nsd-tests.manifest @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/pkgconfig/CMakeLists.txt b/pkgconfig/CMakeLists.txt new file mode 100644 index 0000000..31347e3 --- /dev/null +++ b/pkgconfig/CMakeLists.txt @@ -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 index 0000000..3a5b257 --- /dev/null +++ b/pkgconfig/nsd-dns-sd/CMakeLists.txt @@ -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 index 0000000..210dbf8 --- /dev/null +++ b/pkgconfig/nsd-dns-sd/nsd-dns-sd.pc.in @@ -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 index 0000000..a455fd8 --- /dev/null +++ b/src/CMakeLists.txt @@ -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 index 0000000..2740807 --- /dev/null +++ b/src/dns-sd/CMakeLists.txt @@ -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 index 0000000..323682c --- /dev/null +++ b/src/dns-sd/dns-sd-util.h @@ -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 +#include +#include + +#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 /** +#include +#include +#include +#include +#include +#include +#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 .. + * 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 index 0000000..040bc0f --- /dev/null +++ b/test/CMakeLists.txt @@ -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 index 0000000..363739b --- /dev/null +++ b/test/dns-sd-test.c @@ -0,0 +1,624 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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; +}