int dnssd_start_browsing_service_on_interface(const char *service_type, const char *interface,
dnssd_browser_h *dnssd_service, dnssd_found_cb found_cb,
void *user_data);
+
+/**
+ * @brief Browses the services which have @a service_type.
+ * @details @a found_cb will be called whenever a service appear or disapear from the network.
+ * Application will keep browsing until it calls dnssd_cancel_browse_service().
+ * @since_tizen 6.5
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/internet
+ * @remark dnssd_resolve_service() should be called in @a found_cb
+ * if you want to get a service data such as a target host name, a port,
+ * txt record and IP addresses.
+ * @param[in] service_type The DNSSD service type to browse.
+ * @param[out] browser The DNSSD browse service handle
+ * @param[in] found_cb The callback function to be called
+ * @param[in] user_data The user data passed to the callback function
+ * @return @c 0 on success, otherwise negative error value
+ * @retval #DNSSD_ERROR_NONE Successful
+ * @retval #DNSSD_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DNSSD_ERROR_NOT_SUPPORTED Not Supported
+ * @retval #DNSSD_ERROR_SERVICE_NOT_RUNNING Service Not Running
+ * @retval #DNSSD_ERROR_NOT_INITIALIZED Not Initialized
+ * @retval #DNSSD_ERROR_PERMISSION_DENIED Permission Denied
+ * see dnssd_cancel_browse_service()
+ */
+int dnssd_browse_service(const char *service_type, const char *interface,
+ dnssd_browser_h *browser, dnssd_found_cb found_cb, void *user_data);
+
+/**
+ * @brief Cancels browsing the services.
+ * @since_tizen 6.5
+ * @param[in] browser The DNSSD browse service handle returned by dnssd_browse_service()
+ * @return @c 0 on success, otherwise negative error value
+ * @retval #DNSSD_ERROR_NONE Successful
+ * @retval #DNSSD_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DNSSD_ERROR_NOT_SUPPORTED Not Supported
+ * @retval #DNSSD_ERROR_SERVICE_NOT_RUNNING Service Not Running
+ * @retval #DNSSD_ERROR_NOT_INITIALIZED Not Initialized
+ * see dnssd_browse_service()
+ */
+
+int dnssd_cancel_browse_service(dnssd_browser_h browser);
+
+/**
+ * @brief Called when the service is resolved.
+ * @since_tizen 6.5
+ * @param[in] result The result of resolving.
+ * @param[in] service The resolved service.
+ * @param[in] user_data The user data passed from the request function
+ * @see dnssd_resolve_service()
+ */
+typedef void (*dnssd_resolved_cb) (dnssd_error_e result,
+ dnssd_service_h service, void *user_data);
+
+/**
+ * @brief Resolves a service browsed by dnssd_browse_service().
+ * @details @a resolved_cb will be called whenever a service is resolved.
+ * You can get a target host name, a port, txt record and IP addresses
+ * from @a resolved_cb. If you have gotten the desired results,
+ * cancel resolving service using dnssd_cancel_resolve_service().
+ * @since_tizen 6.5
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/internet
+ * @param[in] service The DNSSD service handle
+ * @param[in] resolved_cb The callback function to be called
+ * @param[in] user_data The user data passed to the callback function
+ * @return @c 0 on success, otherwise negative error value
+ * @retval #DNSSD_ERROR_NONE Successful
+ * @retval #DNSSD_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DNSSD_ERROR_NOT_SUPPORTED Not Supported
+ * @retval #DNSSD_ERROR_SERVICE_NOT_RUNNING Service Not Running
+ * @retval #DNSSD_ERROR_NOT_INITIALIZED Not Initialized
+ * @retval #DNSSD_ERROR_PERMISSION_DENIED Permission Denied
+ * @see dnssd_browse_service()
+ * @see dnssd_cancel_resolve_service()
+ */
+int dnssd_resolve_service(dnssd_service_h service,
+ dnssd_resolved_cb resolved_cb, void *user_data);
+
+/**
+ * @brief Cancels resolving a service.
+ * @since_tizen 6.5
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/internet
+ * @param[in] service The DNSSD service handle
+ * @return @c 0 on success, otherwise negative error value
+ * @retval #DNSSD_ERROR_NONE Successful
+ * @retval #DNSSD_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #DNSSD_ERROR_NOT_SUPPORTED Not Supported
+ * @retval #DNSSD_ERROR_SERVICE_NOT_RUNNING Service Not Running
+ * @retval #DNSSD_ERROR_NOT_INITIALIZED Not Initialized
+ * @retval #DNSSD_ERROR_PERMISSION_DENIED Permission Denied
+ * @see dnssd_resolve_service()
+ */
+int dnssd_cancel_resolve_service(dnssd_service_h service);
+
#ifdef __cplusplus
}
#endif
#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 INT_TO_POINTER(i) ((void *) (glong) (i))
+#define POINTER_TO_INT(p) ((gint) (glong) (p))
#define REG_SIZE (sizeof(dnssd_handle_s) + sizeof(dnssd_register_data_s))
#define BROWSE_SIZE (sizeof(dnssd_handle_s) + sizeof(dnssd_browse_data_s))
return FALSE;
}
+static void __update_found_address(const struct sockaddr *address, dnssd_found_data_s *found)
+{
+ if (!address || !found)
+ return;
+
+ if (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->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);
+ }
+}
+
static void __dnssd_getaddrinfo_reply_cb(DNSServiceRef sd_ref,
unsigned int flags, unsigned int if_index,
DNSServiceErrorType error_code, const char *host_name,
DNSSD_LOCK;
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;
+ dnssd_service_state_e service_state;
if (user_data == NULL) {
DNSSD_LOGD("Invalid found handle");
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);
- }
+ __update_found_address(address, found);
if (flags & kDNSServiceFlagsMoreComing) {
DNSSD_LOGD("More results are queued, No need to send callback to "
return;
}
- if (callback) {
- if (flags & kDNSServiceFlagsAdd)
- callback(DNSSD_SERVICE_STATE_AVAILABLE,
- local_handle->service_handler, data);
- else
- callback(DNSSD_SERVICE_STATE_UNAVAILABLE,
- local_handle->service_handler, data);
+ if(local_handle->op_type == DNSSD_TYPE_FOUND_NOT_RESOLVED) {
+ local_handle->op_type = DNSSD_TYPE_FOUND;
+ found->callback.resolved_cb(DNSSD_ERROR_NONE,
+ local_handle->service_handler, found->user_data);
+ DNSSD_LOGD("Finished executing Resolve callback");
+ } else {
+ service_state = (flags & kDNSServiceFlagsAdd) ? DNSSD_SERVICE_STATE_AVAILABLE
+ : DNSSD_SERVICE_STATE_UNAVAILABLE;
+ found->callback.found_cb(service_state, local_handle->service_handler, found->user_data);
DNSSD_LOGD("Finished executing Browse %s callback",
(flags & kDNSServiceFlagsAdd) ? "Available" : "Unavailable");
}
+
g_idle_add_full(G_PRIORITY_HIGH, __remove_service_getaddrinfo_socket,
local_handle, NULL);
DNSSD_UNLOCK;
}
-static int __dnssd_getaddrinfo(dnssd_handle_s *dnssd_handle, unsigned int flags,
- unsigned int if_index, const char *host_name, char *service_name,
- const char *fullname, const char *txt_record,
- unsigned short txt_len, int port)
+static dnssd_handle_s *__create_found_service(dnssd_handle_s *dnssd_handle, dnssd_type_e op_type,
+ unsigned int flags, unsigned int if_index,
+ const char *host_name, const char *service_name, const char *domain, int port,
+ const char *txt_record, unsigned short txt_len)
{
- DNSServiceErrorType ret;
- dnssd_handle_s *local_handle = NULL;
- dnssd_found_data_s *found = NULL;
- char *name;
- char *domain;
- char *save_str = NULL;
- 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;
- }
+ if (dnssd_handle == NULL)
+ return NULL;
- /* fullname is of the form <servicename>.<protocol>.<domain>
- * Extract servicename and domain from fullname */
- name = g_strdup(fullname);
- if (name == NULL) {
- DNSSD_LOGE("Invalid browse handle");
- return DNSSD_ERROR_OPERATION_FAILED;
- }
- domain = strtok_r(name, ".", &save_str);
- domain = strtok_r(NULL, ".", &save_str);
- domain = strtok_r(NULL, ".", &save_str);
- domain = strtok_r(NULL, ".", &save_str);
-
- local_handle = g_try_malloc0(FOUND_SIZE);
+ dnssd_found_data_s *found = NULL;
+ dnssd_handle_s *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;
+ return NULL;
}
found = GET_FOUND_DATA_P(local_handle);
- local_handle->op_type = DNSSD_TYPE_FOUND;
+ local_handle->op_type = op_type;
local_handle->service_handler = (uintptr_t)local_handle & 0xffffffff;
if (domain)
g_strlcpy(local_handle->domain, domain, sizeof(local_handle->domain));
- g_free(name);
found->if_index = if_index;
local_handle->flags = flags;
found->host = g_strdup(host_name);
found->port = (int)ntohs(port);
- DNSSD_LOGD("Create found handle [%u]", local_handle->service_handler);
+ dnssd_browse_data_s *browse = GET_BROWSE_DATA_P(dnssd_handle);
+ if (browse) {
+ found->callback.found_cb = browse->callback;
+ found->user_data = browse->user_data;
+ }
+ 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));
+ return local_handle;
+}
+
+/* fullname is of the form <servicename>.<protocol>.<domain>
+ * Extract servicename and domain from fullname */
+static void __extract_domain_from_name(const char *fullname, char **domain)
+{
+ char *name = NULL;
+ char *save_str = NULL;
+
+ name = g_strdup(fullname);
+ if (name == NULL)
+ return;
+
+ *domain = strtok_r(name, ".", &save_str);
+ *domain = strtok_r(NULL, ".", &save_str);
+ *domain = strtok_r(NULL, ".", &save_str);
+ *domain = strtok_r(NULL, ".", &save_str);
+}
+
+static int __dnssd_getaddrinfo(dnssd_handle_s *dnssd_handle, unsigned int flags,
+ unsigned int if_index, const char *host_name, char *service_name,
+ const char *fullname, const char *txt_record,
+ unsigned short txt_len, int port)
+{
+ DNSServiceErrorType ret;
+ dnssd_handle_s *local_handle = NULL;
+ char *domain = NULL;
+ 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;
+ }
+
+ DNSSD_LOGD("dnssd_handle[%p] optype[%d]", dnssd_handle, dnssd_handle->op_type);
+ if (dnssd_handle->op_type == DNSSD_TYPE_BROWSE) {
+ __extract_domain_from_name(fullname, &domain);
+ local_handle = __create_found_service(dnssd_handle, DNSSD_TYPE_FOUND,
+ flags, if_index, host_name, service_name, domain, port,
+ txt_record, txt_len);
+ } else if (dnssd_handle->op_type == DNSSD_TYPE_FOUND_NOT_RESOLVED) {
+ local_handle = dnssd_handle;
+ dnssd_found_data_s *found = GET_FOUND_DATA_P(local_handle);
+ found->port = (int)ntohs(port);
+ } else {
+ DNSSD_LOGE("Invalid op_type[%d].", dnssd_handle->op_type);
+ return DNSSD_ERROR_OPERATION_FAILED;
+ }
+
+ if (!local_handle) {
+ DNSSD_LOGE("Failed to get local_handle");
+ return DNSSD_ERROR_OUT_OF_MEMORY;
+ }
+
ret = DNSServiceGetAddrInfo(&(local_handle->sd_ref), flags, if_index,
dns_protocol, host_name,
__dnssd_getaddrinfo_reply_cb, local_handle);
data->dnssd_handle = dnssd_handle;
data->watch_id = 0;
data->service_name = g_strdup(service_name);
-
resolve_handle_list = g_slist_prepend(resolve_handle_list, data);
ret = DNSServiceResolve(&(data->sd_ref), flags, if_index, service_name,
GSList *list;
void *data;
+ int do_resolving = POINTER_TO_INT(user_data);
+
DNSSD_LOGD("Received Browse Reply");
if (error_code != kDNSServiceErr_NoError) {
if (flags & kDNSServiceFlagsAdd) {
/* Resolve address and send callback later */
- __dnssd_resolve_dns_service(dnssd_handle, flags,
- if_index, service_name,
- service_type, domain);
+ if (do_resolving) {
+ __dnssd_resolve_dns_service(dnssd_handle, flags,
+ if_index, service_name,
+ service_type, domain);
+ } else {
+ dnssd_browse_data_s *browse = GET_BROWSE_DATA_P(dnssd_handle);
+ if (browse->callback) {
+ dnssd_handle_s *found_service = __create_found_service(dnssd_handle,
+ DNSSD_TYPE_FOUND_NOT_RESOLVED, flags,
+ if_index, NULL, service_name, domain, -1, NULL, 0);
+ if (found_service)
+ browse->callback(DNSSD_SERVICE_STATE_AVAILABLE,
+ (dnssd_service_h)found_service, browse->user_data);
+ }
+ }
} else {
-
dnssd_browse_data_s *browse = NULL;
dnssd_found_cb callback;
dnssd_handle_s *found_handle;
__DNSSD_LOG_FUNC_EXIT__;
}
-EXPORT_API int dnssd_start_browsing_service(const char *service_type,
- dnssd_browser_h *dnssd_service, dnssd_found_cb found_cb,
- void *user_data)
+static int _dnssd_browse_service(const char *service_type, const char *interface, int do_resolving,
+ dnssd_browser_h *browser, dnssd_found_cb found_cb, void *user_data)
{
__DNSSD_LOG_FUNC_ENTER__;
DNSServiceErrorType ret;
dnssd_handle_s *local_handle;
dnssd_browse_data_s *browse;
unsigned int handler;
+ unsigned int if_index;
CHECK_FEATURE_SUPPORTED(NETWORK_SERVICE_DISCOVERY_FEATURE);
DNSSD_LOCK;
CHECK_PERMISSION();
-
CHECK_INITIALIZED();
- if (found_cb == NULL || dnssd_service == NULL || service_type == NULL ||
- __dnssd_get_struct_from_handle(*dnssd_service) != NULL) {
+ if (found_cb == NULL || browser == NULL || service_type == NULL ||
+ __dnssd_get_struct_from_handle(*browser) != NULL) {
DNSSD_LOGE("Invalid Parameter");
DNSSD_UNLOCK;
__DNSSD_LOG_FUNC_EXIT__;
return DNSSD_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE
}
+ if (interface && (if_index = if_nametoindex(interface)) == 0) {
+ DNSSD_LOGE("Invalid interface name");
+ g_free(local_handle);
+ DNSSD_UNLOCK;
+ __DNSSD_LOG_FUNC_EXIT__;
+ return DNSSD_ERROR_INVALID_PARAMETER;
+ } else {
+ if_index = kDNSServiceInterfaceIndexAny;
+ }
+ DNSSD_LOGD("Interface index: %u", if_index);
+
handler = (uintptr_t)local_handle & 0xffffffff;
- *dnssd_service = handler;
+ *browser = handler;
local_handle->service_handler = handler;
local_handle->op_type = DNSSD_TYPE_BROWSE;
local_handle->service_type = g_strdup(service_type);
browse = GET_BROWSE_DATA_P(local_handle);
DNSSD_LOGD("New browse handle created [%p]->[%u] type %s", local_handle,
- *dnssd_service, local_handle->service_type);
+ *browser, local_handle->service_type);
ret = DNSServiceBrowse(&(local_handle->sd_ref), local_handle->flags,
- kDNSServiceInterfaceIndexAny, local_handle->service_type,
+ if_index, local_handle->service_type,
local_handle->domain, __dnssd_browse_reply_cb,
- NULL);
+ INT_TO_POINTER(do_resolving));
if (ret != kDNSServiceErr_NoError) {
DNSSD_LOGE("Failed to browse for dns service, error[%s]", //LCOV_EXCL_LINE
dnssd_error_to_string(ret)); //LCOV_EXCL_LINE
return DNSSD_ERROR_NONE;
}
+EXPORT_API int dnssd_start_browsing_service(const char *service_type,
+ dnssd_browser_h *dnssd_service, dnssd_found_cb found_cb,
+ void *user_data)
+{
+ return _dnssd_browse_service(service_type, NULL, 1, dnssd_service, found_cb, user_data);
+}
+
EXPORT_API int dnssd_start_browsing_service_on_interface(const char *service_type, const char *interface,
dnssd_browser_h *dnssd_service, dnssd_found_cb found_cb,
void *user_data)
+{
+ if (interface == NULL)
+ return DNSSD_ERROR_INVALID_PARAMETER;
+
+ return _dnssd_browse_service(service_type, interface, 1, dnssd_service, found_cb, user_data);
+}
+
+EXPORT_API int dnssd_browse_service(const char *service_type, const char *interface,
+ dnssd_browser_h *browser, dnssd_found_cb found_cb, void *user_data)
+{
+ return _dnssd_browse_service(service_type, interface, 0, browser, found_cb, user_data);
+}
+
+EXPORT_API int dnssd_cancel_browse_service(dnssd_browser_h browser)
+{
+ return DNSSD_ERROR_NONE;
+}
+
+static int _dnssd_resolve_service(dnssd_handle_s *local_handle,
+ dnssd_resolved_cb resolved_cb, void *user_data)
+{
+ dnssd_found_data_s *found = GET_FOUND_DATA_P(local_handle);
+ if (!found)
+ return DNSSD_ERROR_OPERATION_FAILED;
+
+ found->callback.resolved_cb = resolved_cb;
+ found->user_data = user_data;
+
+ return __dnssd_resolve_dns_service(local_handle, local_handle->flags, found->if_index,
+ found->service_name, local_handle->service_type, local_handle->domain);
+}
+
+EXPORT_API int dnssd_resolve_service(dnssd_service_h service,
+ dnssd_resolved_cb resolved_cb, void *user_data)
{
__DNSSD_LOG_FUNC_ENTER__;
- DNSServiceErrorType ret;
- dnssd_handle_s *local_handle;
- dnssd_browse_data_s *browse;
- unsigned int handler;
- unsigned int if_index;
+ dnssd_handle_s *local_handle = NULL;
+ int res = DNSSD_ERROR_NONE;
CHECK_FEATURE_SUPPORTED(NETWORK_SERVICE_DISCOVERY_FEATURE);
DNSSD_LOCK;
- CHECK_PERMISSION();
-
CHECK_INITIALIZED();
- if (found_cb == NULL || dnssd_service == NULL || service_type == NULL ||
- __dnssd_get_struct_from_handle(*dnssd_service) != NULL) {
- DNSSD_LOGE("Invalid Parameter");
- DNSSD_UNLOCK;
- __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"); //LCOV_EXCL_LINE
- DNSSD_UNLOCK;
- __DNSSD_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
- return DNSSD_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE
- }
-
- if ((if_index = if_nametoindex(interface)) == 0) {
- DNSSD_LOGE("Invalid interface name");
- g_free(local_handle);
+ res = __get_valid_handle(service, &local_handle);
+ if (res != DNSSD_ERROR_NONE) {
DNSSD_UNLOCK;
- __DNSSD_LOG_FUNC_EXIT__;
- return DNSSD_ERROR_INVALID_PARAMETER;
+ return res;
}
- DNSSD_LOGD("Interface index: %u", if_index);
-
- handler = (uintptr_t)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->watch_id = 0;
- browse = GET_BROWSE_DATA_P(local_handle);
- DNSSD_LOGD("New browse handle created [%p]->[%u] type %s", local_handle,
- *dnssd_service, local_handle->service_type);
-
- ret = DNSServiceBrowse(&(local_handle->sd_ref), local_handle->flags,
- if_index, local_handle->service_type,
- local_handle->domain, __dnssd_browse_reply_cb,
- NULL);
- if (ret != kDNSServiceErr_NoError) {
- DNSSD_LOGE("Failed to browse for dns service, error[%s]", //LCOV_EXCL_LINE
- dnssd_error_to_string(ret)); //LCOV_EXCL_LINE
- g_free(local_handle->service_type); //LCOV_EXCL_LINE
- g_free(local_handle); //LCOV_EXCL_LINE
+ if (local_handle->op_type != DNSSD_TYPE_FOUND_NOT_RESOLVED) {
+ DNSSD_LOGD("Not matched type. [%d]", local_handle->op_type);
DNSSD_UNLOCK;
- __DNSSD_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
- return DNSSD_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
+ return DNSSD_ERROR_OPERATION_FAILED;
}
- browse->callback = found_cb;
- browse->user_data = user_data;
- dnssd_handle_list = g_slist_prepend(dnssd_handle_list, local_handle);
- __dnssd_handle_add_event_handler(&(local_handle->watch_id), local_handle);
+ res = _dnssd_resolve_service(local_handle, resolved_cb, user_data);
- DNSSD_LOGD("Succeeded to browse for dns service");
DNSSD_UNLOCK;
__DNSSD_LOG_FUNC_EXIT__;
+ return res;
+}
+
+EXPORT_API int dnssd_cancel_resolve_service(dnssd_service_h service)
+{
return DNSSD_ERROR_NONE;
}
--- /dev/null
+/*
+* Copyright (c) 2021 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 <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <glib.h>
+
+#include "dns-sd.h"
+#include "dns-sd-internal.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' || c == EOF)
+ break;
+
+ buf[i++] = c;
+ if (i == buf_size-1)
+ break;
+ }
+
+ buf[i] = '\0';
+ 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 unsigned char *txt_record)
+{
+ const unsigned char *ptr = txt_record;
+ const unsigned char *max = txt_record + txt_len;
+ while (ptr < max) {
+ const unsigned char *const end = ptr + 1 + ptr[0];
+ if (end > max) {
+ printf("<< invalid data >>");
+ break;
+ }
+ if (++ptr < end)
+ printf(" "); /* As long as string is non-empty, begin with a space */
+ while (ptr < end) {
+ if (strchr(" &;`'\"|*?~<>^()[]{}$", *ptr))
+ printf("\\");
+ if (*ptr == '\\')
+ printf("\\\\\\\\");
+ else if (*ptr >= ' ')
+ printf("%c", *ptr);
+ else
+ printf("\\\\x%02X", *ptr);
+ ptr++;
+ }
+ }
+ printf("\n");
+}
+
+static void _resolve_cb(dnssd_error_e result, dnssd_service_h service, void *user_data)
+{
+ char *name = NULL;
+ char *type = NULL;
+ char *ip_v4_address = NULL;
+ char *ip_v6_address = NULL;
+ unsigned char *txt_record = NULL;
+ unsigned short txt_len = 0;
+ int port = 0;
+
+ printf("Resolve Service Callback\n");
+ int rv = dnssd_service_get_name(service, &name);
+ if (rv == DNSSD_ERROR_NONE && name != NULL)
+ printf("Service Name : %s\n", name);
+
+ rv = dnssd_service_get_type(service, &type);
+ if (rv == DNSSD_ERROR_NONE && type != NULL)
+ printf("Service Type : %s\n", type);
+
+ rv = dnssd_service_get_ip(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(service, &port);
+ printf("Port : %d\n", port);
+
+ printf("TXT Record : ");
+ dnssd_service_get_all_txt_record(service, &txt_len,
+ (void *)&txt_record);
+ show_txt_record(txt_len, txt_record);
+ printf("\n");
+
+ g_free(ip_v4_address);
+ g_free(ip_v6_address);
+ g_free(txt_record);
+ g_free(name);
+ g_free(type);
+}
+
+static void _browse_cb(dnssd_service_state_e service_state,
+ dnssd_service_h service, void *user_data)
+{
+ printf("Browse Service Callback\n");
+ printf("Handler : %u\n", 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;
+ }
+
+ if (service_state == DNSSD_SERVICE_STATE_AVAILABLE) {
+ int rv = dnssd_resolve_service(service, _resolve_cb, NULL);
+ if (rv != DNSSD_ERROR_NONE)
+ printf("Failed to resolve a service.\n");
+ }
+ printf("\n");
+}
+
+int test_dnssd_browse_service()
+{
+ dnssd_service_h service = 0;
+ 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_browse_service(service_type, NULL, &service, _browse_cb, 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_cancel_browse_service()
+{
+ dnssd_browser_h browser;
+ int rv;
+ printf("Enter Browse Service Handle:\n");
+ rv = scanf("%u", &browser);
+
+ rv = dnssd_cancel_browse_service(browser);
+ 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 - Browse DNS Service |\n");
+ printf("| 2 - Cancel 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_browse_service();
+ break;
+ case '2':
+ rv = test_dnssd_cancel_browse_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");
+
+ dnssd_initialize();
+
+ g_main_loop_run(mainloop);
+
+ dnssd_deinitialize();
+ printf("Test Application Terminated\n");
+ g_main_loop_unref(mainloop);
+
+ return 0;
+}