Add CAPI for ssdp 80/59480/1 accepted/tizen/ivi/20160218.084201 accepted/tizen/mobile/20160218.060059 accepted/tizen/tv/20160218.060122 accepted/tizen/wearable/20160218.060145 submit/tizen/20160218.041451
authorYu Jiung <jiung.yu@samsung.com>
Tue, 16 Feb 2016 02:57:55 +0000 (11:57 +0900)
committerYu Jiung <jiung.yu@samsung.com>
Tue, 16 Feb 2016 02:57:55 +0000 (11:57 +0900)
Change-Id: Icef10b30f3e36b16f921489e8ab89a56b74cee1b

17 files changed:
CMakeLists.txt
doc/nsd_doc.h [new file with mode: 0644]
include/CMakeLists.txt
include/ssdp.h [new file with mode: 0644]
packaging/capi-network-nsd.spec
packaging/libnsd-ssdp.manifest [new file with mode: 0644]
pkgconfig/CMakeLists.txt
pkgconfig/nsd-ssdp/CMakeLists.txt [new file with mode: 0644]
pkgconfig/nsd-ssdp/nsd-ssdp.pc.in [new file with mode: 0644]
src/CMakeLists.txt
src/ssdp/CMakeLists.txt [new file with mode: 0644]
src/ssdp/ssdp-util.h [new file with mode: 0644]
src/ssdp/ssdp.c [new file with mode: 0644]
test/CMakeLists.txt
test/ssdp-browse-test.c [new file with mode: 0644]
test/ssdp-register-test.c [new file with mode: 0644]
test/ssdp-test.c [new file with mode: 0644]

index af3f383..fb5b63e 100644 (file)
@@ -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 (file)
index 0000000..ff92501
--- /dev/null
@@ -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 <ssdp.h>
+ *
+ * @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 <a href="https://developer.tizen.org/development/getting-started/native-application/understanding-tizen-programming/application-filtering"><b>Feature List</b>.</a>
+ *
+ */
+
+/**
+ * @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 <ssdp.h>
+ *
+ * @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 <a href="https://developer.tizen.org/development/getting-started/native-application/understanding-tizen-programming/application-filtering"><b>Feature List</b>.</a>
+ *
+ */
index 9731d49..a178fd1 100644 (file)
@@ -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 (file)
index 0000000..f6bcd26
--- /dev/null
@@ -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 <tizen.h>
+
+#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__ */
index 74179b1..884793a 100644 (file)
@@ -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 (file)
index 0000000..50eefc9
--- /dev/null
@@ -0,0 +1,5 @@
+<manifest>
+       <request>
+               <domain name="_" />
+       </request>
+</manifest>
\ No newline at end of file
index 31347e3..daae87b 100644 (file)
@@ -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 (file)
index 0000000..583f85d
--- /dev/null
@@ -0,0 +1,24 @@
+# Copyright (c) 2014-2015 Samsung Electronics Co., Ltd All Rights Reserved
+#
+#    Licensed under the Apache License, Version 2.0 (the "License");
+#    you may not use this file except in compliance with the License.
+#    You may obtain a copy of the License at
+#
+#        http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+#
+# @file        CMakeLists.txt
+#
+
+CONFIGURE_FILE(nsd-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 (file)
index 0000000..e25838f
--- /dev/null
@@ -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
index a455fd8..106a88d 100644 (file)
@@ -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 (file)
index 0000000..782cfea
--- /dev/null
@@ -0,0 +1,45 @@
+# Copyright (c) 2014-2015 Samsung Electronics Co., Ltd All Rights Reserved
+#
+#    Licensed under the Apache License, Version 2.0 (the "License");
+#    you may not use this file except in compliance with the License.
+#    You may obtain a copy of the License at
+#
+#        http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+#
+# @file        CMakeLists.txt
+#
+
+SET(LIB_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 (file)
index 0000000..c0c3dcd
--- /dev/null
@@ -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 <dlog.h>
+
+#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 (file)
index 0000000..17f328d
--- /dev/null
@@ -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 <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+/*****************************************************************************
+ *     System headers
+ *****************************************************************************/
+#include <glib.h>
+#include <gio/gio.h>
+
+#include <libgssdp/gssdp.h>
+#include <dlog.h>
+
+/*****************************************************************************
+ *     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;
+}
+
+
+
index 040bc0f..b258641 100644 (file)
@@ -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 (file)
index 0000000..1b88165
--- /dev/null
@@ -0,0 +1,65 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+#include <assert.h>
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <ssdp.h>
+
+#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 (file)
index 0000000..1699e7e
--- /dev/null
@@ -0,0 +1,72 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+#include <assert.h>
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <ssdp.h>
+
+#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 (file)
index 0000000..bc863a3
--- /dev/null
@@ -0,0 +1,523 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+#include <assert.h>
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <ssdp.h>
+
+#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;
+}