From b402da2e7d3c90065609bd5fcffcc2eb50edad36 Mon Sep 17 00:00:00 2001 From: Yu Jiung Date: Tue, 16 Feb 2016 11:57:55 +0900 Subject: [PATCH] Add CAPI for ssdp Change-Id: Icef10b30f3e36b16f921489e8ab89a56b74cee1b --- CMakeLists.txt | 10 +- doc/nsd_doc.h | 73 +++ include/CMakeLists.txt | 1 + include/ssdp.h | 307 ++++++++++++ packaging/capi-network-nsd.spec | 24 +- packaging/libnsd-ssdp.manifest | 5 + pkgconfig/CMakeLists.txt | 1 + pkgconfig/nsd-ssdp/CMakeLists.txt | 24 + pkgconfig/nsd-ssdp/nsd-ssdp.pc.in | 11 + src/CMakeLists.txt | 1 + src/ssdp/CMakeLists.txt | 45 ++ src/ssdp/ssdp-util.h | 77 +++ src/ssdp/ssdp.c | 994 ++++++++++++++++++++++++++++++++++++++ test/CMakeLists.txt | 3 +- test/ssdp-browse-test.c | 65 +++ test/ssdp-register-test.c | 72 +++ test/ssdp-test.c | 523 ++++++++++++++++++++ 17 files changed, 2226 insertions(+), 10 deletions(-) create mode 100644 doc/nsd_doc.h create mode 100644 include/ssdp.h create mode 100644 packaging/libnsd-ssdp.manifest create mode 100644 pkgconfig/nsd-ssdp/CMakeLists.txt create mode 100644 pkgconfig/nsd-ssdp/nsd-ssdp.pc.in create mode 100644 src/ssdp/CMakeLists.txt create mode 100644 src/ssdp/ssdp-util.h create mode 100644 src/ssdp/ssdp.c create mode 100644 test/ssdp-browse-test.c create mode 100644 test/ssdp-register-test.c create mode 100644 test/ssdp-test.c diff --git a/CMakeLists.txt b/CMakeLists.txt index af3f383..fb5b63e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,7 +26,7 @@ INCLUDE(FindPkgConfig) ########################## search for packages ################################ -SET(COMMON_DEPS "dlog glib-2.0 gio-2.0 capi-base-common gio-unix-2.0") +SET(COMMON_DEPS "dlog glib-2.0 gio-2.0 capi-base-common gio-unix-2.0 gssdp-1.0 dns_sd") SET(PC_DEPS "capi-base-common") @@ -34,11 +34,6 @@ PKG_CHECK_MODULES(NSD_DEPS REQUIRED ${COMMON_DEPS}) ######################## directory configuration ############################ -SET(LIB_DIR - "${CMAKE_INSTALL_PREFIX}/lib" - CACHE PATH - "Object code libraries directory") - SET(BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH @@ -83,7 +78,7 @@ FOREACH(flag ${NSD_DEPS_CFLAGS}) ENDFOREACH(flag) -SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIC -Wall -ldns_sd") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIC -Wall") SET(CMAKE_C_FLAGS_DEBUG "-O0 -g") SET(CMAKE_C_FLAGS_RELEASE "-O2 -g") @@ -94,6 +89,7 @@ SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -Wl,--rpath=${LIBDIR}") SET(TARGET_NSD "nsd") SET(TARGET_LIB_NSD_DNS_SD "nsd-dns-sd") +SET(TARGET_LIB_NSD_SSDP "nsd-ssdp") SET(TARGET_NSD_TESTS "nsd-tests") diff --git a/doc/nsd_doc.h b/doc/nsd_doc.h new file mode 100644 index 0000000..ff92501 --- /dev/null +++ b/doc/nsd_doc.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2011 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. + */ + + +#ifndef __TIZEN_NETWORK_SERVICE_DISCOVERY_DOC_H__ +#define __TIZEN_NETWORK_SERVICE_DISCOVERY_DOC_H__ + +/** + * @defgroup CAPI_NETWORK_SSDP_MODULE SSDP + * @brief The SSDP API provides functions for network service discovery using SSDP. + * @ingroup CAPI_NETWORK_FRAMEWORK + * + * @section CAPI_NETWORK_SSDP_MODULE_HEADER Required Header + * \#include + * + * @section CAPI_NETWORK_SSDP_MODULE_OVERVIEW Overview + * SSDP allows your application to create and register a local service. + * You should deregister and destroy the created local service handle if it is not available. + * In addition, you can browse services on a network using SSDP API. + * You should stop browsing if you do not need it anymore. + * @section CAPI_NETWORK_SSDP_MODULE_FEATURE Related Features + * This API is related with the following features:\n + * - http://tizen.org/feature/network.service_discovery.ssdp + * + * It is recommended to design feature related codes in your application for reliability.\n + * + * You can check if a device supports the related features for this API by using @ref CAPI_SYSTEM_SYSTEM_INFO_MODULE, thereby controlling the procedure of your application.\n + * + * To ensure your application is only running on the device with specific features, please define the features in your manifest file using the manifest editor in the SDK.\n + * + * More details on featuring your application can be found from Feature List. + * + */ + +/** + * @defgroup CAPI_NETWORK_DNSSD_MODULE DNSSD + * @brief The DNSSD API provides functions for network service discovery using DNSSD. + * @ingroup CAPI_NETWORK_FRAMEWORK + * + * @section CAPI_NETWORK_DNSSD_MODULE_HEADER Required Header + * \#include + * + * @section CAPI_NETWORK_DNSSD_MODULE_OVERVIEW Overview + * DNSSD allows your application to create and register a local service. + * You should deregister and destroy the created local service handle if it is not available. + * In addition, you can browse services on a network using DNSSD API. + * You should stop browsing if you do not need it anymore. + * @section CAPI_NETWORK_DNSSD_MODULE_FEATURE Related Features + * This API is related with the following features:\n + * - http://tizen.org/feature/network.service_discovery.dnssd + * + * It is recommended to design feature related codes in your application for reliability.\n + * + * You can check if a device supports the related features for this API by using @ref CAPI_SYSTEM_SYSTEM_INFO_MODULE, thereby controlling the procedure of your application.\n + * + * To ensure your application is only running on the device with specific features, please define the features in your manifest file using the manifest editor in the SDK.\n + * + * More details on featuring your application can be found from Feature List. + * + */ diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index 9731d49..a178fd1 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -18,5 +18,6 @@ INSTALL(FILES ${CMAKE_SOURCE_DIR}/include/dns-sd.h + ${CMAKE_SOURCE_DIR}/include/ssdp.h DESTINATION ${INCLUDE_DIR}/nsd ) diff --git a/include/ssdp.h b/include/ssdp.h new file mode 100644 index 0000000..f6bcd26 --- /dev/null +++ b/include/ssdp.h @@ -0,0 +1,307 @@ +/* + * ssdp + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * + * 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_SSDP_H__ +#define __TIZEN_NET_SSDP_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef TIZEN_ERROR_SSDP +#define TIZEN_ERROR_SSDP -0x01C90000 +#endif + + +/** + * @addtogroup CAPI_NETWORK_SSDP_MODULE + * @{ + */ + +/** + * @brief Enumeration for Network Service Discovery SSDP error code. + * @since_tizen 3.0 + */ +typedef enum +{ + SSDP_ERROR_NONE = TIZEN_ERROR_NONE, /**< Successful */ + SSDP_ERROR_OUT_OF_MEMORY = TIZEN_ERROR_OUT_OF_MEMORY, /**< Out of memory */ + SSDP_ERROR_INVALID_PARAMETER = TIZEN_ERROR_INVALID_PARAMETER, /**< Invalid function parameter */ + SSDP_ERROR_NOT_SUPPORTED = TIZEN_ERROR_NOT_SUPPORTED, /**< Not supported */ + SSDP_ERROR_NOT_INITIALIZED = TIZEN_ERROR_SSDP|0x01, /**< Not initialized */ + SSDP_ERROR_OPERATION_FAILED = TIZEN_ERROR_SSDP|0x04, /**< Operation failed */ + SSDP_ERROR_SERVICE_NOT_FOUND = TIZEN_ERROR_SSDP|0x05, /**< Service not found */ + SSDP_ERROR_SERVICE_ALREADY_REGISTERED = TIZEN_ERROR_SSDP|0x06, /**< Service already registered */ +} ssdp_error_e; + +/** + * @brief Enumeration for Network Service Discovery SSDP service browse state. + * @since_tizen 3.0 + */ +typedef enum +{ + SSDP_SERVICE_STATE_AVAILABLE, /**< A new service is available */ + SSDP_SERVICE_STATE_UNAVAILABLE, /**< A service is not available */ +} ssdp_service_state_e; + +/** + * @brief The SSDP service handle + * @since_tizen 3.0 + */ +typedef unsigned int ssdp_service_h; + +/** + * @brief The SSDP browser handle + * @since_tizen 3.0 + */ +typedef unsigned int ssdp_browser_h; + +/** + * @brief Called when the registration of SSDP service is finished. + * @since_tizen 3.0 + * @param[in] result The result of registration + * @param[in] ssdp_service The SSDP local service handle + * @param[in] user_data The user data passed from the request function + * @see ssdp_register_local_service() + */ +typedef void (*ssdp_registered_cb) (ssdp_error_e result, + ssdp_service_h ssdp_local_service, void *user_data); + +/** + * @brief Called when a service has become available or unavailable + * @since_tizen 3.0 + * @param[in] state The state of found service + * @param[in] ssdp_service The SSDP remote service handle + * @param[in] user_data The user data passed from the request function + * @see ssdp_start_browsing_service() + */ +typedef void (*ssdp_found_cb) (ssdp_service_state_e state, + ssdp_service_h ssdp_remote_service, void *user_data); + +/** + * @brief Initializes SSDP. + * @since_tizen 3.0 + * @return 0 on success, otherwise negative error value + * @retval #SSDP_ERROR_NONE Successful + * @retval #SSDP_ERROR_OPERATION_FAILED Operation failed + * @retval #SSDP_ERROR_NOT_SUPPORTED Not supported + */ +int ssdp_initialize(void); + +/** + * @brief Deinitializes SSDP. + * @since_tizen 3.0 + * @return 0 on success, otherwise negative error value + * @retval #SSDP_ERROR_NONE Successful + * @retval #SSDP_ERROR_NOT_SUPPORTED Not supported + */ +int ssdp_deinitialize(void); + +/** + * @brief Creates a SSDP local service handle. + * @since_tizen 3.0 + * @remarks You must release @a local_service using ssdp_destroy_local_service(). + * @param[in] target The SSDP local service's target. It may be a device type or a service type specified in UPnP forum (http://upnp.org). + * @param[out] local_service The SSDP local service handle + * @return 0 on success, otherwise negative error value + * @retval #SSDP_ERROR_NONE Successful + * @retval #SSDP_ERROR_NOT_INITIALIZED Not initialized + * @retval #SSDP_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #SSDP_ERROR_OUT_OF_MEMORY Out of memory + * @retval #SSDP_ERROR_NOT_SUPPORTED Not supported + * @see ssdp_destroy_local_service() + * @pre This API needs ssdp_initialize() before use + */ +int ssdp_create_local_service(const char *target, ssdp_service_h *local_service); + +/** + * @brief Destroys the SSDP local service handle. + * @details You must call ssdp_deregister_local_service() before destroying the local service. + * @since_tizen 3.0 + * @param[in] local_service The SSDP local service handle + * @return 0 on success, otherwise negative error value + * @retval #SSDP_ERROR_NONE Successful + * @retval #SSDP_ERROR_NOT_INITIALIZED Not initialized + * @retval #SSDP_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #SSDP_ERROR_SERVICE_NOT_FOUND Service not found + * @retval #SSDP_ERROR_NOT_SUPPORTED Not supported + * @see ssdp_create_local_service() + */ +int ssdp_destroy_local_service(ssdp_service_h local_service); + +/** + * @brief Sets the USN (Unique Service Name) of SSDP local service. The USN format is specified in UPnP forum (http://upnp.org). + * @since_tizen 3.0 + * @remarks You must pass only @a unregistered local_service created using ssdp_create_local_service(). If @a local_service is already registered, you cannot set @usn + * @param[in] local_service The SSDP local service handle + * @param[in] usn The USN of SSDP local service + * @return 0 on success, otherwise negative error value + * @retval #SSDP_ERROR_NONE Successful + * @retval #SSDP_ERROR_NOT_INITIALIZED Not initialized + * @retval #SSDP_ERROR_SERVICE_NOT_FOUND Service not found + * @retval #SSDP_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #SSDP_ERROR_OUT_OF_MEMORY Out of memory + * @retval #SSDP_ERROR_NOT_SUPPORTED Not supported + */ +int ssdp_service_set_usn(ssdp_service_h local_service, const char *usn); + +/** + * @brief Sets the URL (Uniform Resource Locator) for description of SSDP local service. See RFC 3986. + * @since_tizen 3.0 + * @remarks You must pass only unregistered @a local_service created using ssdp_create_local_service(). If @a local_service is already registered, you cannot set @url + * @param[in] local_service The SSDP local service handle + * @param[in] url The URL of SSDP local service + * @return 0 on success, otherwise negative error value + * @retval #SSDP_ERROR_NONE Successful + * @retval #SSDP_ERROR_NOT_INITIALIZED Not initialized + * @retval #SSDP_ERROR_SERVICE_NOT_FOUND Service not found + * @retval #SSDP_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #SSDP_ERROR_OUT_OF_MEMORY Out of memory + * @retval #SSDP_ERROR_NOT_SUPPORTED Not supported + */ +int ssdp_service_set_url(ssdp_service_h local_service, const char *url); + +/** + * @brief Gets the target of SSDP service. + * @since_tizen 3.0 + * @remarks You must release @a target using free(). + * @param[in] service The SSDP service handle + * @param[out] target The target of SSDP service + * @return 0 on success, otherwise negative error value + * @retval #SSDP_ERROR_NONE Successful + * @retval #SSDP_ERROR_NOT_INITIALIZED Not initialized + * @retval #SSDP_ERROR_SERVICE_NOT_FOUND Service not found + * @retval #SSDP_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #SSDP_ERROR_OUT_OF_MEMORY Out of memory + * @retval #SSDP_ERROR_NOT_SUPPORTED Not supported + */ +int ssdp_service_get_target(ssdp_service_h service, char **target); + +/** + * @brief Gets the USN of SSDP service. + * @since_tizen 3.0 + * @remarks You must release @a usn using free(). + * @param[in] service The SSDP service handle + * @param[out] usn The USN of SSDP service + * @return 0 on success, otherwise negative error value + * @retval #SSDP_ERROR_NONE Successful + * @retval #SSDP_ERROR_NOT_INITIALIZED Not initialized + * @retval #SSDP_ERROR_SERVICE_NOT_FOUND Service not found + * @retval #SSDP_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #SSDP_ERROR_OUT_OF_MEMORY Out of memory + * @retval #SSDP_ERROR_NOT_SUPPORTED Not supported + */ +int ssdp_service_get_usn(ssdp_service_h service, char **usn); + +/** + * @brief Gets the URL of SSDP service. + * @since_tizen 3.0 + * @remarks You must release @a url using free(). + * @param[in] service The SSDP service handle + * @param[out] url The URL of SSDP service + * @return 0 on success, otherwise negative error value + * @retval #SSDP_ERROR_NONE Successful + * @retval #SSDP_ERROR_NOT_INITIALIZED Not initialized + * @retval #SSDP_ERROR_SERVICE_NOT_FOUND Service not found + * @retval #SSDP_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #SSDP_ERROR_OUT_OF_MEMORY Out of memory + * @retval #SSDP_ERROR_NOT_SUPPORTED Not supported + */ +int ssdp_service_get_url(ssdp_service_h service, char **url); + +/** + * @brief Registers the SSDP local service for publishing. + * @details You must set a USN and a URL of the local service before ssdp_register_local_service() is called. + * @since_tizen 3.0 + * @remarks You must pass only local_service created using ssdp_create_local_service(). + * @param[in] local_service The SSDP local service handle + * @param[in] registered_cb The callback function to be called + * @param[in] user_data The user data passed to the callback function + * @return 0 on success, otherwise negative error value + * @retval #SSDP_ERROR_NONE Successful + * @retval #SSDP_ERROR_NOT_INITIALIZED Not initialized + * @retval #SSDP_ERROR_SERVICE_NOT_FOUND Service not found + * @retval #SSDP_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #SSDP_ERROR_OPERATION_FAILED Operation failed + * @retval #SSDP_ERROR_NOT_SUPPORTED Not supported + * @retval #SSDP_ERROR_SERVICE_ALREADY_REGISTERED Service already registered + * @pre This API needs ssdp_service_set_usn() and ssdp_service_set_url() before use + */ +int ssdp_register_local_service(ssdp_service_h local_service, + ssdp_registered_cb registered_cb, void *user_data); + +/** + * @brief Deregisters the SSDP local service. + * @since_tizen 3.0 + * @remarks You must pass only local_service created using ssdp_create_local_service(). + * @param[in] local_service The SSDP local service handle + * @return 0 on success, otherwise negative error value + * @retval #SSDP_ERROR_NONE Successful + * @retval #SSDP_ERROR_NOT_INITIALIZED Not initialized + * @retval #SSDP_ERROR_SERVICE_NOT_FOUND Service not found + * @retval #SSDP_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #SSDP_ERROR_NOT_SUPPORTED Not supported + */ +int ssdp_deregister_local_service(ssdp_service_h local_service); + +/** + * @brief Starts browsing the SSDP remote service. + * @details ssdp_start_browsing_service() keeps browsing services until calling ssdp_stop_browsing_service() + * @since_tizen 3.0 + * @param[in] target The target to browse + * @param[out] ssdp_browser The SSDP browser handle + * @param[in] found_cb The callback function to be called + * @param[in] user_data The user data passed to the callback function + * @return 0 on success, otherwise negative error value + * @retval #SSDP_ERROR_NONE Successful + * @retval #SSDP_ERROR_NOT_INITIALIZED Not initialized + * @retval #SSDP_ERROR_SERVICE_NOT_FOUND Service not found + * @retval #SSDP_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #SSDP_ERROR_OPERATION_FAILED Operation failed + * @retval #SSDP_ERROR_OUT_OF_MEMORY Out of memory + * @retval #SSDP_ERROR_NOT_SUPPORTED Not supported + */ +int ssdp_start_browsing_service(const char* target, ssdp_browser_h* ssdp_browser, + ssdp_found_cb found_cb, void *user_data); + +/** + * @brief Stops browsing the SSDP remote service. + * @since_tizen 3.0 + * @param[in] ssdp_browser The SSDP browser handle + * @return 0 on success, otherwise negative error value + * @retval #SSDP_ERROR_NONE Successful + * @retval #SSDP_ERROR_NOT_INITIALIZED Not initialized + * @retval #SSDP_ERROR_SERVICE_NOT_FOUND Service not found + * @retval #SSDP_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #SSDP_ERROR_NOT_SUPPORTED Not supported + */ +int ssdp_stop_browsing_service(ssdp_browser_h ssdp_browser); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __TIZEN_NET_SSDP_H__ */ diff --git a/packaging/capi-network-nsd.spec b/packaging/capi-network-nsd.spec index 74179b1..884793a 100644 --- a/packaging/capi-network-nsd.spec +++ b/packaging/capi-network-nsd.spec @@ -7,12 +7,14 @@ License: Apache-2.0 Source0: %{name}-%{version}.tar.gz Source1001: capi-network-nsd.manifest Source1002: libnsd-dns-sd.manifest -Source1003: nsd-tests.manifest +Source1003: libnsd-ssdp.manifest +Source1004: nsd-tests.manifest BuildRequires: cmake BuildRequires: pkgconfig(capi-base-common) BuildRequires: pkgconfig(dlog) BuildRequires: pkgconfig(glib-2.0) -BuildRequires: pkgconfig(mDNSResponder) +BuildRequires: pkgconfig(dns_sd) +BuildRequires: pkgconfig(gssdp-1.0) Requires(post): /sbin/ldconfig Requires(postun): /sbin/ldconfig @@ -24,6 +26,7 @@ DNS-SD Tizen C API %package devel Summary: A NSD library in Native API (Development) Requires: libnsd-dns-sd = %{version}-%{release} +Requires: libnsd-ssdp = %{version}-%{release} %description devel Netowrk Service Discovery library in Tizen C API development files @@ -40,6 +43,12 @@ Summary: NSD - DNS-SD library in Tizen C API %description -n libnsd-dns-sd Network Service Discovery library for DNS-SD +%package -n libnsd-ssdp +Summary: NSD - SSDP library in Tizen C API + +%description -n libnsd-ssdp +Network Service Discovery library for SSDP + %prep %setup -q chmod 644 %{SOURCE1001} @@ -48,6 +57,7 @@ chmod 644 %{SOURCE1003} cp -a %{SOURCE1001} . cp -a %{SOURCE1002} . cp -a %{SOURCE1003} . +cp -a %{SOURCE1004} . %build %if 0%{?sec_build_binary_debug_enable} @@ -77,6 +87,10 @@ rm -rf %{buildroot} %postun -n libnsd-dns-sd -p /sbin/ldconfig +%post -n libnsd-ssdp -p /sbin/ldconfig + +%postun -n libnsd-ssdp -p /sbin/ldconfig + %files %manifest capi-network-nsd.manifest %license LICENSE @@ -89,8 +103,14 @@ rm -rf %{buildroot} %files tests %manifest nsd-tests.manifest %attr(755,root,root) %{_bindir}/dns-sd-test +%attr(755,root,root) %{_bindir}/ssdp-test %files -n libnsd-dns-sd %manifest libnsd-dns-sd.manifest %license LICENSE %{_libdir}/libnsd-dns-sd.so.* + +%files -n libnsd-ssdp +%manifest libnsd-ssdp.manifest +%license LICENSE +%{_libdir}/libnsd-ssdp.so.* diff --git a/packaging/libnsd-ssdp.manifest b/packaging/libnsd-ssdp.manifest new file mode 100644 index 0000000..50eefc9 --- /dev/null +++ b/packaging/libnsd-ssdp.manifest @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/pkgconfig/CMakeLists.txt b/pkgconfig/CMakeLists.txt index 31347e3..daae87b 100644 --- a/pkgconfig/CMakeLists.txt +++ b/pkgconfig/CMakeLists.txt @@ -16,3 +16,4 @@ # ADD_SUBDIRECTORY(nsd-dns-sd) +ADD_SUBDIRECTORY(nsd-ssdp) diff --git a/pkgconfig/nsd-ssdp/CMakeLists.txt b/pkgconfig/nsd-ssdp/CMakeLists.txt new file mode 100644 index 0000000..583f85d --- /dev/null +++ b/pkgconfig/nsd-ssdp/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-ssdp.pc.in nsd-ssdp.pc @ONLY) + +INSTALL(FILES + ${CMAKE_BINARY_DIR}/pkgconfig/nsd-ssdp/nsd-ssdp.pc + DESTINATION + ${LIB_DIR}/pkgconfig + ) diff --git a/pkgconfig/nsd-ssdp/nsd-ssdp.pc.in b/pkgconfig/nsd-ssdp/nsd-ssdp.pc.in new file mode 100644 index 0000000..e25838f --- /dev/null +++ b/pkgconfig/nsd-ssdp/nsd-ssdp.pc.in @@ -0,0 +1,11 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=${prefix} +libdir=@LIB_DIR@ +includedir=${prefix}/include + +Name: nsd-ssdp +Description: nsd-ssdp package +Version: @VERSION@ +Requires: +Libs: -L${libdir} -lnsd-ssdp +Cflags: -I${includedir}/nsd diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a455fd8..106a88d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -22,3 +22,4 @@ INCLUDE_DIRECTORIES( ) ADD_SUBDIRECTORY(dns-sd) +ADD_SUBDIRECTORY(ssdp) diff --git a/src/ssdp/CMakeLists.txt b/src/ssdp/CMakeLists.txt new file mode 100644 index 0000000..782cfea --- /dev/null +++ b/src/ssdp/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_SSDP_PATH ${NSD_PATH}/ssdp) + +INCLUDE_DIRECTORIES( + ${LIB_SSDP_PATH} + ${NSD_PATH}/include + ) + +SET(LIB_SSDP_SOURCES + ${LIB_SSDP_PATH}/ssdp.c + ) + +ADD_DEFINITIONS("-fvisibility=default") + +ADD_LIBRARY(${TARGET_LIB_NSD_SSDP} SHARED ${LIB_SSDP_SOURCES}) + +SET_TARGET_PROPERTIES( + ${TARGET_LIB_NSD_SSDP} + PROPERTIES + SOVERSION ${MAJORVER} + VERSION ${FULLVER} + ) + +TARGET_LINK_LIBRARIES(${TARGET_LIB_NSD_SSDP} + ${NSD_DEPS_LIBRARIES} + dl + ) + +INSTALL(TARGETS ${TARGET_LIB_NSD_SSDP} DESTINATION ${LIB_DIR}) diff --git a/src/ssdp/ssdp-util.h b/src/ssdp/ssdp-util.h new file mode 100644 index 0000000..c0c3dcd --- /dev/null +++ b/src/ssdp/ssdp-util.h @@ -0,0 +1,77 @@ +/* + * 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 __ssdp_util_h__ +#define __ssdp_util_h__ + +#define USE_DLOG +#ifdef USE_DLOG +#include + +#undef LOG_TAG +#define LOG_TAG "CAPI_NETWORK_SSDP" + +#define SSDP_LOGD(format, args...) LOGD(format, ##args) +#define SSDP_LOGI(format, args...) LOGI(format, ##args) +#define SSDP_LOGW(format, args...) LOGW(format, ##args) +#define SSDP_LOGE(format, args...) LOGE(format, ##args) + +#define __SSDP_LOG_FUNC_ENTER__ LOGD("Enter") +#define __SSDP_LOG_FUNC_EXIT__ LOGD("Quit") + +#else /* USE_DLOG */ + +#define SSDP_LOGD(format, args...) +#define SSDP_LOGI(format, args...) +#define SSDP_LOGW(format, args...) +#define SSDP_LOGE(format, args...) + +#define __SSDP_LOG_FUNC_ENTER__ +#define __SSDP_LOG_FUNC_EXIT__ + +#endif /* USE_DLOG */ + +#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){\ + LOGE("%s feature is disabled", feature_name);\ + return NSD_ERROR_NOT_SUPPORTED;\ + }\ + } else {\ + LOGE("Error - Feature getting from System Info");\ + return NSD_ERROR_OPERATION_FAILED;\ + }\ + }while(0) + +#else +#define CHECK_FEATURE_SUPPORTED(feature_name) +#endif + +#define GLIST_ITER_START(arg_list, elem) \ + GList *temp = NULL; \ + temp = g_list_first(arg_list); \ + while (temp) {\ + elem = temp->data;\ + temp = g_list_next(temp); \ + +#define GLIST_ITER_END() } + +#endif diff --git a/src/ssdp/ssdp.c b/src/ssdp/ssdp.c new file mode 100644 index 0000000..17f328d --- /dev/null +++ b/src/ssdp/ssdp.c @@ -0,0 +1,994 @@ +/* +* 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. +*/ + +/***************************************************************************** + * Standard headers + *****************************************************************************/ + +#include +#include +#include + +/***************************************************************************** + * System headers + *****************************************************************************/ +#include +#include + +#include +#include + +/***************************************************************************** + * Network Service Discovery headers + *****************************************************************************/ + +#include "ssdp.h" +#include "ssdp-util.h" + +/***************************************************************************** + * Macros and Typedefs + *****************************************************************************/ + +typedef enum { + SSDP_SERVICE_STATE_NOT_REGISTERED, + SSDP_SERVICE_STATE_REGISTERED, + SSDP_SERVICE_STATE_BROWSED, + SSDP_SERVICE_STATE_FOUND, +} ssdp_state_e; + +typedef struct { + unsigned int browser_id; /* for found services */ + unsigned int service_handler; + char *target; + char *usn; + char *url; + + ssdp_state_e origin; + + unsigned int resource_id; + GSSDPResourceGroup *resource_group; + GSSDPResourceBrowser *resource_browser; + + ssdp_registered_cb registered_cb; + ssdp_found_cb found_cb; + + void *cb_user_data; +} ssdp_service_s; + +typedef struct { + ssdp_service_s *service; + unsigned int service_id; +} foreach_hash_user_data_s; + + +/***************************************************************************** + * Global Variables + *****************************************************************************/ +static __thread gboolean g_is_gssdp_init; +static __thread GSSDPClient *g_gssdp_client = NULL; + +static __thread GList *g_ssdp_local_services; +static __thread GHashTable *g_found_ssdp_services = NULL; +//static __thread GList *g_ssdp_browsers; TODO +/***************************************************************************** + * Local Functions Definition + *****************************************************************************/ + +/** + * free a local service + */ +static void __g_list_free_service(gpointer data, gpointer user_data) +{ + ssdp_service_s *service = NULL; + + service = (ssdp_service_s *)data; + if(service == NULL) + return; + /* moon + if(service->resource_group != NULL && service->resource_id != 0) + gssdp_resource_group_remove_resource(service->resource_group, service->resource_id); + + if(service->resource_browser != NULL) + g_object_unref (service->resource_browser); + */ + if(service->origin == SSDP_SERVICE_STATE_NOT_REGISTERED) + SSDP_LOGE("Free not registered service"); + else if(service->origin == SSDP_SERVICE_STATE_REGISTERED) + SSDP_LOGE("Free registered service"); + else if (service->origin == SSDP_SERVICE_STATE_BROWSED) + SSDP_LOGE("Free browsed service"); + else + SSDP_LOGE("Free found service"); + + g_free(service->target); + g_free(service->usn); + g_free(service->url); + g_free(service); +} + +/** + * free a remote service + */ +static void __g_hash_free_service(gpointer key, gpointer value, + gpointer user_data) +{ + ssdp_service_s *service = NULL; + + service = (ssdp_service_s *)value; + if(service == NULL) + return; + /* + if(service->resource_group != NULL && service->resource_id != 0) + gssdp_resource_group_remove_resource(service->resource_group, service->resource_id); + + if(service->resource_browser != NULL) + g_object_unref (service->resource_browser); + */ + if(service->origin == SSDP_SERVICE_STATE_REGISTERED) + SSDP_LOGE("Free registered service"); + else if (service->origin == SSDP_SERVICE_STATE_BROWSED) + SSDP_LOGE("Free browsed service"); + else + SSDP_LOGE("Free found service"); + + g_free(service->target); + g_free(service->usn); + g_free(service->url); + g_free(service); +} + +/** + * remove remove services found by request of a browser (browser_id is passed to by user_data) + */ +static void __g_hash_remove_related_services(gpointer key, gpointer value, + gpointer user_data) +{ + ssdp_service_s *service = NULL; + int browse_id = *((unsigned int *)user_data); + + service = (ssdp_service_s *)value; + if(service == NULL) + return; + + if(service->browser_id != browse_id) + return; + + SSDP_LOGD("Free found service"); + + g_free(service->target); + g_free(service->usn); + g_free(service->url); + g_free(service); +} + +static ssdp_service_s *__ssdp_find_local_service(GList *services, + unsigned int handler) +{ + __SSDP_LOG_FUNC_ENTER__; + ssdp_service_s *service = NULL; + GList *list; + for (list = services; list != NULL; list = list->next) { + service = list->data; + if (service && service->service_handler == handler) { + SSDP_LOGD("target [%s]", service->target); + break; + } + else { + service = NULL; + } + } + __SSDP_LOG_FUNC_EXIT__; + return service; +} + +static ssdp_service_s *__ssdp_find_local_service_with_usn(GList *services, + const char* usn) +{ + __SSDP_LOG_FUNC_ENTER__; + ssdp_service_s *service = NULL; + GList *list; + for (list = services; list != NULL; list = list->next) { + service = list->data; + if (service && strncmp(service->usn, usn, strlen(usn))) { + SSDP_LOGD("USN [%s]", service->usn); + break; + } + else { + service = NULL; + } + } + __SSDP_LOG_FUNC_EXIT__; + return service; +} + +static ssdp_service_s *__ssdp_find_local_service_with_url(GList *services, + const char* url) +{ + __SSDP_LOG_FUNC_ENTER__; + ssdp_service_s *service = NULL; + GList *list; + for (list = services; list != NULL; list = list->next) { + service = list->data; + if (service && strncmp(service->url, url, strlen(url))) { + SSDP_LOGD("URL [%s]", service->url); + break; + } + else { + service = NULL; + } + } + __SSDP_LOG_FUNC_EXIT__; + return service; +} + +static void __g_hash_find_remote_service(gpointer key, gpointer value, + gpointer user_data) +{ + ssdp_service_s *service = NULL; + foreach_hash_user_data_s *data = NULL; + + service = (ssdp_service_s *)value; + data = (foreach_hash_user_data_s *)user_data; + if(service == NULL || data == NULL) + return; + + if (service->origin != SSDP_SERVICE_STATE_FOUND) + return; + + if(service->service_handler == data->service_id) + data->service = service; + + return; +} + +static ssdp_service_s *__ssdp_find_remote_service(GHashTable *services, + unsigned int handler) +{ + foreach_hash_user_data_s user_data; + + user_data.service_id = handler; + user_data.service = NULL; + g_hash_table_foreach(g_found_ssdp_services, + (GHFunc)__g_hash_find_remote_service, &user_data); + + return user_data.service; +} + +static void +__ssdp_res_available_cb (GSSDPResourceBrowser *resource_browser, + const char *usn, GList *urls, gpointer user_data) +{ + __SSDP_LOG_FUNC_ENTER__; + ssdp_service_s *browser = NULL; + ssdp_service_s *found_service = NULL; + char *temp_url = NULL; + char *ptr = NULL; + int url_len = 0; + GList *l; + + browser = (ssdp_service_s *)user_data; + if (browser == NULL) { + SSDP_LOGE("Service not found"); + return; + } + + for (l = urls; l != NULL; l = l->next) { + SSDP_LOGD(" URL: %s", (char *)l->data); + url_len += strlen((char *)l->data); + } + + temp_url = g_try_malloc0(url_len + 1); + if (!temp_url) { + SSDP_LOGE("Failed to get memory for url"); + __SSDP_LOG_FUNC_EXIT__; + return; + } + + for (l = urls; l != NULL; l = l->next) { + ptr = temp_url; + g_strlcpy(ptr, (char*)l->data, strlen((char *)l->data) + 1); + ptr+=strlen((char *)l->data); + } + + found_service = g_hash_table_lookup(g_found_ssdp_services, usn); + if (found_service != NULL && + g_strcmp0(found_service->usn, usn) == 0) { + SSDP_LOGD("Duplicated service!"); + __SSDP_LOG_FUNC_EXIT__; + return; + } + + found_service = (ssdp_service_s *)g_try_malloc0(sizeof(ssdp_service_s)); + if (!found_service) { + SSDP_LOGE("Failed to get memory for ssdp service structure"); + __SSDP_LOG_FUNC_EXIT__; + return; + } + + SSDP_LOGD("resource available\nUSN: %s", usn); + + found_service->usn = g_strdup(usn); + found_service->url= temp_url; + found_service->service_handler = (unsigned int)found_service & 0xffffffff; + found_service->browser_id = browser->service_handler; + found_service->origin = SSDP_SERVICE_STATE_FOUND; + + SSDP_LOGD("added service [%u]", found_service->service_handler); + g_hash_table_insert(g_found_ssdp_services, + found_service->usn, found_service); + + SSDP_LOGD("Hash tbl size [%d]", g_hash_table_size(g_found_ssdp_services)); + + if (browser->found_cb) { + browser->found_cb(found_service->service_handler, + SSDP_SERVICE_STATE_AVAILABLE, browser->cb_user_data); + } + + __SSDP_LOG_FUNC_EXIT__; + return; + +} + +static void +__ssdp_res_unavailable_cb (GSSDPResourceBrowser *resource_browser, + const char *usn, GList *urls, gpointer user_data) +{ + __SSDP_LOG_FUNC_ENTER__; + ssdp_service_s *browser = NULL; + ssdp_service_s *found_service = NULL; + + browser = (ssdp_service_s *)user_data; + if (browser == NULL) { + SSDP_LOGE("Service not found"); + return; + } + + found_service = g_hash_table_lookup(g_found_ssdp_services, usn); + if (found_service == NULL) { + SSDP_LOGD("No service matched!"); + return; + } + + SSDP_LOGD("resource unavailable\n USN: %s\n", usn); + + g_hash_table_remove(g_found_ssdp_services, usn); + g_free(found_service->target); + g_free(found_service->usn); + g_free(found_service->url); + g_free(found_service); + + SSDP_LOGD("Hash tbl size [%d]", g_hash_table_size(g_found_ssdp_services)); + + if (browser->found_cb) { + browser->found_cb(found_service->service_handler, + SSDP_SERVICE_STATE_UNAVAILABLE, browser->cb_user_data); + } + + __SSDP_LOG_FUNC_EXIT__; + return; +} + +int ssdp_initialize() +{ + __SSDP_LOG_FUNC_ENTER__; + int status = SSDP_ERROR_NONE; + + CHECK_FEATURE_SUPPORTED(NETWORK_SERVICE_DISCOVERY_FEATURE); + + GError *gerror = NULL; + + if (g_is_gssdp_init) { + SSDP_LOGE("gssdp already initialized"); + return SSDP_ERROR_NONE; + } + + g_gssdp_client = gssdp_client_new (NULL, NULL, &gerror); + if (gerror) { + SSDP_LOGE("Error creating the GSSDP client: %s\n", + gerror->message); + g_error_free(gerror); + __SSDP_LOG_FUNC_EXIT__; + return SSDP_ERROR_OPERATION_FAILED; + } + + if (g_gssdp_client == NULL) { + SSDP_LOGE("failed to create client\n"); + __SSDP_LOG_FUNC_EXIT__; + return SSDP_ERROR_OPERATION_FAILED; + } + + g_found_ssdp_services = g_hash_table_new(g_str_hash, g_str_equal); + + g_is_gssdp_init = TRUE; + + __SSDP_LOG_FUNC_EXIT__; + return status; +} + +int ssdp_deinitialize() +{ + __SSDP_LOG_FUNC_ENTER__; + int status = SSDP_ERROR_NONE; + + CHECK_FEATURE_SUPPORTED(NETWORK_SERVICE_DISCOVERY_FEATURE); + + if (!g_is_gssdp_init) { + SSDP_LOGE("gssdp not initialized"); + return SSDP_ERROR_NOT_INITIALIZED; + } + + g_list_foreach(g_ssdp_local_services, (GFunc)__g_list_free_service, NULL); + g_list_free(g_ssdp_local_services); + g_ssdp_local_services = NULL; + + g_hash_table_foreach(g_found_ssdp_services, + (GHFunc)__g_hash_free_service, NULL); + g_hash_table_remove_all(g_found_ssdp_services); + + g_object_unref(g_gssdp_client); + g_gssdp_client = NULL; + g_is_gssdp_init = FALSE; + + __SSDP_LOG_FUNC_EXIT__; + return status; +} + +int ssdp_create_local_service(const char *target, ssdp_service_h *ssdp_service) +{ + __SSDP_LOG_FUNC_ENTER__; + int status = SSDP_ERROR_NONE; + ssdp_service_s *service = NULL; + + CHECK_FEATURE_SUPPORTED(NETWORK_SERVICE_DISCOVERY_FEATURE); + + if (!g_is_gssdp_init) { + SSDP_LOGE("gssdp not initialized"); + return SSDP_ERROR_NOT_INITIALIZED; + } + + if (ssdp_service == NULL) { + SSDP_LOGE("Invalid parameter"); + __SSDP_LOG_FUNC_EXIT__; + return SSDP_ERROR_INVALID_PARAMETER; + } + + service = (ssdp_service_s*)g_try_malloc0(sizeof(ssdp_service_s)); + if (!service) { + SSDP_LOGE("Failed to get memory for gssdp service structure"); + __SSDP_LOG_FUNC_EXIT__; + return SSDP_ERROR_OUT_OF_MEMORY; + } + + service->target = g_strndup(target, strlen(target)); + if (!service->target) { + SSDP_LOGE("Failed to get memory for gssdp service type"); + g_free(service); + __SSDP_LOG_FUNC_EXIT__; + return SSDP_ERROR_OUT_OF_MEMORY; + } + + *ssdp_service = (unsigned int)service & 0xFFFFFFFF; + SSDP_LOGD("Create handler for service [%u]", *ssdp_service); + service->service_handler = *ssdp_service; + service->origin = SSDP_SERVICE_STATE_NOT_REGISTERED; + g_ssdp_local_services = g_list_append(g_ssdp_local_services, service); + + __SSDP_LOG_FUNC_EXIT__; + return status; +} + +int ssdp_destroy_local_service(ssdp_service_h ssdp_service) +{ + __SSDP_LOG_FUNC_ENTER__; + int status = SSDP_ERROR_NONE; + ssdp_service_s *service = NULL; + + CHECK_FEATURE_SUPPORTED(NETWORK_SERVICE_DISCOVERY_FEATURE); + + if (ssdp_service == 0) { + SSDP_LOGE("Invalid parameter"); + return SSDP_ERROR_INVALID_PARAMETER; + } + + SSDP_LOGD("SSDP service ID [%u]", ssdp_service); + + if (!g_is_gssdp_init) { + SSDP_LOGE("gssdp not initialized"); + return SSDP_ERROR_NOT_INITIALIZED; + } + + service = __ssdp_find_local_service(g_ssdp_local_services, ssdp_service); + if (service == NULL) + return SSDP_ERROR_SERVICE_NOT_FOUND; + + if (service->resource_group != NULL) + service->resource_group = NULL; + + if (service->resource_browser != NULL) + g_object_unref(service->resource_browser); + + g_ssdp_local_services = g_list_remove(g_ssdp_local_services, service); + g_free(service->target); + g_free(service->usn); + g_free(service->url); + g_free(service); + + __SSDP_LOG_FUNC_EXIT__; + return status; +} + +int ssdp_service_set_usn(ssdp_service_h local_service, const char* usn) +{ + __SSDP_LOG_FUNC_ENTER__; + int status = SSDP_ERROR_NONE; + ssdp_service_s *service = NULL; + + CHECK_FEATURE_SUPPORTED(NETWORK_SERVICE_DISCOVERY_FEATURE); + + if (local_service == 0 || usn == NULL) { + SSDP_LOGE("Invalid parameter"); + return SSDP_ERROR_INVALID_PARAMETER; + } + SSDP_LOGD("SSDP service ID [%u]", local_service); + SSDP_LOGD("USN [%s]", usn); + + if (!g_is_gssdp_init) { + SSDP_LOGE("gssdp not initialized"); + return SSDP_ERROR_NOT_INITIALIZED; + } + + service = __ssdp_find_local_service(g_ssdp_local_services, local_service); + if (service == NULL) { + SSDP_LOGE("Service not found"); + return SSDP_ERROR_SERVICE_NOT_FOUND; + } + + if (service->origin == SSDP_SERVICE_STATE_REGISTERED) { + SSDP_LOGE("Already registered"); + return SSDP_ERROR_INVALID_PARAMETER; + } + + if (__ssdp_find_local_service_with_usn(g_ssdp_local_services, usn) != NULL) { + SSDP_LOGE("Duplicate USN"); + return SSDP_ERROR_INVALID_PARAMETER; + } + + g_free(service->usn); + service->usn = g_strndup(usn, strlen(usn)); + + + __SSDP_LOG_FUNC_EXIT__; + return status; +} + +int ssdp_service_set_url(ssdp_service_h local_service, const char *url) +{ + __SSDP_LOG_FUNC_ENTER__; + int status = SSDP_ERROR_NONE; + ssdp_service_s *service = NULL; + + CHECK_FEATURE_SUPPORTED(NETWORK_SERVICE_DISCOVERY_FEATURE); + + if (local_service == 0 || url == NULL) { + SSDP_LOGE("Invalid parameter"); + return SSDP_ERROR_INVALID_PARAMETER; + } + SSDP_LOGD("SSDP service ID [%u]", local_service); + SSDP_LOGD("Location [%s]", url); + + if (!g_is_gssdp_init) { + SSDP_LOGE("gssdp not initialized"); + return SSDP_ERROR_NOT_INITIALIZED; + } + + service = __ssdp_find_local_service(g_ssdp_local_services, local_service); + if (service == NULL) { + SSDP_LOGE("Service not found"); + return SSDP_ERROR_SERVICE_NOT_FOUND; + } + + if (service->origin == SSDP_SERVICE_STATE_REGISTERED) { + SSDP_LOGE("Already registered"); + return SSDP_ERROR_INVALID_PARAMETER; + } + + if (__ssdp_find_local_service_with_url(g_ssdp_local_services, url) != NULL) { + SSDP_LOGE("Duplicate URL"); + return SSDP_ERROR_INVALID_PARAMETER; + } + + g_free(service->url); + service->url = g_strndup(url, strlen(url)); + + __SSDP_LOG_FUNC_EXIT__; + return status; +} + +int ssdp_service_get_target(ssdp_service_h ssdp_service, char **target) +{ + __SSDP_LOG_FUNC_ENTER__; + int status = SSDP_ERROR_NONE; + ssdp_service_s *service = NULL; + + CHECK_FEATURE_SUPPORTED(NETWORK_SERVICE_DISCOVERY_FEATURE); + + if (ssdp_service == 0 || !target) { + SSDP_LOGE("Invalid parameter"); + return SSDP_ERROR_INVALID_PARAMETER; + } + SSDP_LOGD("SSDP service ID [%u]", ssdp_service); + + if (!g_is_gssdp_init) { + SSDP_LOGE("gssdp not initialized"); + return SSDP_ERROR_NOT_INITIALIZED; + } + + service = __ssdp_find_local_service(g_ssdp_local_services, ssdp_service); + if (service == NULL) + service = __ssdp_find_remote_service(g_found_ssdp_services, + ssdp_service); + + if (service == NULL || service->target == NULL) { + SSDP_LOGE("Service not found"); + return SSDP_ERROR_SERVICE_NOT_FOUND; + } + + *target = g_strndup(service->target, strlen(service->target)); + if (!target) { + SSDP_LOGE("Failed to get memory for gssdp service type"); + g_free(target); + __SSDP_LOG_FUNC_EXIT__; + return SSDP_ERROR_OUT_OF_MEMORY; + } + + __SSDP_LOG_FUNC_EXIT__; + return status; +} + +int ssdp_service_get_usn(ssdp_service_h ssdp_service, char **usn) +{ + __SSDP_LOG_FUNC_ENTER__; + int status = SSDP_ERROR_NONE; + ssdp_service_s *service = NULL; + + CHECK_FEATURE_SUPPORTED(NETWORK_SERVICE_DISCOVERY_FEATURE); + + if (ssdp_service == 0 || !usn) { + SSDP_LOGE("Invalid parameter"); + return SSDP_ERROR_INVALID_PARAMETER; + } + SSDP_LOGD("SSDP service ID [%u]", ssdp_service); + + if (!g_is_gssdp_init) { + SSDP_LOGE("gssdp not initialized"); + return SSDP_ERROR_NOT_INITIALIZED; + } + + service = __ssdp_find_local_service(g_ssdp_local_services, ssdp_service); + if (service == NULL) + service = __ssdp_find_remote_service(g_found_ssdp_services, + ssdp_service); + + if (service == NULL || service->usn == NULL) { + SSDP_LOGE("Service not found"); + return SSDP_ERROR_SERVICE_NOT_FOUND; + } + + *usn = g_strndup(service->usn, strlen(service->usn)); + if (!usn) { + SSDP_LOGE("Failed to get memory for gssdp service type"); + g_free(usn); + __SSDP_LOG_FUNC_EXIT__; + return SSDP_ERROR_OUT_OF_MEMORY; + } + + __SSDP_LOG_FUNC_EXIT__; + return status; +} + +int ssdp_service_get_url(ssdp_service_h ssdp_service, char **url) +{ + __SSDP_LOG_FUNC_ENTER__; + int status = SSDP_ERROR_NONE; + ssdp_service_s *service = NULL; + + CHECK_FEATURE_SUPPORTED(NETWORK_SERVICE_DISCOVERY_FEATURE); + + if (ssdp_service == 0 || !url) { + SSDP_LOGE("Invalid parameter"); + return SSDP_ERROR_INVALID_PARAMETER; + } + SSDP_LOGD("SSDP service ID [%u]", ssdp_service); + + if (!g_is_gssdp_init) { + SSDP_LOGE("gssdp not initialized"); + return SSDP_ERROR_NOT_INITIALIZED; + } + + service = __ssdp_find_local_service(g_ssdp_local_services, ssdp_service); + if (service == NULL) + service = __ssdp_find_remote_service(g_found_ssdp_services, + ssdp_service); + + if (service == NULL || service->url == NULL) { + SSDP_LOGE("Service not found"); + return SSDP_ERROR_SERVICE_NOT_FOUND; + } + + *url = g_strndup(service->url, strlen(service->url)); + if (!url) { + SSDP_LOGE("Failed to get memory for gssdp service type"); + g_free(url); + __SSDP_LOG_FUNC_EXIT__; + return SSDP_ERROR_OUT_OF_MEMORY; + } + + __SSDP_LOG_FUNC_EXIT__; + return status; +} + +int ssdp_register_local_service(ssdp_service_h local_service, + ssdp_registered_cb cb, void *user_data) +{ + __SSDP_LOG_FUNC_ENTER__; + int status = SSDP_ERROR_NONE; + ssdp_service_s *service = NULL; + + CHECK_FEATURE_SUPPORTED(NETWORK_SERVICE_DISCOVERY_FEATURE); + + if (local_service == 0) { + SSDP_LOGE("Invalid parameter"); + return SSDP_ERROR_INVALID_PARAMETER; + } + SSDP_LOGD("SSDP service ID [%u]", local_service); + + if (!g_is_gssdp_init) { + SSDP_LOGE("gssdp not initialized"); + return SSDP_ERROR_NOT_INITIALIZED; + } + + service = __ssdp_find_local_service(g_ssdp_local_services, local_service); + if (service == NULL) { + SSDP_LOGE("Service not found"); + return SSDP_ERROR_SERVICE_NOT_FOUND; + } + + if (service->origin == SSDP_SERVICE_STATE_REGISTERED) { + SSDP_LOGE("Already registered"); + return SSDP_ERROR_INVALID_PARAMETER; + } + + if (service->resource_group != NULL) { + SSDP_LOGE("Resource group is not NULL\ninit first"); + gssdp_resource_group_remove_resource(service->resource_group, + service->resource_id); + } + + if (g_gssdp_client == NULL) { + SSDP_LOGE("GSSDPClient is NULL. Init first"); + return SSDP_ERROR_INVALID_PARAMETER; + } + + service->resource_group = gssdp_resource_group_new (g_gssdp_client); + if (service->resource_group == NULL) { + SSDP_LOGE("Resource group is NULL"); + return SSDP_ERROR_OPERATION_FAILED; + } + + service->resource_id = gssdp_resource_group_add_resource_simple( + service->resource_group, + service->target, + service->usn, + service->url); + + service->origin = SSDP_SERVICE_STATE_REGISTERED; + service->registered_cb = cb; + service->cb_user_data = user_data; + + gssdp_resource_group_set_available (service->resource_group, TRUE); + SSDP_LOGD("Now service is available [%u]", local_service); + + SSDP_LOGD("Resource group id is [%d]\n", service->resource_id); + if (service->resource_id == 0) + status = SSDP_ERROR_OPERATION_FAILED; + + __SSDP_LOG_FUNC_EXIT__; + return status; +} + + +int ssdp_deregister_local_service(ssdp_service_h local_service) +{ + __SSDP_LOG_FUNC_ENTER__; + int status = SSDP_ERROR_NONE; + ssdp_service_s *service = NULL; + + CHECK_FEATURE_SUPPORTED(NETWORK_SERVICE_DISCOVERY_FEATURE); + + if (local_service == 0) { + SSDP_LOGE("Invalid parameter"); + return SSDP_ERROR_INVALID_PARAMETER; + } + SSDP_LOGD("SSDP service ID [%u]", local_service); + + if (!g_is_gssdp_init) { + SSDP_LOGE("gssdp not initialized"); + return SSDP_ERROR_NOT_INITIALIZED; + } + + service = __ssdp_find_local_service(g_ssdp_local_services, local_service); + if (service == NULL) { + SSDP_LOGE("Service not found"); + return SSDP_ERROR_SERVICE_NOT_FOUND; + } + + if (service->resource_group != NULL && service->resource_id != 0) { + gssdp_resource_group_remove_resource(service->resource_group, + service->resource_id); + service->resource_group = NULL; + service->resource_id = 0; + } + + service->origin = SSDP_SERVICE_STATE_NOT_REGISTERED; + service->registered_cb = NULL; + service->cb_user_data = NULL; + + gssdp_resource_group_set_available (service->resource_group, FALSE); + SSDP_LOGD("Now service is unavailable [%u]", local_service); + + __SSDP_LOG_FUNC_EXIT__; + return status; +} + +int ssdp_start_browsing_service(const char* target, ssdp_browser_h* ssdp_browser, + ssdp_found_cb found_cb, void *user_data) +{ + __SSDP_LOG_FUNC_ENTER__; + int status = SSDP_ERROR_NONE; + ssdp_service_s *browser = NULL; + + CHECK_FEATURE_SUPPORTED(NETWORK_SERVICE_DISCOVERY_FEATURE); + + if (!g_is_gssdp_init) { + SSDP_LOGE("gssdp not initialized"); + __SSDP_LOG_FUNC_EXIT__; + return SSDP_ERROR_NOT_INITIALIZED; + } + + if (ssdp_browser == NULL) { + SSDP_LOGE("Invalid parameter"); + __SSDP_LOG_FUNC_EXIT__; + return SSDP_ERROR_INVALID_PARAMETER; + } + + if (g_gssdp_client == NULL) { + SSDP_LOGE("GSSDPClient is NULL. Init first"); + __SSDP_LOG_FUNC_EXIT__; + return SSDP_ERROR_INVALID_PARAMETER; + } + +GLIST_ITER_START(g_ssdp_local_services, browser) + if (strncmp(target, browser->target, strlen(target)) && + browser->origin == SSDP_SERVICE_STATE_BROWSED) { + SSDP_LOGD("Browsing request is already registered"); + } + else { + browser = NULL; + } +GLIST_ITER_END() + + if (browser == NULL) { + browser = (ssdp_service_s*)g_try_malloc0(sizeof(ssdp_service_s)); + if (!browser) { + SSDP_LOGE("Failed to get memory for gssdp service structure"); + __SSDP_LOG_FUNC_EXIT__; + return SSDP_ERROR_OUT_OF_MEMORY; + } + + browser->target = g_strndup(target, strlen(target)); + if (!browser->target) { + SSDP_LOGE("Failed to get memory for gssdp service type"); + g_free(browser); + __SSDP_LOG_FUNC_EXIT__; + return SSDP_ERROR_OUT_OF_MEMORY; + } + + /* Create browser handle */ + *ssdp_browser = (unsigned int)browser & 0xFFFFFFFF; + SSDP_LOGD("Create handler for browser [%u]", *ssdp_browser); + browser->service_handler = *ssdp_browser; + + /* Create the service browser */ + browser->resource_browser = gssdp_resource_browser_new( + g_gssdp_client, + browser->target); + if (browser->resource_browser == NULL) { + SSDP_LOGE("Failed to create service browser\n"); + __SSDP_LOG_FUNC_EXIT__; + return SSDP_ERROR_OPERATION_FAILED; + } + + /* Connect signals */ + g_signal_connect(browser->resource_browser, "resource-available", + G_CALLBACK(__ssdp_res_available_cb), browser); + + g_signal_connect(browser->resource_browser, "resource-unavailable", + G_CALLBACK(__ssdp_res_unavailable_cb), browser); + + gssdp_resource_browser_set_active(browser->resource_browser, TRUE); + + /* Set properties */ + browser->origin = SSDP_SERVICE_STATE_BROWSED; + g_ssdp_local_services = g_list_append(g_ssdp_local_services, browser); + } + else { + if (!(gssdp_resource_browser_rescan(browser->resource_browser))) + { + SSDP_LOGE("Failed to request rescan"); + __SSDP_LOG_FUNC_EXIT__; + return SSDP_ERROR_OPERATION_FAILED; + } + } + + browser->found_cb = found_cb; + browser->cb_user_data = user_data; + + __SSDP_LOG_FUNC_EXIT__; + return status; +} + +int ssdp_stop_browsing_service(ssdp_browser_h ssdp_browser) +{ + __SSDP_LOG_FUNC_ENTER__; + int status = SSDP_ERROR_NONE; + ssdp_service_s *browser = NULL; + + CHECK_FEATURE_SUPPORTED(NETWORK_SERVICE_DISCOVERY_FEATURE); + + if (ssdp_browser == 0) { + SSDP_LOGE("Invalid parameter"); + return SSDP_ERROR_INVALID_PARAMETER; + } + + SSDP_LOGD("SSDP browser ID [%u]", ssdp_browser); + browser = __ssdp_find_local_service(g_ssdp_local_services, ssdp_browser); + if (browser == NULL) { + SSDP_LOGE("Service not found"); + __SSDP_LOG_FUNC_EXIT__; + return SSDP_ERROR_SERVICE_NOT_FOUND; + } + + gssdp_resource_browser_set_active (browser->resource_browser, FALSE); + + g_object_unref (browser->resource_browser); + browser->found_cb = NULL; + browser->cb_user_data = NULL; + + g_ssdp_local_services = g_list_remove(g_ssdp_local_services, browser); + + g_hash_table_foreach(g_found_ssdp_services, + (GHFunc)__g_hash_remove_related_services, + (gpointer)browser->service_handler); + + g_free(browser->target); + g_free(browser); + + __SSDP_LOG_FUNC_EXIT__; + return status; +} + + + diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 040bc0f..b258641 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -16,7 +16,8 @@ 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}) + TARGET_LINK_LIBRARIES(${src_name} ${TARGET_LIB_NSD_DNS_SD} ${TARGET_LIB_NSD_SSDP} ${TARGET_NSD_TESTS_LDFLAGS}) ENDFOREACH() INSTALL(TARGETS dns-sd-test RUNTIME DESTINATION ${BIN_DIR}) +INSTALL(TARGETS ssdp-test RUNTIME DESTINATION ${BIN_DIR}) diff --git a/test/ssdp-browse-test.c b/test/ssdp-browse-test.c new file mode 100644 index 0000000..1b88165 --- /dev/null +++ b/test/ssdp-browse-test.c @@ -0,0 +1,65 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#define RESET_COLOR "\e[m" +#define MAKE_RED "\e[31m" +#define MAKE_GREEN "\e[32m" + +#define MENU_PRINT(str) printf("%s\n", str) + +#define __FUNC_ENTER__ printf("\n%s() entering...\n", __func__) +#define __FUNC_EXIT__ printf("\n%s() leaving...\n", __func__) + +void test_found_cb(ssdp_service_state_e state, ssdp_service_h ssdp_service, void *user_data) +{ + __FUNC_ENTER__; + char *usn; + char *url; + printf("service handler: %u\n", ssdp_service); + ssdp_service_get_usn(ssdp_service, &usn); + ssdp_service_get_url(ssdp_service, &url); + printf("state: %s\n", state==SSDP_SERVICE_STATE_AVAILABLE?"AVAILABLE":"UNAVAILABE"); + printf("usn: %s\n", usn); + printf("url: %s\n", url); + __FUNC_EXIT__; +} + +int main(int argc, char *argv[]) +{ + GMainLoop *main_loop = NULL; + int ret = -1; + ssdp_browser_h browser_id; + char *target = "upnp:rootdevice"; + + /* Initialize required subsystems */ +#if !GLIB_CHECK_VERSION(2,35,0) + g_type_init(); +#endif + + if (ssdp_initialize() == 0) { + printf(MAKE_GREEN"Initialized"RESET_COLOR"\n"); + } + if (ssdp_start_browsing_service(target, &browser_id, &test_found_cb, NULL) == 0) { + printf(MAKE_GREEN"Start browsing"RESET_COLOR"\n"); + } + + /* Crate the GLIB main loop */ + main_loop = g_main_loop_new(NULL, FALSE); + + /* Run the main loop */ + g_main_loop_run (main_loop); + + g_main_loop_unref(main_loop); + + return ret; +} diff --git a/test/ssdp-register-test.c b/test/ssdp-register-test.c new file mode 100644 index 0000000..1699e7e --- /dev/null +++ b/test/ssdp-register-test.c @@ -0,0 +1,72 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#define RESET_COLOR "\e[m" +#define MAKE_RED "\e[31m" +#define MAKE_GREEN "\e[32m" + +#define MENU_PRINT(str) printf("%s\n", str) + +#define __FUNC_ENTER__ printf("\n%s() entering...\n", __func__) +#define __FUNC_EXIT__ printf("\n%s() leaving...\n", __func__) + + +void test_registered_cb(ssdp_error_e result, ssdp_service_h ssdp_service, void *user_data) +{ + __FUNC_ENTER__; + printf("service handler: %u\n", ssdp_service); + printf("result: %d\n", result); + __FUNC_EXIT__; +} + +int main(int argc, char *argv[]) +{ + GMainLoop *main_loop = NULL; + int ret = -1; + ssdp_service_h serv_id; + char *target = "upnp:rootdevice"; + char *usn = "uuid:1234abce-12ab"; + char *url = "localhost"; + + + /* Initialize required subsystems */ +#if !GLIB_CHECK_VERSION(2,35,0) + g_type_init(); +#endif + + if (ssdp_initialize() == 0) { + printf(MAKE_GREEN"Initialized"RESET_COLOR"\n"); + } + if (ssdp_create_local_service(target, &serv_id) == 0) { + printf(MAKE_GREEN"Create service. Type: %s, handle: %u "RESET_COLOR"\n", target, serv_id); + } + if (ssdp_service_set_usn(serv_id, usn) == 0) { + printf(MAKE_GREEN"Set USN %s"RESET_COLOR"\n", usn); + } + if (ssdp_service_set_url(serv_id, url) == 0) { + printf(MAKE_GREEN"Set URL %s"RESET_COLOR"\n", url); + } + if (ssdp_register_local_service(serv_id, &test_registered_cb, NULL) == 0) { + printf(MAKE_GREEN"Start registering"RESET_COLOR"\n"); + } + + /* Crate the GLIB main loop */ + main_loop = g_main_loop_new(NULL, FALSE); + + /* Run the main loop */ + g_main_loop_run (main_loop); + + g_main_loop_unref(main_loop); + + return ret; +} diff --git a/test/ssdp-test.c b/test/ssdp-test.c new file mode 100644 index 0000000..bc863a3 --- /dev/null +++ b/test/ssdp-test.c @@ -0,0 +1,523 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#define RESET_COLOR "\e[m" +#define MAKE_RED "\e[31m" +#define MAKE_GREEN "\e[32m" + +#define MENU_PRINT(str) printf("%s\n", str) + +#define __FUNC_ENTER__ printf("\n%s() entering...\n", __func__) +#define __FUNC_EXIT__ printf("\n%s() leaving...\n", __func__) + +/* +void __ssdp_available_cb (ssdp_service_state_e state, + const char *usn, const char *urls, void *user_data) +{ + printf(MAKE_GREEN"cb %s "RESET_COLOR"\n", __func__ ); + if(state == SSDP_SERIVCE_AVAILABLE) { + printf("usn : [%s]\n", usn); + printf("url : [%s]\n", urls); + } + else if(state == SSDP_SERIVCE_UNAVAILABLE) { + printf("service unavailable\n"); + } +} + +void __foreach_ssdp_found_cb (const char *target, + const char *usn, const char *urls, void *user_data) +{ + printf(MAKE_GREEN"\ncb %s "RESET_COLOR"\n", __func__ ); + + if(target) + printf("target [%s]\n", target); + if(usn) + printf("usn [%s]\n", usn); + if(urls) + printf("urls [%s]\n", urls); + + printf(MAKE_GREEN"Success %s "RESET_COLOR"\n", __func__ ); + __FUNC_EXIT__; + return; +} +*/ + +int test_ssdp_initialize() +{ + __FUNC_ENTER__; + int rv = 0; + + rv = ssdp_initialize(); + if(rv == 0) { + printf(MAKE_GREEN"Success %s "RESET_COLOR"\n", __func__ ); + __FUNC_EXIT__; + return 1; + } + + printf(MAKE_RED"FAILED %s"RESET_COLOR"\n", __func__); + __FUNC_EXIT__; + return -1; +} + +int test_ssdp_deinitialize() +{ + __FUNC_ENTER__; + int rv = 0; + + rv = ssdp_deinitialize(); + if(rv == 0) { + printf(MAKE_GREEN"Success %s "RESET_COLOR"\n", __func__ ); + __FUNC_EXIT__; + return 1; + } + + printf(MAKE_RED"FAILED %s"RESET_COLOR"\n", __func__); + __FUNC_EXIT__; + return -1; +} + +int test_ssdp_create_service() +{ + __FUNC_ENTER__; + int rv = 0; + char *target = NULL; + ssdp_service_h serv_id; + + printf("\nEnter target: (Example : upnp:rootdevice)"); + if(scanf("%ms", &target) < 1) + return -1; + + + rv = ssdp_create_local_service(target, &serv_id); + g_free(target); + printf("service handler %u\n", serv_id); + + if(rv == 0) { + printf(MAKE_GREEN"Success %s "RESET_COLOR"\n", __func__ ); + return 1; + } + + printf(MAKE_RED"FAILED %s"RESET_COLOR" Error: %d\n", __func__, rv); + __FUNC_EXIT__; + return -1; +} + +int test_ssdp_destroy_service() +{ + __FUNC_ENTER__; + int rv = 0; + ssdp_service_h serv_id = 0; + + printf("\nEnter service id: "); + if(scanf("%u", &serv_id) < 1) + return -1; + + rv = ssdp_destroy_local_service(serv_id); + if(rv == 0) { + printf(MAKE_GREEN"Success %s "RESET_COLOR"\n", __func__ ); + __FUNC_EXIT__; + return 1; + } + + printf(MAKE_RED"FAILED %s"RESET_COLOR"\n", __func__); + __FUNC_EXIT__; + return -1; +} + +int test_ssdp_set_usn() +{ + __FUNC_ENTER__; + int rv = 0; + char *usn = NULL; + ssdp_service_h serv_id = 0; + + printf("\nEnter service id: "); + if(scanf("%u", &serv_id) < 1) + return -1; + + printf("\nEnter usn: (Example : uuid:1234abcd-12ab-12ab-12ab-1234567abc12::upnp:rootdevice)"); + if(scanf("%ms", &usn) < 1) + return -1; + + rv = ssdp_service_set_usn(serv_id, usn); + g_free(usn); + if(rv == 0) { + printf(MAKE_GREEN"Success %s "RESET_COLOR"\n", __func__ ); + __FUNC_EXIT__; + return 1; + } + + printf(MAKE_RED"FAILED %s"RESET_COLOR" Error: %d\n", __func__, rv); + __FUNC_EXIT__; + return -1; +} + +int test_ssdp_set_url() +{ + __FUNC_ENTER__; + int rv = 0; + char *url = NULL; + ssdp_service_h serv_id = 0; + + printf("\nEnter service id: "); + if(scanf("%u", &serv_id) < 1) + return -1; + + printf("\nEnter url: (Example : http://192.168.0.110/)"); + if(scanf("%ms", &url) < 1) + return -1; + + rv = ssdp_service_set_url(serv_id, url); + g_free(url); + if(rv == 0) { + printf(MAKE_GREEN"Success %s "RESET_COLOR"\n", __func__ ); + __FUNC_EXIT__; + return 1; + } + + printf(MAKE_RED"FAILED %s"RESET_COLOR"\n", __func__); + __FUNC_EXIT__; + return -1; +} + +int test_ssdp_get_target() +{ + __FUNC_ENTER__; + int rv = 0; + char *target = NULL; + ssdp_service_h serv_id = 0; + + printf("\nEnter service id: "); + if(scanf("%u", &serv_id) < 1) + return -1; + + rv = ssdp_service_get_target(serv_id, &target); + if(rv == 0) { + printf("target [%s]\n", target); + g_free(target); + printf(MAKE_GREEN"Success %s "RESET_COLOR"\n", __func__ ); + __FUNC_EXIT__; + return 1; + } + + printf(MAKE_RED"FAILED %s"RESET_COLOR"\n", __func__); + __FUNC_EXIT__; + return -1; +} + +int test_ssdp_get_usn() +{ + __FUNC_ENTER__; + int rv = 0; + char *usn = NULL; + ssdp_service_h serv_id = 0; + + printf("\nEnter service id: "); + if(scanf("%u", &serv_id) < 1) + return -1; + + rv = ssdp_service_get_usn(serv_id, &usn); + if(rv == 0) { + printf("usn [%s]\n", usn); + g_free(usn); + printf(MAKE_GREEN"Success %s "RESET_COLOR"\n", __func__ ); + return 1; + } + + printf(MAKE_RED"FAILED %s"RESET_COLOR"\n", __func__); + return -1; +} + +int test_ssdp_get_url() +{ + __FUNC_ENTER__; + int rv = 0; + char *url = NULL; + ssdp_service_h serv_id = 0; + + printf("\nEnter service id: "); + if(scanf("%u", &serv_id) < 1) + return -1; + + rv = ssdp_service_get_url(serv_id, &url); + if(rv == 0) { + printf("url [%s]\n", url); + g_free(url); + printf(MAKE_GREEN"Success %s "RESET_COLOR"\n", __func__ ); + __FUNC_EXIT__; + return 1; + } + + printf(MAKE_RED"FAILED %s"RESET_COLOR"\n", __func__); + __FUNC_EXIT__; + return -1; +} + +void test_registered_cb(ssdp_error_e result, ssdp_service_h ssdp_service, void *user_data) +{ + __FUNC_ENTER__; + printf("service handler: %u\n", ssdp_service); + printf("result: %d\n", result); + __FUNC_EXIT__; +} + +void test_found_cb(ssdp_service_state_e state, ssdp_service_h ssdp_service, void *user_data) +{ + __FUNC_ENTER__; + char *usn; + char *url; + printf("service handler: %u\n", ssdp_service); + ssdp_service_get_usn(ssdp_service, &usn); + ssdp_service_get_url(ssdp_service, &url); + printf("state: %s\n", state==SSDP_SERVICE_STATE_AVAILABLE?"AVAILABLE":"UNAVAILABE"); + printf("usn: %s\n", usn); + printf("url: %s\n", url); + __FUNC_EXIT__; +} + +int test_ssdp_register_service() +{ + __FUNC_ENTER__; + int rv = 0; + ssdp_service_h serv_id = 0; + + printf("\nEnter service id: "); + if(scanf("%u", &serv_id) < 1) + return -1; + + rv = ssdp_register_local_service(serv_id, &test_registered_cb, NULL); + if(rv == 0) { + printf(MAKE_GREEN"Success %s "RESET_COLOR"\n", __func__ ); + __FUNC_EXIT__; + return 1; + } + + printf(MAKE_RED"FAILED %s"RESET_COLOR"\n", __func__); + __FUNC_EXIT__; + return -1; +} + +int test_ssdp_deregister_service() +{ + __FUNC_ENTER__; + int rv = 0; + ssdp_service_h serv_id = 0; + + printf("\nEnter service id: "); + if(scanf("%u", &serv_id) < 1) + return -1; + + rv = ssdp_deregister_local_service(serv_id); + if(rv == 0) { + printf(MAKE_GREEN"Success %s "RESET_COLOR"\n", __func__ ); + __FUNC_EXIT__; + return 1; + } + + printf(MAKE_RED"FAILED %s"RESET_COLOR"\n", __func__); + __FUNC_EXIT__; + return -1; +} + +int test_ssdp_service_browse() +{ + __FUNC_ENTER__; + int rv = 0; + ssdp_browser_h browser_id = 0; + char *target = NULL; + + printf("\nEnter target: (Example : upnp:rootdevice)"); + if(scanf("%ms", &target) < 1) + return -1; + + rv = ssdp_start_browsing_service(target, &browser_id, &test_found_cb, NULL); + g_free(target); + if(rv == 0) { + printf(MAKE_GREEN"Success %s "RESET_COLOR"\n", __func__ ); + __FUNC_EXIT__; + return 1; + } + + printf(MAKE_RED"FAILED %s"RESET_COLOR"\n", __func__); + __FUNC_EXIT__; + return -1; +} + +int test_ssdp_service_stop_browse() +{ + __FUNC_ENTER__; + int rv = 0; + ssdp_browser_h browser_id = 0; + + printf("\nEnter browser id: "); + if(scanf("%u", &browser_id) < 1) + return -1; + + rv = ssdp_stop_browsing_service(browser_id); + if(rv == 0) { + printf(MAKE_GREEN"Success %s "RESET_COLOR"\n", __func__ ); + __FUNC_EXIT__; + return 1; + } + + printf(MAKE_RED"FAILED %s"RESET_COLOR"\n", __func__); + __FUNC_EXIT__; + return -1; +} + +int test_ssdp_foreach_found() +{ + /* + __FUNC_ENTER__; + int rv = 0; + ssdp_service_h serv_id = 0; + + printf("\nEnter service id: "); + if(scanf("%u", &serv_id) < 1) + return -1; + + rv = ssdp_service_foreach_found(serv_id, __foreach_ssdp_found_cb, NULL); + if(rv == 0) { + printf(MAKE_GREEN"Success %s "RESET_COLOR"\n", __func__ ); + __FUNC_EXIT__; + return 1; + } + + printf(MAKE_RED"FAILED %s"RESET_COLOR"\n", __func__); + __FUNC_EXIT__; + */ + return -1; +} + +static void MenuScreen() +{ + MENU_PRINT("___________________________________"); + MENU_PRINT("|__________MENU-SCREEN ___________|"); + MENU_PRINT("| 0 - EXIT |"); + MENU_PRINT("| 1 - Initialize SSDP |"); + MENU_PRINT("| 2 - deinitialize SSDP |"); + MENU_PRINT("| 3 - Create SSDP Service |"); + MENU_PRINT("| 4 - Destroy SSDP Service |"); + MENU_PRINT("| 5 - Set SSDP USN |"); + MENU_PRINT("| 6 - Set SSDP Location |"); + MENU_PRINT("| 7 - Get SSDP Target |"); + MENU_PRINT("| 8 - Get SSDP USN |"); + MENU_PRINT("| 9 - Get SSDP Location |"); + MENU_PRINT("| a - Register SSDP Service |"); + MENU_PRINT("| b - Deregister SSDP Service |"); + MENU_PRINT("| c - Browse SSDP Service |"); + MENU_PRINT("| d - Stop Browsing SSDP |"); + MENU_PRINT("|_________________________________|"); +} + + +int test_thread() +{ + int rv; + char a[10]; + + printf("Event received from stdin\n"); + + rv = read(0, a, 10); + + if (rv <= 0 || a[0] == '0') + exit(1); + + if (a[0] == '\n' || a[0] == '\r') { + printf("\n\n SSDP CAPI Test App\n\n"); + printf("Options..\n"); + MenuScreen(); + printf("Press ENTER to show options menu.......\n"); + } + + switch (a[0]) { + case '1': + rv = test_ssdp_initialize(); + break; + case '2': + rv = test_ssdp_deinitialize(); + break; + case '3': + rv = test_ssdp_create_service(); + break; + case '4': + rv = test_ssdp_destroy_service(); + break; + case '5': + rv = test_ssdp_set_usn(); + break; + case '6': + rv = test_ssdp_set_url(); + break; + case '7': + rv = test_ssdp_get_target(); + break; + case '8': + rv = test_ssdp_get_usn(); + break; + case '9': + rv = test_ssdp_get_url(); + break; + case 'a': + rv = test_ssdp_register_service(); + break; + case 'b': + rv = test_ssdp_deregister_service(); + break; + case 'c': + rv = test_ssdp_service_browse(); + break; + case 'd': + rv = test_ssdp_service_stop_browse(); + break; + default: + break; + } + + if (rv == 1) + printf("\nOperation Succeeded!\n"); + else + printf("\nOperation Failed!\n"); + + return TRUE; +} + +/* test thread */ + +int main(int argc, char *argv[]) +{ + GMainLoop *main_loop = NULL; + int ret = -1; + + /* Initialize required subsystems */ +#if !GLIB_CHECK_VERSION(2,35,0) + g_type_init(); +#endif + + /* test thread */ + + 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, NULL); + + printf("Test Thread Created...\n"); + + /* Crate the GLIB main loop */ + main_loop = g_main_loop_new(NULL, FALSE); + + /* Run the main loop */ + g_main_loop_run (main_loop); + + g_main_loop_unref(main_loop); + + return ret; +} -- 2.7.4