Add 'webos' into the target OS list 35/23935/67
authorsungmok.shin <sungmok.shin@lge.com>
Mon, 15 Jan 2018 09:52:29 +0000 (18:52 +0900)
committerNathan Heldt-Sheller <nathan.heldt-sheller@intel.com>
Fri, 15 Jun 2018 21:27:24 +0000 (21:27 +0000)
- TARGET_OS "webos" is added
- IP adapter for network monitoring is implemented
- Introduce PmLog for IoTivity over webos
- Provisioning library is included
- Crash with iotivity-node application is fixed
- Build error due to RD_MODE=all is fixed
- ACG (Access Control Group) configuration file for
  sample application is added
- Procedure for registering/Unregistering luna service
  is implemented
- Internal function for getting LSHandle is implemented
- ocserverbasicops & occlientbasicops for webos
  is implemented (built from separate folder)
- IoTivity sampler(iotivity-node) for webOS is implemented
- Set native application path to /usr/palm/services

Bug: https://jira.iotivity.org/browse/IOT-2967
Change-Id: I3f4f143e7f528e873e5758410e226d98b2679151
Signed-off-by: sungmok.shin <sungmok.shin@lge.com>
112 files changed:
Readme.scons.txt
bridging/SConscript
bridging/mpm_client/SConscript
build_common/SConscript
plugins/SConscript
plugins/unittests/SConscript
resource/SConscript
resource/csdk/connectivity/inc/caadapterutils.h
resource/csdk/connectivity/inc/caipinterface.h
resource/csdk/connectivity/src/SConscript
resource/csdk/connectivity/src/adapter_util/webos/caadapterutils.c [new file with mode: 0644]
resource/csdk/connectivity/src/ip_adapter/caipadapter.c
resource/csdk/connectivity/src/ip_adapter/webos/SConscript [new file with mode: 0644]
resource/csdk/connectivity/src/ip_adapter/webos/caipnwmonitor.c [new file with mode: 0644]
resource/csdk/logger/SConscript
resource/csdk/logger/src/logger.c
resource/csdk/resource-directory/SConscript
resource/csdk/security/SConscript
resource/csdk/security/provisioning/src/SConscript
resource/csdk/stack/SConscript
resource/csdk/stack/samples/SConscript
resource/csdk/stack/samples/webos/com.example.app.iotivity/appinfo.json [new file with mode: 0644]
resource/csdk/stack/samples/webos/com.example.app.iotivity/npm-shrinkwrap.json [new file with mode: 0644]
resource/csdk/stack/samples/webos/com.example.app.iotivity/package.json [new file with mode: 0644]
resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.client/client-lowlevel.js [new file with mode: 0644]
resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.client/client.txt [new file with mode: 0644]
resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.client/com.example.service.iotivity.client.json [new file with mode: 0644]
resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.client/files/sysbus/com.example.service.iotivity.client.api.json [new file with mode: 0644]
resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.client/files/sysbus/com.example.service.iotivity.client.manifest.json [new file with mode: 0644]
resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.client/files/sysbus/com.example.service.iotivity.client.perm.json [new file with mode: 0644]
resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.client/files/sysbus/com.example.service.iotivity.client.role.json [new file with mode: 0644]
resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.client/files/sysbus/com.example.service.iotivity.client.service [new file with mode: 0644]
resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.client/main.js [new file with mode: 0644]
resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.client/oic_svr_db_client.dat [new file with mode: 0644]
resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.client/oic_svr_db_client.json [new file with mode: 0644]
resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.client/package.json [new file with mode: 0644]
resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.server/com.example.service.iotivity.server.json [new file with mode: 0644]
resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.server/files/sysbus/com.example.service.iotivity.server.api.json [new file with mode: 0644]
resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.server/files/sysbus/com.example.service.iotivity.server.manifest.json [new file with mode: 0644]
resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.server/files/sysbus/com.example.service.iotivity.server.perm.json [new file with mode: 0644]
resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.server/files/sysbus/com.example.service.iotivity.server.role.json [new file with mode: 0644]
resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.server/files/sysbus/com.example.service.iotivity.server.service [new file with mode: 0644]
resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.server/main.js [new file with mode: 0644]
resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.server/mock-sensor.js [new file with mode: 0644]
resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.server/oic_svr_db_server.dat [new file with mode: 0644]
resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.server/oic_svr_db_server.json [new file with mode: 0644]
resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.server/package.json [new file with mode: 0644]
resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.server/server-lowlevel.js [new file with mode: 0644]
resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.server/server.txt [new file with mode: 0644]
resource/csdk/stack/samples/webos/com.example.app.iotivity/src/App/App.js [new file with mode: 0644]
resource/csdk/stack/samples/webos/com.example.app.iotivity/src/App/App.less [new file with mode: 0755]
resource/csdk/stack/samples/webos/com.example.app.iotivity/src/App/package.json [new file with mode: 0755]
resource/csdk/stack/samples/webos/com.example.app.iotivity/src/actions/ActionCreators.js [new file with mode: 0644]
resource/csdk/stack/samples/webos/com.example.app.iotivity/src/actions/ActionTypes.js [new file with mode: 0644]
resource/csdk/stack/samples/webos/com.example.app.iotivity/src/index.js [new file with mode: 0644]
resource/csdk/stack/samples/webos/com.example.app.iotivity/src/reducer/Reducer.js [new file with mode: 0644]
resource/csdk/stack/samples/webos/com.example.app.iotivity/src/views/Client.js [new file with mode: 0644]
resource/csdk/stack/samples/webos/com.example.app.iotivity/src/views/MainPanel.js [new file with mode: 0644]
resource/csdk/stack/samples/webos/com.example.app.iotivity/src/views/Server.js [new file with mode: 0644]
resource/csdk/stack/samples/webos/secure/SConscript [new file with mode: 0644]
resource/csdk/stack/samples/webos/secure/common.cpp [new file with mode: 0644]
resource/csdk/stack/samples/webos/secure/common.h [new file with mode: 0644]
resource/csdk/stack/samples/webos/secure/files/sysbus/occlientbasicops.api.json [new file with mode: 0644]
resource/csdk/stack/samples/webos/secure/files/sysbus/occlientbasicops.manifest.json [new file with mode: 0644]
resource/csdk/stack/samples/webos/secure/files/sysbus/occlientbasicops.perm.json [new file with mode: 0644]
resource/csdk/stack/samples/webos/secure/files/sysbus/occlientbasicops.role.json [new file with mode: 0644]
resource/csdk/stack/samples/webos/secure/files/sysbus/occlientbasicops.service [new file with mode: 0644]
resource/csdk/stack/samples/webos/secure/files/sysbus/ocserverbasicops.api.json [new file with mode: 0644]
resource/csdk/stack/samples/webos/secure/files/sysbus/ocserverbasicops.manifest.json [new file with mode: 0644]
resource/csdk/stack/samples/webos/secure/files/sysbus/ocserverbasicops.perm.json [new file with mode: 0644]
resource/csdk/stack/samples/webos/secure/files/sysbus/ocserverbasicops.role.json [new file with mode: 0644]
resource/csdk/stack/samples/webos/secure/files/sysbus/ocserverbasicops.service [new file with mode: 0644]
resource/csdk/stack/samples/webos/secure/occlientbasicops/SConscript [new file with mode: 0644]
resource/csdk/stack/samples/webos/secure/occlientbasicops/logging.h [new file with mode: 0644]
resource/csdk/stack/samples/webos/secure/occlientbasicops/occlientbasicops.cpp [new file with mode: 0644]
resource/csdk/stack/samples/webos/secure/occlientbasicops/occlientbasicops.h [new file with mode: 0644]
resource/csdk/stack/samples/webos/secure/occlientbasicops/oic_svr_db_client_devowner.dat [new file with mode: 0644]
resource/csdk/stack/samples/webos/secure/occlientbasicops/oic_svr_db_client_devowner.json [new file with mode: 0644]
resource/csdk/stack/samples/webos/secure/occlientbasicops/oic_svr_db_client_nondevowner.dat [new file with mode: 0644]
resource/csdk/stack/samples/webos/secure/occlientbasicops/oic_svr_db_client_nondevowner.json [new file with mode: 0644]
resource/csdk/stack/samples/webos/secure/occlientbasicops/sample_payload_logging.h [new file with mode: 0644]
resource/csdk/stack/samples/webos/secure/ocserverbasicops/SConscript [new file with mode: 0644]
resource/csdk/stack/samples/webos/secure/ocserverbasicops/logging.h [new file with mode: 0644]
resource/csdk/stack/samples/webos/secure/ocserverbasicops/ocserverbasicops.cpp [new file with mode: 0644]
resource/csdk/stack/samples/webos/secure/ocserverbasicops/ocserverbasicops.h [new file with mode: 0644]
resource/csdk/stack/samples/webos/secure/ocserverbasicops/oic_svr_db_server.json [new file with mode: 0644]
resource/csdk/stack/samples/webos/unsecure/SConscript [new file with mode: 0644]
resource/csdk/stack/samples/webos/unsecure/common.cpp [new file with mode: 0644]
resource/csdk/stack/samples/webos/unsecure/common.h [new file with mode: 0644]
resource/csdk/stack/samples/webos/unsecure/device_properties.json [new file with mode: 0644]
resource/csdk/stack/samples/webos/unsecure/files/sysbus/occlient.api.json [new file with mode: 0644]
resource/csdk/stack/samples/webos/unsecure/files/sysbus/occlient.manifest.json [new file with mode: 0644]
resource/csdk/stack/samples/webos/unsecure/files/sysbus/occlient.perm.json [new file with mode: 0644]
resource/csdk/stack/samples/webos/unsecure/files/sysbus/occlient.role.json [new file with mode: 0644]
resource/csdk/stack/samples/webos/unsecure/files/sysbus/occlient.service [new file with mode: 0644]
resource/csdk/stack/samples/webos/unsecure/files/sysbus/ocserver.api.json [new file with mode: 0644]
resource/csdk/stack/samples/webos/unsecure/files/sysbus/ocserver.manifest.json [new file with mode: 0644]
resource/csdk/stack/samples/webos/unsecure/files/sysbus/ocserver.perm.json [new file with mode: 0644]
resource/csdk/stack/samples/webos/unsecure/files/sysbus/ocserver.role.json [new file with mode: 0644]
resource/csdk/stack/samples/webos/unsecure/files/sysbus/ocserver.service [new file with mode: 0644]
resource/csdk/stack/samples/webos/unsecure/introspection.json [new file with mode: 0644]
resource/csdk/stack/samples/webos/unsecure/occlient/SConscript [new file with mode: 0644]
resource/csdk/stack/samples/webos/unsecure/occlient/logging.h [new file with mode: 0644]
resource/csdk/stack/samples/webos/unsecure/occlient/occlient.cpp [new file with mode: 0644]
resource/csdk/stack/samples/webos/unsecure/occlient/occlient.h [new file with mode: 0644]
resource/csdk/stack/samples/webos/unsecure/occlient/sample_payload_logging.h [new file with mode: 0644]
resource/csdk/stack/samples/webos/unsecure/ocserver/SConscript [new file with mode: 0644]
resource/csdk/stack/samples/webos/unsecure/ocserver/logging.h [new file with mode: 0644]
resource/csdk/stack/samples/webos/unsecure/ocserver/ocserver.cpp [new file with mode: 0644]
resource/csdk/stack/samples/webos/unsecure/ocserver/ocserver.h [new file with mode: 0644]
resource/provisioning/SConscript
resource/src/SConscript

index 4526e93..b762287 100644 (file)
@@ -235,6 +235,14 @@ to run many build combinations with TARGET_OS to 'windows'.
       $ run build -arch x86 -release
 See run.bat for more example usage parameters
 
+webOS:
+ * Possible values for <TARGET_TRANSPORT> are: ALL, IP
+
+IoTivity build for webOS requires webOS build based on the open-embedded build
+framework. So to speak, scons build is not directly triggered by user but by
+the build recipe combinated with build environment. You can check the whole
+procedure for building IoTivity over webOS at https://wiki.iotivity.org/webos.
+
 * Additional options
  * VERBOSE=true or false (Show compilation)
  * RELEASE=true or false (Build for release?)
index b7b0aaa..2539e37 100644 (file)
@@ -32,7 +32,7 @@ src_dir = env.get('SRC_DIR')
 # rapidjson fetch
 SConscript('#extlibs/rapidjson/SConscript')
 
-if target_os not in ['android', 'darwin', 'ios', 'tizen', 'msys_nt', 'windows']:
+if target_os not in ['android', 'darwin', 'ios', 'tizen', 'msys_nt', 'webos', 'windows']:
 
     SConscript('common/SConscript')
 
index 272546d..62baeec 100644 (file)
@@ -55,10 +55,10 @@ mpmclient_env.AppendUnique(LIBS=[
     'curl'
 ])
 
-if target_os in ['linux', 'tizen', 'yocto']:
+if target_os in ['linux', 'tizen', 'yocto', 'webos']:
     mpmclient_env.AppendUnique(LIBS = ['rt'])
 
-if target_os in ['linux', 'tizen']:
+if target_os in ['linux', 'tizen', 'webos']:
     mpmclient_env.ParseConfig('pkg-config --cflags --libs sqlite3')
 else:
     mpmclient_env.AppendUnique(CPPPATH=['#/extlibs/sqlite3'])
index 5d0f6b3..7199ea7 100644 (file)
@@ -12,7 +12,7 @@ project_version = '1.4.0'
 
 # Map of build host to possible target os
 host_target_map = {
-    'linux': ['linux', 'android', 'yocto', 'tizen'],
+    'linux': ['linux', 'android', 'yocto', 'tizen', 'webos'],
     'windows': ['windows', 'android'],
     'darwin': ['darwin', 'ios', 'android'],
     'msys_nt': ['msys_nt'],
@@ -26,6 +26,7 @@ os_arch_map = {
         'armv6l', 'armv7l'
     ],
     'tizen': ['x86', 'x86_64', 'arm', 'arm-v7a', 'armeabi-v7a', 'arm64'],
+    'webos': ['arm'],
     'android': [
         'x86', 'x86_64', 'armeabi', 'armeabi-v7a', 'armeabi-v7a-hard',
         'arm64-v8a'
@@ -66,6 +67,8 @@ if target_os not in host_target_map[host]:
 # work out a reasonable default for target_arch if not specified by user
 if target_os == 'android':
     default_arch = 'x86'
+elif target_os == 'webos':
+    default_arch = 'arm'
 else:
     default_arch = platform.machine()
     if target_os == 'windows':
@@ -363,7 +366,7 @@ if target_os in targets_support_cc:
         print(tc_set_msg)
 
 # Import env variables only if reproductibility is ensured
-if target_os in ['yocto']:
+if target_os in ['yocto', 'webos']:
     env['CONFIG_ENVIRONMENT_IMPORT'] = True
 else:
     env['CONFIG_ENVIRONMENT_IMPORT'] = False
@@ -695,6 +698,9 @@ if 'ALL' in target_transport:
         env.AppendUnique(CPPDEFINES=[
             'IP_ADAPTER', 'EDR_ADAPTER', 'LE_ADAPTER', 'NFC_ADAPTER'
         ])
+    elif (target_os in ['webos']):
+        env.AppendUnique(CPPDEFINES=[
+            'IP_ADAPTER', 'NO_EDR_ADAPTER', 'NO_LE_ADAPTER'])
     elif (target_os in ['darwin', 'ios', 'msys_nt', 'windows']):
         env.AppendUnique(
             CPPDEFINES=['IP_ADAPTER', 'NO_EDR_ADAPTER', 'NO_LE_ADAPTER'])
@@ -703,7 +709,7 @@ if 'ALL' in target_transport:
             CPPDEFINES=['IP_ADAPTER', 'EDR_ADAPTER', 'LE_ADAPTER'])
 else:
     if ('BT' in target_transport):
-        if target_os in ('linux', 'yocto'):
+        if target_os in ('linux', 'yocto', 'webos'):
             msg = "CA Transport BT is not supported "
             Exit(msg)
         else:
@@ -723,7 +729,7 @@ else:
 
     if with_tcp:
         if (target_os in [
-                'linux', 'tizen', 'android', 'ios', 'windows', 'yocto'
+                'linux', 'tizen', 'android', 'ios', 'windows', 'yocto', 'webos'
         ]):
             env.AppendUnique(CPPDEFINES=['TCP_ADAPTER', 'WITH_TCP'])
         else:
@@ -774,7 +780,7 @@ env.SConscript('external_builders.scons')
 ######################################################################
 # Link scons to Yocto cross-toolchain ONLY when target_os is yocto
 ######################################################################
-if target_os == "yocto":
+if target_os in ['yocto', 'webos']:
     '''
     This code injects Yocto cross-compilation tools+flags into the scons
     construction environment in order to invoke the relevant tools while
index 38918de..a153c0f 100644 (file)
@@ -28,7 +28,7 @@ Import('env')
 target_os = env.get('TARGET_OS')
 build_sample = env.get('BUILD_SAMPLE')
 
-if target_os not in ['android', 'darwin', 'ios', 'tizen', 'msys_nt', 'windows']:
+if target_os not in ['android', 'darwin', 'ios', 'tizen', 'msys_nt', 'windows', 'webos']:
 
     SConscript('zigbee_wrapper/SConscript')
 
index 1b7f937..cb0016c 100644 (file)
@@ -55,7 +55,7 @@ Alias("piunittests", piunittests)
 
 unittests_env.AppendTarget('piunittests')
 if unittests_env.get('TEST') == '1':
-    if target_os in ['linux']:
+    if target_os in ['linux', 'webos']:
         run_test(unittests_env, 'plugins_unittests.memcheck',
                  'plugins/unittests/piunittests', piunittests)
 
index ef3785b..50b8447 100644 (file)
@@ -56,7 +56,7 @@ if target_os not in ['darwin', 'ios', 'android']:
     # Build examples
     SConscript('examples/SConscript')
 
-if target_os in ['linux', 'windows', 'darwin', 'msys_nt']:
+if target_os in ['linux', 'windows', 'darwin', 'msys_nt', 'webos']:
     if target_os == 'darwin':
         env.Command('#/out/darwin/iotivity-csdk.framework', None,
                     '#/tools/darwin/mkfwk_osx.sh')
index e14e60b..a6f66f4 100644 (file)
 #include "uarraylist.h"
 #include "cacommonutil.h"
 
+#ifdef __webos__
+#include <luna-service2/lunaservice.h>
+#include <pbnjson.h>
+#include "cathreadpool.h"
+#endif // __webos__
+
 #ifdef __cplusplus
 extern "C"
 {
@@ -315,6 +321,27 @@ void CALogAdapterTypeInfo(CATransportAdapter_t adapter);
  */
 CAResult_t CAGetIpv6AddrScopeInternal(const char *addr, CATransportFlags_t *scopeLevel);
 
+#ifdef __webos__
+/**
+ * Initialize Luna service.
+ * @param[in] handle The thread pool structure.
+ * @return CA_STATUS_OK on success, or an appropriate error code on failure.
+ *
+ */
+CAResult_t CAInitializeLS(ca_thread_pool_t handle);
+
+/**
+ * Terminate Luna service.
+ */
+void CATerminateLS();
+
+/**
+ * Get Luna service handle.
+ * @return Luna service handle.
+ */
+LSHandle* CAGetLSHandle();
+#endif // __webos__
+
 #ifdef __cplusplus
 } /* extern "C" */
 #endif
index 3a5dcea..80ed601 100644 (file)
@@ -171,6 +171,16 @@ void CAWakeUpForChange(void);
  */
 void CAIPSetErrorHandler(CAIPErrorHandleCallback errorHandleCallback);
 
+#ifdef __webos__
+/**
+ * Set the thread pool handle for IP monitoring thread.
+ *
+ * @param[in] handle Thread pool handle which is given by above layer
+ *                   for using thread creation task.
+ */
+void CAIPSetMonitorThreadPoolHandle(ca_thread_pool_t handle);
+#endif // __webos__
+
 #ifdef __cplusplus
 }
 #endif
index b249cb3..c5e1efc 100644 (file)
@@ -49,10 +49,16 @@ connectivity_env.SConscript(root_dir + '/common/SConscript',
 connectivity_env.SConscript(root_dir + '/util/SConscript',
                             exports='connectivity_env')
 
-src_files = [File(src) for src in (
-    'adapter_util/caadapterutils.c',
-    'adapter_util/cacertprofile.c'
-)]
+if ca_os in ['webos']:
+    src_files = [File(src) for src in (
+        'adapter_util/webos/caadapterutils.c',
+        'adapter_util/cacertprofile.c'
+    )]
+else:
+    src_files = [File(src) for src in (
+        'adapter_util/caadapterutils.c',
+        'adapter_util/cacertprofile.c'
+    )]
 
 if (('BLE' in ca_transport) or ('ALL' in ca_transport)):
     src_files.append(File('adapter_util/cafragmentation.c'))
@@ -119,6 +125,8 @@ if 'ALL' in ca_transport:
         transports.add('bt_edr_adapter')
         transports.add('bt_le_adapter')
         transports.add('nfc_adapter')
+    elif ca_os in ['webos']:
+        transports.add('ip_adapter')
     elif ca_os in ['darwin', 'ios', 'msys_nt', 'windows']:
         transports.add('ip_adapter')
     else:
@@ -138,7 +146,7 @@ if 'BLE' in ca_transport:
 if 'NFC' in ca_transport:
     transports.add('nfc_adapter')
 
-if ca_os in ['linux', 'tizen', 'android', 'ios', 'windows'] and with_tcp:
+if ca_os in ['linux', 'tizen', 'android', 'ios', 'windows', 'webos'] and with_tcp:
     transports.add('tcp_adapter')
 
 SConscript(dirs=list(transports), exports='connectivity_env')
@@ -162,6 +170,11 @@ if connectivity_env.get('SECURED') == '1':
 if ca_os in ['tizen']:
     connectivity_env.AppendUnique(LIBS=['pthread'])
 
+if ca_os in ['webos']:
+    connectivity_env.ParseConfig("pkg-config --cflags --libs glib-2.0")
+    connectivity_env.ParseConfig("pkg-config --cflags --libs luna-service2")
+    connectivity_env.ParseConfig("pkg-config --cflags --libs pbnjson_c")
+
 # c_common calls into mbedcrypto.
 connectivity_env.AppendUnique(LIBS=['mbedcrypto'])
 
@@ -169,7 +182,7 @@ calib_internal = connectivity_env.StaticLibrary(
     'connectivity_abstraction_internal', connectivity_env.get('CA_SRC'))
 calib = Flatten(calib_internal)
 
-if ca_os in ['android', 'tizen', 'linux', 'yocto']:
+if ca_os in ['android', 'tizen', 'linux', 'yocto', 'webos']:
     connectivity_env.AppendUnique(LIBS=['coap'])
     if ca_os != 'android':
         connectivity_env.AppendUnique(LIBS=['rt'])
diff --git a/resource/csdk/connectivity/src/adapter_util/webos/caadapterutils.c b/resource/csdk/connectivity/src/adapter_util/webos/caadapterutils.c
new file mode 100644 (file)
index 0000000..0e0e171
--- /dev/null
@@ -0,0 +1,586 @@
+/******************************************************************
+ *
+ * Copyright (c) 2018 LG Electronics Inc.
+ * Copyright 2014 Samsung Electronics 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.
+ *
+ ******************************************************************/
+
+#include "iotivity_config.h"
+#include "caadapterutils.h"
+
+#include <string.h>
+#include <ctype.h>
+#include "oic_string.h"
+#include "oic_malloc.h"
+#include <errno.h>
+#include <inttypes.h>
+
+#ifdef HAVE_WS2TCPIP_H
+#include <ws2tcpip.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#if defined(HAVE_WINSOCK2_H) && defined(HAVE_WS2TCPIP_H)
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_IN6ADDR_H
+#include <in6addr.h>
+#endif
+
+#ifdef __JAVA__
+#include <jni.h>
+
+/**
+ * @var g_jvm
+ * @brief pointer to store JavaVM
+ */
+static JavaVM *g_jvm = NULL;
+
+#ifdef __ANDROID__
+/**
+ * @var gContext
+ * @brief pointer to store context for android callback interface
+ */
+static jobject g_Context = NULL;
+static jobject g_Activity = NULL;
+#endif
+#endif
+
+#define MAX_LS_NAME_SIZE 1024
+#define MAX_GET_LS_SERVICE_NAME_COUNT 5
+static LSHandle *g_pLSHandle = NULL;
+static GMainContext *g_loopContext = NULL;
+static GMainLoop *g_mainLoop = NULL;
+static bool g_isLSRegistering = false;
+char *g_lsServiceName = NULL;
+
+#define CA_ADAPTER_UTILS_TAG "OIC_CA_ADAP_UTILS"
+
+CAResult_t CAConvertAddrToName(const struct sockaddr_storage *sockAddr, socklen_t sockAddrLen,
+                               char *host, uint16_t *port)
+{
+    VERIFY_NON_NULL_RET(sockAddr, CA_ADAPTER_UTILS_TAG, "sockAddr is null",
+                        CA_STATUS_INVALID_PARAM);
+    VERIFY_NON_NULL_RET(host, CA_ADAPTER_UTILS_TAG, "host is null", CA_STATUS_INVALID_PARAM);
+    VERIFY_NON_NULL_RET(port, CA_ADAPTER_UTILS_TAG, "port is null", CA_STATUS_INVALID_PARAM);
+
+    int r = getnameinfo((struct sockaddr *)sockAddr,
+                        sockAddrLen,
+                        host, MAX_ADDR_STR_SIZE_CA,
+                        NULL, 0,
+                        NI_NUMERICHOST|NI_NUMERICSERV);
+    if (r)
+    {
+#if defined(EAI_SYSTEM)
+        if (EAI_SYSTEM == r)
+        {
+            OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG,
+                            "getnameinfo failed: errno %s", strerror(errno));
+        }
+        else
+        {
+            OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG,
+                            "getnameinfo failed: %s", gai_strerror(r));
+        }
+#elif defined(_WIN32)
+        OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG,
+                            "getnameinfo failed: errno %i", WSAGetLastError());
+#else
+        OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG,
+                            "getnameinfo failed: %s", gai_strerror(r));
+#endif
+        return CA_STATUS_FAILED;
+    }
+    *port = ntohs(((struct sockaddr_in *)sockAddr)->sin_port); // IPv4 and IPv6
+    return CA_STATUS_OK;
+}
+
+CAResult_t CAConvertNameToAddr(const char *host, uint16_t port, struct sockaddr_storage *sockaddr)
+{
+    VERIFY_NON_NULL_RET(host, CA_ADAPTER_UTILS_TAG, "host is null", CA_STATUS_INVALID_PARAM);
+    VERIFY_NON_NULL_RET(sockaddr, CA_ADAPTER_UTILS_TAG, "sockaddr is null",
+                        CA_STATUS_INVALID_PARAM);
+
+    struct addrinfo *addrs = NULL;
+    struct addrinfo hints = { .ai_family = AF_UNSPEC,
+                              .ai_flags = AI_NUMERICHOST };
+
+    int r = getaddrinfo(host, NULL, &hints, &addrs);
+    if (r)
+    {
+        if (NULL != addrs)
+        {
+            freeaddrinfo(addrs);
+        }
+#if defined(EAI_SYSTEM)
+        if (EAI_SYSTEM == r)
+        {
+            OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG,
+                            "getaddrinfo failed: errno %s", strerror(errno));
+        }
+        else
+        {
+            OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG,
+                            "getaddrinfo failed: %s", gai_strerror(r));
+        }
+#elif defined(_WIN32)
+        OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG,
+                            "getaddrinfo failed: errno %i", WSAGetLastError());
+#else
+        OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG,
+                            "getaddrinfo failed: %s", gai_strerror(r));
+#endif
+        return CA_STATUS_FAILED;
+    }
+    // assumption: in this case, getaddrinfo will only return one addrinfo
+    // or first is the one we want.
+    if (addrs[0].ai_family == AF_INET6)
+    {
+        memcpy(sockaddr, addrs[0].ai_addr, sizeof (struct sockaddr_in6));
+        ((struct sockaddr_in6 *)sockaddr)->sin6_port = htons(port);
+    }
+    else
+    {
+        memcpy(sockaddr, addrs[0].ai_addr, sizeof (struct sockaddr_in));
+        ((struct sockaddr_in *)sockaddr)->sin_port = htons(port);
+    }
+    freeaddrinfo(addrs);
+    return CA_STATUS_OK;
+}
+
+#ifdef __JAVA__
+void CANativeJNISetJavaVM(JavaVM *jvm)
+{
+    OIC_LOG_V(DEBUG, CA_ADAPTER_UTILS_TAG, "CANativeJNISetJavaVM");
+    g_jvm = jvm;
+}
+
+JavaVM *CANativeJNIGetJavaVM()
+{
+    return g_jvm;
+}
+
+void CADeleteGlobalReferences(JNIEnv *env)
+{
+    OC_UNUSED(env);
+#ifdef __ANDROID__
+    if (g_Context)
+    {
+        (*env)->DeleteGlobalRef(env, g_Context);
+        g_Context = NULL;
+    }
+
+    if (g_Activity)
+    {
+        (*env)->DeleteGlobalRef(env, g_Activity);
+        g_Activity = NULL;
+    }
+#endif //__ANDROID__
+}
+
+jmethodID CAGetJNIMethodID(JNIEnv *env, const char* className,
+                           const char* methodName,
+                           const char* methodFormat)
+{
+    VERIFY_NON_NULL_RET(env, CA_ADAPTER_UTILS_TAG, "env", NULL);
+    VERIFY_NON_NULL_RET(className, CA_ADAPTER_UTILS_TAG, "className", NULL);
+    VERIFY_NON_NULL_RET(methodName, CA_ADAPTER_UTILS_TAG, "methodName", NULL);
+    VERIFY_NON_NULL_RET(methodFormat, CA_ADAPTER_UTILS_TAG, "methodFormat", NULL);
+
+    jclass jni_cid = (*env)->FindClass(env, className);
+    if (!jni_cid)
+    {
+        OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG, "jni_cid [%s] is null", className);
+        CACheckJNIException(env);
+        return NULL;
+    }
+
+    jmethodID jni_midID = (*env)->GetMethodID(env, jni_cid, methodName, methodFormat);
+    if (!jni_midID)
+    {
+        OIC_LOG_V(ERROR, CA_ADAPTER_UTILS_TAG, "jni_midID [%s] is null", methodName);
+        CACheckJNIException(env);
+        (*env)->DeleteLocalRef(env, jni_cid);
+        return NULL;
+    }
+
+    (*env)->DeleteLocalRef(env, jni_cid);
+    return jni_midID;
+}
+
+bool CACheckJNIException(JNIEnv *env)
+{
+    if ((*env)->ExceptionCheck(env))
+    {
+        (*env)->ExceptionDescribe(env);
+        (*env)->ExceptionClear(env);
+        return true;
+    }
+    return false;
+}
+
+#ifdef __ANDROID__
+void CANativeJNISetContext(JNIEnv *env, jobject context)
+{
+    OIC_LOG_V(DEBUG, CA_ADAPTER_UTILS_TAG, "CANativeJNISetContext");
+
+    if (!context)
+    {
+        OIC_LOG(ERROR, CA_ADAPTER_UTILS_TAG, "context is null");
+        return;
+    }
+
+    if (!g_Context)
+    {
+        g_Context = (*env)->NewGlobalRef(env, context);
+    }
+    else
+    {
+        OIC_LOG(INFO, CA_ADAPTER_UTILS_TAG, "context is already set");
+    }
+}
+
+jobject CANativeJNIGetContext()
+{
+    return g_Context;
+}
+
+void CANativeSetActivity(JNIEnv *env, jobject activity)
+{
+    OIC_LOG_V(DEBUG, CA_ADAPTER_UTILS_TAG, "CANativeSetActivity");
+
+    if (!activity)
+    {
+        OIC_LOG(ERROR, CA_ADAPTER_UTILS_TAG, "activity is null");
+        return;
+    }
+
+    if (!g_Activity)
+    {
+        g_Activity = (*env)->NewGlobalRef(env, activity);
+    }
+    else
+    {
+        OIC_LOG(INFO, CA_ADAPTER_UTILS_TAG, "activity is already set");
+    }
+}
+
+jobject *CANativeGetActivity()
+{
+    return g_Activity;
+}
+#endif //__ANDROID__
+#endif //JAVA__
+
+void CALogAdapterStateInfo(CATransportAdapter_t adapter, CANetworkStatus_t state)
+{
+    OIC_LOG(DEBUG, CA_ADAPTER_UTILS_TAG, "CALogAdapterStateInfo");
+    OIC_LOG(DEBUG, ANALYZER_TAG, "=================================================");
+    CALogAdapterTypeInfo(adapter);
+    if (CA_INTERFACE_UP == state)
+    {
+        OIC_LOG(DEBUG, ANALYZER_TAG, "adapter status is changed to CA_INTERFACE_UP");
+    }
+    else
+    {
+        OIC_LOG(DEBUG, ANALYZER_TAG, "adapter status is changed to CA_INTERFACE_DOWN");
+    }
+    OIC_LOG(DEBUG, ANALYZER_TAG, "=================================================");
+}
+
+void CALogSendStateInfo(CATransportAdapter_t adapter,
+                        const char *addr, uint16_t port, ssize_t sentLen,
+                        bool isSuccess, const char* message)
+{
+#ifndef TB_LOG
+    OC_UNUSED(addr);
+    OC_UNUSED(port);
+    OC_UNUSED(sentLen);
+    OC_UNUSED(message);
+#endif
+
+    OIC_LOG(DEBUG, CA_ADAPTER_UTILS_TAG, "CALogSendStateInfo");
+    OIC_LOG(DEBUG, ANALYZER_TAG, "=================================================");
+
+    if (true == isSuccess)
+    {
+        OIC_LOG_V(DEBUG, ANALYZER_TAG, "Send Success, sent length = [%" PRIdPTR "]", sentLen);
+    }
+    else
+    {
+        OIC_LOG_V(DEBUG, ANALYZER_TAG, "Send Failure, error message  = [%s]",
+                  message != NULL ? message : "no message");
+    }
+
+    CALogAdapterTypeInfo(adapter);
+    OIC_LOG_V(DEBUG, ANALYZER_TAG, "Address = [%s]:[%d]", addr, port);
+    OIC_LOG(DEBUG, ANALYZER_TAG, "=================================================");
+}
+
+void CALogAdapterTypeInfo(CATransportAdapter_t adapter)
+{
+    switch(adapter)
+    {
+        case CA_ADAPTER_IP:
+            OIC_LOG(DEBUG, ANALYZER_TAG, "Transport Type = [OC_ADAPTER_IP]");
+            break;
+        case CA_ADAPTER_TCP:
+            OIC_LOG(DEBUG, ANALYZER_TAG, "Transport Type = [OC_ADAPTER_TCP]");
+            break;
+        case CA_ADAPTER_GATT_BTLE:
+            OIC_LOG(DEBUG, ANALYZER_TAG, "Transport Type = [OC_ADAPTER_GATT_BTLE]");
+            break;
+        case CA_ADAPTER_RFCOMM_BTEDR:
+            OIC_LOG(DEBUG, ANALYZER_TAG, "Transport Type = [OC_ADAPTER_RFCOMM_BTEDR]");
+            break;
+        default:
+            OIC_LOG_V(DEBUG, ANALYZER_TAG, "Transport Type = [%d]", adapter);
+            break;
+    }
+}
+
+CAResult_t CAGetIpv6AddrScopeInternal(const char *addr, CATransportFlags_t *scopeLevel)
+{
+    if (!addr || !scopeLevel)
+    {
+        return CA_STATUS_INVALID_PARAM;
+    }
+    // check addr is ipv6
+    struct in6_addr inAddr6;
+    if (1 == inet_pton(AF_INET6, addr, &inAddr6))
+    {
+        // check addr is multicast
+        if (IN6_IS_ADDR_MULTICAST(&inAddr6))
+        {
+            *scopeLevel = (CATransportFlags_t)(inAddr6.s6_addr[1] & 0xf);
+            return CA_STATUS_OK;
+        }
+        else
+        {
+            // check addr is linklocal or loopback
+            if (IN6_IS_ADDR_LINKLOCAL(&inAddr6) || IN6_IS_ADDR_LOOPBACK(&inAddr6))
+            {
+                *scopeLevel = CA_SCOPE_LINK;
+                return CA_STATUS_OK;
+            }
+            // check addr is sitelocal
+            else if (IN6_IS_ADDR_SITELOCAL(&inAddr6))
+            {
+                *scopeLevel = CA_SCOPE_SITE;
+                return CA_STATUS_OK;
+            }
+            else
+            {
+                *scopeLevel = CA_SCOPE_GLOBAL;
+                return CA_STATUS_OK;
+            }
+        }
+    }
+    else
+    {
+        OIC_LOG(ERROR, CA_ADAPTER_UTILS_TAG, "Failed at parse ipv6 address using inet_pton");
+        return CA_STATUS_FAILED;
+    }
+}
+
+static bool CACheckLSRegistered()
+{
+    if (g_pLSHandle)
+    {
+        OIC_LOG(INFO, CA_ADAPTER_UTILS_TAG, "Luna service is already registered");
+        return true;
+    }
+    else
+    {
+        OIC_LOG(INFO, CA_ADAPTER_UTILS_TAG, "Luna service is not registered");
+        return false;
+    }
+}
+
+static bool CACreateLSServiceName()
+{
+    FILE *fp = NULL;
+    char lunaServiceBuff[MAX_LS_NAME_SIZE];
+    size_t readSize = 0;
+    char *command = NULL;
+    command = g_strdup_printf("ls-monitor -l | grep %d | awk '{print $2}'", getpid());
+
+    OIC_LOG_V(INFO, CA_ADAPTER_UTILS_TAG, "PID : %d", getpid());
+
+    // Get service Name by pid
+    fp = popen(command, "r");
+    if (NULL == fp)
+    {
+        OIC_LOG(ERROR, CA_ADAPTER_UTILS_TAG, "Failed to open ls-monitor");
+        exit(1);
+    }
+
+    readSize = fread((void*)lunaServiceBuff, sizeof(char), MAX_LS_NAME_SIZE - 1, fp);
+    OIC_LOG_V(INFO, CA_ADAPTER_UTILS_TAG, "lunaServiceBuff : %s, readSize: %d", lunaServiceBuff, readSize);
+    if (0 == readSize)
+    {
+        OIC_LOG(ERROR, CA_ADAPTER_UTILS_TAG, "This process does not have Luna service");
+        g_free(command);
+        pclose(fp);
+        return false;
+    }
+    lunaServiceBuff[readSize]='0';
+
+    g_lsServiceName = g_strdup_printf("%s-iotivity%d", g_strndup(lunaServiceBuff, readSize-1), getpid());
+
+    pclose( fp);
+
+    return true;
+}
+
+static void CATriggerCreateLSServiceName()
+{
+    for (int i = 0; i < MAX_GET_LS_SERVICE_NAME_COUNT; i++)
+    {
+        if (CACreateLSServiceName())
+        {
+            OIC_LOG_V(DEBUG, CA_ADAPTER_UTILS_TAG, "Luna service name : %s", g_lsServiceName);
+            break;
+        }
+
+        sleep(1);
+    }
+}
+
+static void CAStartLSMainLoop(void * data)
+{
+    OIC_LOG(DEBUG, CA_ADAPTER_UTILS_TAG, "CAStartLSMainLoop");
+
+    LSError lserror;
+    LSErrorInit(&lserror);
+
+
+    g_isLSRegistering = true;
+    OIC_LOG(DEBUG, CA_ADAPTER_UTILS_TAG, "CAStartLSMainLoop Break 1");
+    if (g_lsServiceName == NULL)
+    {
+        OIC_LOG(ERROR, CA_ADAPTER_UTILS_TAG, "Failed to create Luna service name");
+        return;
+    }
+
+    g_loopContext = g_main_context_new();
+    g_mainLoop = g_main_loop_new(g_loopContext, FALSE);
+    g_main_context_push_thread_default(g_loopContext);
+
+    if (!g_mainLoop)
+    {
+        OIC_LOG(ERROR, CA_ADAPTER_UTILS_TAG, "Failed to create main loop");
+        return;
+    }
+
+    if (!LSRegister(g_lsServiceName, &g_pLSHandle, &lserror))
+    {
+        OIC_LOG(ERROR, CA_ADAPTER_UTILS_TAG, "Failed to register LS Handle");
+        return;
+    }
+
+    if (!LSGmainAttach(g_pLSHandle, g_mainLoop, &lserror))
+    {
+        OIC_LOG(ERROR, CA_ADAPTER_UTILS_TAG, "Failed to attach main loop");
+        return;
+    }
+
+    g_isLSRegistering = false;
+    g_main_loop_run(g_mainLoop);
+
+    g_main_context_unref(g_loopContext);
+    g_main_loop_unref(g_mainLoop);
+}
+
+CAResult_t CAInitializeLS(ca_thread_pool_t handle)
+{
+    OIC_LOG(DEBUG, CA_ADAPTER_UTILS_TAG, "CAInitializeLS");
+
+    CAResult_t result = CA_STATUS_FAILED;
+
+    if (CACheckLSRegistered())
+       return CA_STATUS_OK;
+
+    if (g_isLSRegistering)
+    {
+        OIC_LOG(DEBUG, CA_ADAPTER_UTILS_TAG, "Wait for registering LS service");
+        sleep(1);
+    }
+
+    CATriggerCreateLSServiceName();
+
+    result = ca_thread_pool_add_task(handle, CAStartLSMainLoop, NULL);
+    if (CA_STATUS_OK != result)
+    {
+        OIC_LOG(ERROR, CA_ADAPTER_UTILS_TAG, "LS thread_pool_add_task failed");
+        return result;
+    }
+
+    for (int i = 0; i < MAX_GET_LS_SERVICE_NAME_COUNT; i++)
+    {
+        if (CACheckLSRegistered())
+        {
+            result = CA_STATUS_OK;
+            break;
+        }
+        else
+        {
+            sleep(1);
+            result = CA_STATUS_FAILED;
+        }
+    }
+    return result;
+}
+
+void CATerminateLS()
+{
+    OIC_LOG(INFO, CA_ADAPTER_UTILS_TAG, "CATerminateLS");
+    LSError lserror;
+    LSErrorInit(&lserror);
+
+    if (g_pLSHandle)
+    {
+        OIC_LOG(DEBUG, CA_ADAPTER_UTILS_TAG, "g_pLSHandle is not null");
+        if (!LSUnregister(g_pLSHandle, &lserror))
+        {
+            OIC_LOG(DEBUG, CA_ADAPTER_UTILS_TAG, "Failed to unregister Luna service");
+            LSErrorPrint(&lserror, stderr);
+            LSErrorFree(&lserror);
+        }
+        g_pLSHandle = NULL;
+    }
+
+    g_main_loop_quit(g_mainLoop);
+}
+
+LSHandle* CAGetLSHandle()
+{
+    OIC_LOG(DEBUG, CA_ADAPTER_UTILS_TAG, "CAGetLSHandle");
+    return g_pLSHandle;
+}
+
index 6019fd6..6d2e5ae 100644 (file)
@@ -339,6 +339,10 @@ CAResult_t CAInitializeIP(CARegisterConnectivityCallback registerCallback,
     OIC_LOG(DEBUG, TAG, "WSAStartup Succeeded");
 #endif
 
+#ifdef __webos__
+    CAIPSetMonitorThreadPoolHandle(handle);
+#endif // __webos__
+
     g_networkChangeCallback = netCallback;
     g_networkPacketCallback = networkPacketCallback;
     g_errorCallback = errorCallback;
diff --git a/resource/csdk/connectivity/src/ip_adapter/webos/SConscript b/resource/csdk/connectivity/src/ip_adapter/webos/SConscript
new file mode 100644 (file)
index 0000000..d5097f5
--- /dev/null
@@ -0,0 +1,35 @@
+#******************************************************************
+#
+# Copyright (c) 2018 LG Electronics, Inc.
+#
+#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+#
+# 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
+#
+#      https://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.
+#
+#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+
+#######################################################
+#       Build IP adapter for webOS
+#######################################################
+import os
+
+Import('connectivity_env')
+
+connectivity_env.ParseConfig("pkg-config --cflags --libs glib-2.0")
+connectivity_env.ParseConfig("pkg-config --cflags --libs luna-service2")
+connectivity_env.ParseConfig("pkg-config --cflags --libs pbnjson_c")
+
+connectivity_env.AppendUnique(CA_SRC=[File('caipnwmonitor.c')])
+
+connectivity_env.AppendUnique(CPPDEFINES=['__webos__'])
diff --git a/resource/csdk/connectivity/src/ip_adapter/webos/caipnwmonitor.c b/resource/csdk/connectivity/src/ip_adapter/webos/caipnwmonitor.c
new file mode 100644 (file)
index 0000000..4dd9b18
--- /dev/null
@@ -0,0 +1,672 @@
+/*******************************************************************
+ *
+ * Copyright (c) 2018 LG Electronics, Inc.
+ * Copyright 2014 Samsung Electronics 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
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+
+#include "caipinterface.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <ifaddrs.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <netdb.h>
+#include <errno.h>
+
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+
+#include <luna-service2/lunaservice.h>
+#include <pbnjson.h>
+#include "caipnwmonitor.h"
+#include "octhread.h"
+#include "caadapterutils.h"
+#include "experimental/logger.h"
+#include "oic_malloc.h"
+#include "oic_string.h"
+#include <coap/utlist.h>
+
+#define TAG "OIC_CA_IP_MONITOR"
+#define LS_CONNECTIONMANAGER_GETSTATUS_URI "luna://com.webos.service.connectionmanager/getstatus"
+
+typedef struct _CONNECTION_STATUS {
+    bool isConnectWired;
+    bool isConnectWiFi;
+} CONNECTION_STATUS_T;
+
+CONNECTION_STATUS_T gConnectionStates;
+
+/*
+ * Enable or disable log for network changed event
+ */
+#define NETWORK_INTERFACE_CHANGED_LOGGING 1
+
+/**
+ * Mutex for synchronizing access to cached interface and IP address information.
+ */
+static oc_mutex g_networkMonitorContextMutex = NULL;
+
+/**
+ * Used to storing network interface.
+ */
+static u_arraylist_t *g_netInterfaceList = NULL;
+
+/**
+ * Used to storing adapter changes callback interface.
+ */
+static struct CAIPCBData_t *g_adapterCallbackList = NULL;
+
+/**
+ * Used to monitoring network changes over luna bus which webos uses for IPC
+ */
+static ca_thread_pool_t g_ipMonitorThreadPool = NULL;
+
+/**
+ * Initialize the network interface monitoring list.
+ */
+static CAResult_t CAIPInitializeNetworkMonitorList();
+
+/**
+ * Destroy the network interface monitoring list.
+ */
+static void CAIPDestroyNetworkMonitorList();
+
+/**
+ * Compare the interface with the already added interface in list.
+ */
+static bool CACmpNetworkList(uint32_t ifiindex);
+
+/**
+ * Add new network interface in list.
+ */
+static CAResult_t CAAddNetworkMonitorList(CAInterface_t *ifitem);
+
+/**
+ * Remove network interface from list.
+ */
+static void CARemoveNetworkMonitorList(int ifiindex);
+
+/**
+ * Pass the changed network status through the stored callback.
+ */
+static void CAIPPassNetworkChangesToAdapter(CANetworkStatus_t status);
+
+/**
+ * Create new interface item.
+ */
+static CAInterface_t *CANewInterfaceItem(int index, const char *name, int family,
+                                         const char *addr, int flags);
+
+static CAResult_t CAIPInitializeNetworkMonitorList()
+{
+    if (!g_networkMonitorContextMutex)
+    {
+        g_networkMonitorContextMutex = oc_mutex_new();
+        if (!g_networkMonitorContextMutex)
+        {
+            OIC_LOG(ERROR, TAG, "oc_mutex_new has failed");
+            return CA_STATUS_FAILED;
+        }
+    }
+
+    if (!g_netInterfaceList)
+    {
+        g_netInterfaceList = u_arraylist_create();
+        if (!g_netInterfaceList)
+        {
+            OIC_LOG(ERROR, TAG, "u_arraylist_create has failed");
+            CAIPDestroyNetworkMonitorList();
+            return CA_STATUS_FAILED;
+        }
+    }
+    return CA_STATUS_OK;
+}
+
+static void CAIPDestroyNetworkMonitorList()
+{
+    if (g_netInterfaceList)
+    {
+        u_arraylist_destroy(g_netInterfaceList);
+        g_netInterfaceList = NULL;
+    }
+
+    if (g_networkMonitorContextMutex)
+    {
+        oc_mutex_free(g_networkMonitorContextMutex);
+        g_networkMonitorContextMutex = NULL;
+    }
+}
+
+static bool CACmpNetworkList(uint32_t ifiindex)
+{
+#if NETWORK_INTERFACE_CHANGED_LOGGING
+    OIC_LOG_V(DEBUG, TAG, "IN %s: ifiindex = %ul", __func__, ifiindex);
+#endif
+    if (!g_netInterfaceList)
+    {
+        OIC_LOG(ERROR, TAG, "g_netInterfaceList is NULL");
+        return false;
+    }
+
+    oc_mutex_lock(g_networkMonitorContextMutex);
+
+    size_t list_length = u_arraylist_length(g_netInterfaceList);
+    for (size_t list_index = 0; list_index < list_length; list_index++)
+    {
+        CAInterface_t *currItem = (CAInterface_t *) u_arraylist_get(g_netInterfaceList,
+                                                                    list_index);
+        if (currItem->index == ifiindex)
+        {
+            oc_mutex_unlock(g_networkMonitorContextMutex);
+            return true;
+        }
+    }
+    oc_mutex_unlock(g_networkMonitorContextMutex);
+    OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
+    return false;
+}
+
+static CAResult_t CAAddNetworkMonitorList(CAInterface_t *ifitem)
+{
+    OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
+    VERIFY_NON_NULL(g_netInterfaceList, TAG, "g_netInterfaceList is NULL");
+    VERIFY_NON_NULL(ifitem, TAG, "ifitem is NULL");
+
+    oc_mutex_lock(g_networkMonitorContextMutex);
+    bool result = u_arraylist_add(g_netInterfaceList, (void *) ifitem);
+    if (!result)
+    {
+        OIC_LOG(ERROR, TAG, "u_arraylist_add failed.");
+        oc_mutex_unlock(g_networkMonitorContextMutex);
+        return CA_STATUS_FAILED;
+    }
+    oc_mutex_unlock(g_networkMonitorContextMutex);
+    OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
+    return CA_STATUS_OK;
+}
+
+static void CARemoveNetworkMonitorList(int ifiindex)
+{
+    VERIFY_NON_NULL_VOID(g_netInterfaceList, TAG, "g_netInterfaceList is NULL");
+
+    oc_mutex_lock(g_networkMonitorContextMutex);
+
+    size_t list_length = u_arraylist_length(g_netInterfaceList);
+    for (size_t list_index = 0; list_index < list_length; list_index++)
+    {
+        CAInterface_t *removedifitem = (CAInterface_t *) u_arraylist_get(
+                g_netInterfaceList, list_index);
+        if (removedifitem && ((int)removedifitem->index) == ifiindex)
+        {
+            if (u_arraylist_remove(g_netInterfaceList, list_index))
+            {
+                OICFree(removedifitem);
+                oc_mutex_unlock(g_networkMonitorContextMutex);
+                return;
+            }
+            continue;
+        }
+    }
+    oc_mutex_unlock(g_networkMonitorContextMutex);
+    return;
+}
+
+static bool get_connection_status_cb(LSHandle *sh, LSMessage *message, void *ctx)
+{
+    OIC_LOG(DEBUG, TAG, "Callback for com.webos.service.connectionmanager/getstatus is invoked...");
+
+    jvalue_ref parsedObj = {0};
+    jschema_ref input_schema = jschema_parse(j_cstr_to_buffer("{}"), DOMOPT_NOOPT, NULL);
+
+    if (!input_schema)
+        return false;
+
+    JSchemaInfo schemaInfo;
+    jschema_info_init(&schemaInfo, input_schema, NULL, NULL);
+    parsedObj = jdom_parse(j_cstr_to_buffer(LSMessageGetPayload(message)), DOMOPT_NOOPT, &schemaInfo);
+    jschema_release(&input_schema);
+
+    if (jis_null(parsedObj))
+        return true;
+
+    const char *payload = jvalue_tostring(parsedObj, input_schema);
+
+    OIC_LOG_V(DEBUG, TAG, "Paylod: %s", payload);
+
+    jvalue_ref wiredObj={0}, wifiObj ={0}, wiredStateObj={0}, wifiStateObj={0};
+
+    if (jobject_get_exists(parsedObj, J_CSTR_TO_BUF("wired"), &wiredObj))
+    {
+        if (jobject_get_exists(wiredObj, J_CSTR_TO_BUF("state"), &wiredStateObj))
+        {
+            if (jstring_equal2(wiredStateObj, J_CSTR_TO_BUF("connected")) && !gConnectionStates.isConnectWired)
+            {
+                gConnectionStates.isConnectWired = true;
+                CAIPPassNetworkChangesToAdapter(CA_INTERFACE_UP);
+                OIC_LOG(INFO, TAG, "Wired LAN is connected...");
+            }
+            else if (jstring_equal2(wiredStateObj, J_CSTR_TO_BUF("disconnected")) && gConnectionStates.isConnectWired)
+            {
+                gConnectionStates.isConnectWired = false;
+                CAIPPassNetworkChangesToAdapter(CA_INTERFACE_DOWN);
+                OIC_LOG(INFO, TAG, "Wired LAN is disconnected...");
+            }
+        }
+    }
+
+    if (jobject_get_exists(parsedObj, J_CSTR_TO_BUF("wifi"), &wifiObj))
+    {
+        if (jobject_get_exists(wifiObj, J_CSTR_TO_BUF("state"), &wifiStateObj))
+        {
+            if (jstring_equal2(wifiStateObj, J_CSTR_TO_BUF("connected")) && !gConnectionStates.isConnectWiFi)
+            {
+                gConnectionStates.isConnectWiFi = true;
+                CAIPPassNetworkChangesToAdapter(CA_INTERFACE_UP);
+                OIC_LOG(INFO, TAG, "Wi-Fi is connected...");
+            }
+            else if (jstring_equal2(wifiStateObj, J_CSTR_TO_BUF("disconnected")) && gConnectionStates.isConnectWiFi)
+            {
+                gConnectionStates.isConnectWiFi = false;
+                CAIPPassNetworkChangesToAdapter(CA_INTERFACE_DOWN);
+                OIC_LOG(DEBUG, TAG, "Wi-Fi is disconnected...");
+            }
+        }
+    }
+
+    return true;
+}
+
+static void CANetworkMonitorHandler()
+{
+    OIC_LOG(DEBUG, TAG, "CANetworkMonitorHandler");
+    LSError lserror;
+    LSErrorInit(&lserror);
+
+    if (!CAGetLSHandle())
+    {
+        OIC_LOG(ERROR, TAG, "Luna service handle is null");
+        exit(1);
+    }
+
+    if(!LSCall(CAGetLSHandle(), LS_CONNECTIONMANAGER_GETSTATUS_URI,
+                            "{\"subscribe\":true}",
+                            get_connection_status_cb, NULL, NULL, &lserror))
+    {
+        OIC_LOG(ERROR, TAG, "com.webos.service.connectionmanager/getstatus failed");
+        LSErrorPrint(&lserror, stderr);
+    }
+    else
+    {
+        OIC_LOG(INFO, TAG, "com.webos.service.connectionmanager/getstatus succeeds");
+    }
+}
+
+CAResult_t CAIPStartNetworkMonitor(CAIPAdapterStateChangeCallback callback,
+                                   CATransportAdapter_t adapter)
+{
+    CAResult_t res = CA_STATUS_FAILED;
+
+    res = CAInitializeLS(g_ipMonitorThreadPool);
+    if (CA_STATUS_OK != res)
+    {
+        OIC_LOG(ERROR, TAG, "Failed to register LS in IP monitor");
+        return res;
+    }
+
+    CANetworkMonitorHandler();
+
+    res = CAIPInitializeNetworkMonitorList();
+    if (CA_STATUS_OK == res)
+    {
+        return CAIPSetNetworkMonitorCallback(callback, adapter);
+    }
+
+    return res;
+}
+
+CAResult_t CAIPStopNetworkMonitor(CATransportAdapter_t adapter)
+{
+    gboolean ret = false;
+    LSError lserror;
+    LSErrorInit(&lserror);
+
+    CAIPDestroyNetworkMonitorList();
+
+    CATerminateLS();
+
+    return CAIPUnSetNetworkMonitorCallback(adapter);
+}
+
+int CAGetPollingInterval(int interval)
+{
+    return interval;
+}
+
+static void CAIPPassNetworkChangesToAdapter(CANetworkStatus_t status)
+{
+    OIC_LOG_V(DEBUG, TAG, "IN %s: status = %d", __func__, status);
+    CAIPCBData_t *cbitem = NULL;
+    LL_FOREACH(g_adapterCallbackList, cbitem)
+    {
+        if (cbitem && cbitem->adapter)
+        {
+            cbitem->callback(cbitem->adapter, status);
+            CALogAdapterStateInfo(cbitem->adapter, status);
+        }
+    }
+    OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
+}
+
+CAResult_t CAIPSetNetworkMonitorCallback(CAIPAdapterStateChangeCallback callback,
+                                         CATransportAdapter_t adapter)
+{
+    if (!callback)
+    {
+        OIC_LOG(ERROR, TAG, "callback is null");
+        return CA_STATUS_INVALID_PARAM;
+    }
+
+    CAIPCBData_t *cbitem = NULL;
+    LL_FOREACH(g_adapterCallbackList, cbitem)
+    {
+        if (cbitem && adapter == cbitem->adapter && callback == cbitem->callback)
+        {
+            OIC_LOG(DEBUG, TAG, "this callback is already added");
+            return CA_STATUS_OK;
+        }
+    }
+
+    cbitem = (CAIPCBData_t *)OICCalloc(1, sizeof(*cbitem));
+    if (!cbitem)
+    {
+        OIC_LOG(ERROR, TAG, "Malloc failed");
+        return CA_STATUS_FAILED;
+    }
+
+    cbitem->adapter = adapter;
+    cbitem->callback = callback;
+    LL_APPEND(g_adapterCallbackList, cbitem);
+
+    return CA_STATUS_OK;
+}
+
+CAResult_t CAIPUnSetNetworkMonitorCallback(CATransportAdapter_t adapter)
+{
+    CAIPCBData_t *cbitem = NULL;
+    CAIPCBData_t *tmpCbitem = NULL;
+    LL_FOREACH_SAFE(g_adapterCallbackList, cbitem, tmpCbitem)
+    {
+        if (cbitem && adapter == cbitem->adapter)
+        {
+            OIC_LOG(DEBUG, TAG, "remove specific callback");
+            LL_DELETE(g_adapterCallbackList, cbitem);
+            OICFree(cbitem);
+            return CA_STATUS_OK;
+        }
+    }
+    return CA_STATUS_OK;
+}
+
+static CAInterface_t *CANewInterfaceItem(int index, const char *name, int family,
+                                         const char *addr, int flags)
+{
+    OIC_LOG_V(DEBUG, TAG, "IN %s:"
+              "index = %d, name = \"%s\", family = %d, addr = \"%s\", flags = %d",
+              __func__, index, name, family, addr, flags);
+    CAInterface_t *ifitem = (CAInterface_t *)OICCalloc(1, sizeof (CAInterface_t));
+    if (!ifitem)
+    {
+        OIC_LOG(ERROR, TAG, "Malloc failed");
+        return NULL;
+    }
+
+    OICStrcpy(ifitem->name, sizeof (ifitem->name), name);
+    ifitem->index = index;
+    ifitem->family = family;
+    OICStrcpy(ifitem->addr, sizeof (ifitem->addr), addr);
+    ifitem->flags = flags;
+
+    OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
+    return ifitem;
+}
+
+u_arraylist_t *CAFindInterfaceChange()
+{
+    u_arraylist_t *iflist = NULL;
+    char buf[4096] = { 0 };
+    struct nlmsghdr *nh = NULL;
+    struct sockaddr_nl sa = { .nl_family = 0 };
+    struct iovec iov = { .iov_base = buf,
+                         .iov_len = sizeof (buf) };
+    struct msghdr msg = { .msg_name = (void *)&sa,
+                          .msg_namelen = sizeof (sa),
+                          .msg_iov = &iov,
+                          .msg_iovlen = 1 };
+
+    ssize_t len = recvmsg(caglobals.ip.netlinkFd, &msg, 0);
+
+    for (nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, len); nh = NLMSG_NEXT(nh, len))
+    {
+        if (nh != NULL && (nh->nlmsg_type != RTM_DELADDR && nh->nlmsg_type != RTM_NEWADDR))
+        {
+            continue;
+        }
+
+        if (RTM_DELADDR == nh->nlmsg_type)
+        {
+            struct ifaddrmsg *ifa = (struct ifaddrmsg *)NLMSG_DATA (nh);
+            if (ifa)
+            {
+                int ifiIndex = ifa->ifa_index;
+                bool isFound = CACmpNetworkList(ifiIndex);
+                if (isFound)
+                {
+                    CARemoveNetworkMonitorList(ifiIndex);
+                }
+            }
+            continue;
+        }
+
+        // Netlink message type is RTM_NEWADDR.
+        struct ifaddrmsg *ifa = (struct ifaddrmsg *)NLMSG_DATA (nh);
+        if (ifa)
+        {
+            int ifiIndex = ifa->ifa_index;
+            iflist = CAIPGetInterfaceInformation(ifiIndex);
+            if (!iflist)
+            {
+                OIC_LOG_V(ERROR, TAG, "get interface info failed: %s", strerror(errno));
+                return NULL;
+            }
+        }
+    }
+    return iflist;
+}
+
+u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex)
+{
+#if NETWORK_INTERFACE_CHANGED_LOGGING
+    OIC_LOG_V(DEBUG, TAG, "IN %s: desiredIndex = %d", __func__, desiredIndex);
+#endif
+    if (desiredIndex < 0)
+    {
+        OIC_LOG_V(ERROR, TAG, "invalid index : %d", desiredIndex);
+        return NULL;
+    }
+
+    u_arraylist_t *iflist = u_arraylist_create();
+    if (!iflist)
+    {
+        OIC_LOG_V(ERROR, TAG, "Failed to create iflist: %s", strerror(errno));
+        return NULL;
+    }
+
+    struct ifaddrs *ifp = NULL;
+    if (-1 == getifaddrs(&ifp))
+    {
+        OIC_LOG_V(ERROR, TAG, "Failed to get ifaddrs: %s", strerror(errno));
+        u_arraylist_destroy(iflist);
+        return NULL;
+    }
+
+    struct ifaddrs *ifa = NULL;
+#if NETWORK_INTERFACE_CHANGED_LOGGING
+    OIC_LOG(DEBUG, TAG, "Iterating over interface addresses.");
+#endif
+    for (ifa = ifp; ifa; ifa = ifa->ifa_next)
+    {
+        if (!ifa->ifa_addr)
+        {
+            continue;
+        }
+        int family = ifa->ifa_addr->sa_family;
+        if ((ifa->ifa_flags & IFF_LOOPBACK) || (AF_INET != family && AF_INET6 != family))
+        {
+            continue;
+        }
+
+        int ifindex = if_nametoindex(ifa->ifa_name);
+        if (desiredIndex && (ifindex != desiredIndex))
+        {
+            continue;
+        }
+
+        size_t length = u_arraylist_length(iflist);
+        int already = false;
+#if NETWORK_INTERFACE_CHANGED_LOGGING
+        OIC_LOG_V(DEBUG, TAG, "Iterating over %" PRIuPTR " interfaces.", length);
+#endif
+        for (size_t i = 0; i < length; i++)
+        {
+#if NETWORK_INTERFACE_CHANGED_LOGGING
+            OIC_LOG_V(DEBUG, TAG, "Checking interface %" PRIuPTR ".", i);
+#endif
+            CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i);
+
+            if (ifitem
+                && (int)ifitem->index == ifindex
+                && ifitem->family == (uint16_t)family)
+            {
+                already = true;
+                break;
+            }
+        }
+        if (already)
+        {
+            continue;
+        }
+
+        CAInterface_t *ifitem = (CAInterface_t *)OICCalloc(1, sizeof(CAInterface_t));
+        if (!ifitem)
+        {
+            OIC_LOG(ERROR, TAG, "Malloc failed");
+            goto exit;
+        }
+
+        OICStrcpy(ifitem->name, INTERFACE_NAME_MAX, ifa->ifa_name);
+        ifitem->index = ifindex;
+        ifitem->family = family;
+        ifitem->flags = ifa->ifa_flags;
+
+        if (ifitem->family == AF_INET6)
+        {
+            struct sockaddr_in6 *in6 = (struct sockaddr_in6*) ifa->ifa_addr;
+            inet_ntop(ifitem->family, (void *)&(in6->sin6_addr), ifitem->addr,
+                      sizeof(ifitem->addr));
+        }
+        else if (ifitem->family == AF_INET)
+        {
+            struct sockaddr_in *in = (struct sockaddr_in*) ifa->ifa_addr;
+            inet_ntop(ifitem->family, (void *)&(in->sin_addr), ifitem->addr,
+                      sizeof(ifitem->addr));
+        }
+
+        bool result = u_arraylist_add(iflist, ifitem);
+        if (!result)
+        {
+            OIC_LOG(ERROR, TAG, "u_arraylist_add failed.");
+            goto exit;
+        }
+
+        bool isFound = CACmpNetworkList(ifitem->index);
+        if (!isFound)
+        {
+            CAInterface_t *newifitem = CANewInterfaceItem(ifitem->index, ifitem->name, ifitem->family,
+                                                          ifitem->addr, ifitem->flags);
+            CAResult_t ret = CAAddNetworkMonitorList(newifitem);
+            if (CA_STATUS_OK != ret)
+            {
+                OICFree(newifitem);
+                goto exit;
+            }
+            OIC_LOG_V(DEBUG, TAG, "Added interface: %s (%d)", ifitem->name, ifitem->family);
+        }
+    }
+    freeifaddrs(ifp);
+#if NETWORK_INTERFACE_CHANGED_LOGGING
+    OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
+#endif
+    return iflist;
+
+exit:
+    freeifaddrs(ifp);
+    u_arraylist_destroy(iflist);
+#if NETWORK_INTERFACE_CHANGED_LOGGING
+    OIC_LOG_V(DEBUG, TAG, "OUT %s", __func__);
+#endif
+    return NULL;
+}
+
+CAResult_t CAGetLinkLocalZoneIdInternal(uint32_t ifindex, char **zoneId)
+{
+    if (!zoneId || (*zoneId != NULL))
+    {
+        return CA_STATUS_INVALID_PARAM;
+    }
+
+    *zoneId = (char *)OICCalloc(IF_NAMESIZE, sizeof(char));
+    if (!(*zoneId))
+    {
+        OIC_LOG(ERROR, TAG, "OICCalloc failed in CAGetLinkLocalZoneIdInternal");
+        return CA_MEMORY_ALLOC_FAILED;
+    }
+
+    if (!if_indextoname(ifindex, *zoneId))
+    {
+        OIC_LOG(ERROR, TAG, "if_indextoname failed in CAGetLinkLocalZoneIdInternal");
+        OICFree(*zoneId);
+        *zoneId = NULL;
+        return CA_STATUS_FAILED;
+    }
+
+    OIC_LOG_V(DEBUG, TAG, "Given ifindex is %d parsed zoneId is %s", ifindex, *zoneId);
+    return CA_STATUS_OK;
+}
+
+void CAIPSetMonitorThreadPoolHandle(ca_thread_pool_t handle)
+{
+    g_ipMonitorThreadPool = handle;
+}
index 62e4f5e..06b6116 100644 (file)
@@ -32,6 +32,11 @@ else:
 if env.get('OIC_SUPPORT_TIZEN_TRACE') == 'True':
     env.AppendUnique(CPPDEFINES=['OIC_SUPPORT_TIZEN_TRACE'])
 
+if env.get('TARGET_OS') == 'webos':
+    env.AppendUnique(CPPDEFINES=['__webos__'])
+    env.ParseConfig("pkg-config --cflags --libs PmLogLib")
+    env.ParseConfig("pkg-config --cflags --libs glib-2.0")
+
 local_env = env.Clone()
 
 ######################################################################
@@ -41,7 +46,7 @@ logger_src = ['./src/logger.c', './src/trace.c']
 
 loggerlib = local_env.StaticLibrary('logger', logger_src)
 local_env.InstallTarget(loggerlib, 'logger')
-local_env.UserInstallTargetHeader('include/experimental/logger_types.h', 
+local_env.UserInstallTargetHeader('include/experimental/logger_types.h',
                                   'c_common/experimental', 'logger_types.h')
 local_env.UserInstallTargetHeader('include/experimental/logger.h',
                                   'c_common/experimental', 'logger.h')
index bccb5fe..a55a0a4 100644 (file)
 #include "string.h"
 #include "experimental/logger_types.h"
 
+#ifdef __webos__
+#include <PmLogLib.h>
+#include <glib.h>
+
+PmLogContext gLogLibContext;
+#endif // __webos__
+
 // log level
 static int g_level = DEBUG;
 // private log messages are not logged unless they have been explicitly enabled by calling OCSetLogLevel().
@@ -86,10 +93,12 @@ static oc_log_level LEVEL_XTABLE[] = {OC_LOG_DEBUG, OC_LOG_INFO,
     static android_LogPriority LEVEL[] =
     {ANDROID_LOG_DEBUG, ANDROID_LOG_INFO, ANDROID_LOG_WARN, ANDROID_LOG_ERROR, ANDROID_LOG_FATAL};
 #endif
-#elif defined(__linux__) || defined(__APPLE__) || defined(__msys_nt__)
+#elif (defined(__linux__) && !defined(__webos__)) || defined(__APPLE__) || defined(__msys_nt__)
     static const char * LEVEL[] __attribute__ ((unused)) = {"\e[0;32mDEBUG\033[0m", "\e[0;33mINFO\033[0m", "\e[0;35mWARNING\033[0m", "\e[0;31mERROR\033[0m", "\e[0;31mFATAL\033[0m"};
 #elif defined(_MSC_VER)
     static const char * LEVEL[] = {"DEBUG", "INFO", "WARNING", "ERROR", "FATAL"};
+#elif defined (__linux__) && (__webos__)
+    static const char * LEVEL[] = {"DEBUG", "INFO", "WARNING", "ERROR", "FATAL"};
 #elif defined ARDUINO
 #include <stdarg.h>
 #include "Arduino.h"
@@ -149,6 +158,78 @@ static bool AdjustAndVerifyLogLevel(int* level)
     return true;
 }
 
+#ifdef __webos__
+char *replaceValue(char *strInput, const char *strTarget, const char *strChange)
+{
+    char* strResult;
+    char* strTemp;
+    int i = 0;
+    int nCount = 0;
+    int nTargetLength = strlen(strTarget);
+
+    if (nTargetLength < 1)
+        return strInput;
+
+    int nChangeLength = strlen(strChange);
+
+    if (nChangeLength != nTargetLength)
+    {
+        for (i = 0; strInput[i] != '\0';)
+        {
+            if (memcmp(&strInput[i], strTarget, nTargetLength) == 0)
+            {
+                nCount++;
+                i += nTargetLength;
+            }
+            else i++;
+        }
+    }
+    else
+    {
+        i = strlen(strInput);
+    }
+    strResult = (char *) malloc(i + 1 + nCount * (nChangeLength - nTargetLength));
+    if (strResult == NULL) return NULL;
+
+    strTemp = strResult;
+    while (*strInput)
+    {
+        if (memcmp(strInput, strTarget, nTargetLength) == 0)
+        {
+            memcpy(strTemp, strChange, nChangeLength);
+            strTemp += nChangeLength;
+            strInput  += nTargetLength;
+        }
+        else
+        {
+            *strTemp++ = *strInput++;
+        }
+    }
+
+    *strTemp = '\0';
+
+    return strResult;
+}
+
+static void webos_log_write(PmLogContext context, int level, const char *tag, const char *logStr)
+{
+    char *strResult = NULL;
+    strResult = replaceValue(logStr, "\t", "    ");
+
+    if (!g_strcmp0(LEVEL[level], "DEBUG"))
+        PmLogDebug(context, "%s: %s", tag, strResult);
+    else if (!g_strcmp0(LEVEL[level], "INFO"))
+        PmLogInfo(context, "INFO", 0, "%s: %s", tag, strResult);
+    else if (!g_strcmp0(LEVEL[level], "WARNING"))
+        PmLogWarning(context, "WARNING", 0, "%s: %s", tag, strResult);
+    else if (!g_strcmp0(LEVEL[level], "ERROR"))
+        PmLogError(context, "ERROR", 0, "%s: %s", tag, strResult);
+    else if (!g_strcmp0(LEVEL[level], "FATAL"))
+        PmLogCritical(context, "CRITICAL", 0, "%s: %s", tag, strResult);
+    free(strResult);
+}
+#endif // __webos__
+
 #ifndef ARDUINO
 
 /**
@@ -282,6 +363,11 @@ void OCLog(int level, const char * tag, const char * logStr)
             break;
     }
 
+   #ifdef __webos__
+    PmLogGetContext("IoTivity", &gLogLibContext);
+    webos_log_write(gLogLibContext, level, tag, logStr);
+   #endif // __webos__
+
    #ifdef __ANDROID__
 
    #ifdef ADB_SHELL
@@ -289,7 +375,6 @@ void OCLog(int level, const char * tag, const char * logStr)
    #else
        __android_log_write(LEVEL[level], tag, logStr);
    #endif
-
    #else
        if (logCtx && logCtx->write_level)
        {
@@ -328,10 +413,13 @@ void OCLog(int level, const char * tag, const char * logStr)
                ms = now.tv_usec * 1000;
            }
    #endif
+   #ifdef __webos__
+   #else
            printf("%02d:%02d.%03d %s: %s: %s\n", min, sec, ms, LEVEL[level], tag, logStr);
-       }
-   #endif
-   }
+   #endif // __webos__
+    }
+   #endif // __ANDROID__
+}
 #endif //__TIZEN__
 #endif //ARDUINO
 #ifdef ARDUINO
index 8f79b70..136c94f 100644 (file)
@@ -70,7 +70,7 @@ if target_os == 'android':
     if not env.get('RELEASE'):
         rd_env.AppendUnique(LIBS=['log'])
 
-if target_os in ['linux', 'tizen']:
+if target_os in ['linux', 'tizen', 'webos']:
     rd_env.ParseConfig('pkg-config --cflags --libs sqlite3')
 else:
     rd_env.AppendUnique(CPPPATH=['../../../extlibs/sqlite3'])
@@ -90,7 +90,7 @@ if 'SERVER' in rd_mode:
         RD_SRC_DIR + 'internal/rd_database.c',
         RD_SRC_DIR + 'rd_server.c',
     ]
-    if target_os not in ['linux', 'tizen', 'windows']:
+    if target_os not in ['linux', 'tizen', 'windows', 'webos']:
         rd_src_c += ['../../../extlibs/sqlite3/sqlite3.c']
 
 if 'CLIENT' in rd_mode:
index e83811a..779faca 100644 (file)
@@ -62,10 +62,10 @@ if target_os in ['windows', 'msys_nt']:
     libocsrm_env.AppendUnique(CCFLAGS=['/W4'])
 
 if libocsrm_env.get('SECURED') == '1':
-    if target_os in ['linux', 'android', 'tizen', 'msys_nt', 'windows', 'ios']:
+    if target_os in ['linux', 'android', 'tizen', 'msys_nt', 'windows', 'ios', 'webos']:
         SConscript('provisioning/SConscript', 'libocsrm_env')
 
-    if target_os in ['linux', 'tizen', 'windows', 'darwin']:
+    if target_os in ['linux', 'tizen', 'windows', 'darwin', 'webos']:
         SConscript('tool/SConscript', 'libocsrm_env')
 
 if target_os not in ['windows']:
@@ -87,6 +87,11 @@ if env.get('LOGGING'):
 if env.get('MULTIPLE_OWNER') == '1':
     libocsrm_env.AppendUnique(CPPDEFINES=['MULTIPLE_OWNER'])
 
+if target_os in ['webos']:
+    libocsrm_env.ParseConfig("pkg-config --cflags --libs glib-2.0")
+    libocsrm_env.ParseConfig("pkg-config --cflags --libs luna-service2")
+    libocsrm_env.ParseConfig("pkg-config --cflags --libs pbnjson_c")
+
 ######################################################################
 # Source files and Targets
 ######################################################################
index 1dd304c..74777f0 100644 (file)
@@ -85,7 +85,7 @@ if provisioning_lib_env.get('WITH_TCP') == True and provisioning_lib_env.get('WI
         'cloud/config.c'
     ]
 
-if target_os in ['linux', 'tizen']:
+if target_os in ['linux', 'tizen', 'webos']:
     provisioning_lib_env.ParseConfig('pkg-config --cflags --libs sqlite3')
 else:
     provisioning_lib_env.AppendUnique(CPPPATH=['#/extlibs/sqlite3'])
index ca15187..15ce174 100644 (file)
@@ -102,7 +102,7 @@ if env.get('SECURED') == '1':
 # c_common calls into mbedcrypto.
 liboctbstack_env.AppendUnique(LIBS=['mbedcrypto'])
 
-if target_os in ['android', 'linux', 'tizen', 'msys_nt', 'windows']:
+if target_os in ['android', 'linux', 'tizen', 'msys_nt', 'windows', 'webos']:
     if target_os not in ['windows', 'msys_nt']:
         liboctbstack_env.PrependUnique(LIBS=['connectivity_abstraction'])
     else:
@@ -185,7 +185,7 @@ else:
             liboctbstack_env.Textfile(
                 target='octbstack.def', source=[File('octbstack_temp3.def')])
 
-if target_os in ['tizen', 'linux']:
+if target_os in ['tizen', 'linux', 'webos']:
     liboctbstack_env.ParseConfig("pkg-config --cflags --libs uuid")
     liboctbstack_env.ParseConfig('pkg-config --cflags --libs sqlite3')
 
@@ -216,7 +216,7 @@ if 'CLIENT' in rd_mode or 'SERVER' in rd_mode:
 
     if 'SERVER' in rd_mode:
         liboctbstack_env.AppendUnique(CPPDEFINES=['RD_SERVER'])
-        if target_os not in ['tizen']:
+        if target_os not in ['tizen', 'webos']:
             # tizen added via pkg-config above
             liboctbstack_env.AppendUnique(CPPPATH=['#/extlibs/sqlite3'])
 
@@ -245,7 +245,7 @@ if with_tcp == True:
 
 if 'SERVER' in rd_mode:
     liboctbstack_src.append(OCTBSTACK_SRC + 'oicresourcedirectory.c')
-    if target_os not in ['linux', 'tizen', 'windows']:
+    if target_os not in ['linux', 'tizen', 'windows', 'webos']:
         liboctbstack_src.append('#extlibs/sqlite3/sqlite3.c')
 
 if ((target_os in ['windows']) and (liboctbstack_env.get('MSVC_UWP_APP') == '1')):
index 36f28fe..e8039ec 100644 (file)
@@ -36,3 +36,8 @@ elif target_os == 'darwin':
 elif target_os == 'msys_nt':
     # Build secure samples. Using linux samples for now.
     SConscript('linux/secure/SConscript', 'stacksamples_env')
+elif target_os == 'webos':
+    if stacksamples_env.get('SECURED') == '1':
+        SConscript('webos/secure/SConscript', 'stacksamples_env')
+    else:
+        SConscript('webos/unsecure/SConscript', 'stacksamples_env')
diff --git a/resource/csdk/stack/samples/webos/com.example.app.iotivity/appinfo.json b/resource/csdk/stack/samples/webos/com.example.app.iotivity/appinfo.json
new file mode 100644 (file)
index 0000000..e276121
--- /dev/null
@@ -0,0 +1,11 @@
+{
+    "id": "com.example.app.iotivity",
+    "version": "1.0.0",
+    "vendor": "LGE",
+    "type": "web",
+    "main": "index.html",
+    "title": "IOTIVITY SAMPLER",
+    "icon": "icon.png",
+    "uiRevision": 2,
+    "requiredPermissions": ["all"]
+}
\ No newline at end of file
diff --git a/resource/csdk/stack/samples/webos/com.example.app.iotivity/npm-shrinkwrap.json b/resource/csdk/stack/samples/webos/com.example.app.iotivity/npm-shrinkwrap.json
new file mode 100644 (file)
index 0000000..097210d
--- /dev/null
@@ -0,0 +1,258 @@
+{
+  "name": "com.example.app.iotivity",
+  "version": "1.0.0",
+  "dependencies": {
+    "@enact/core": {
+      "version": "1.15.0",
+      "from": "@enact/core@^1.8.0",
+      "resolved": "https://registry.npmjs.org/@enact/core/-/core-1.15.0.tgz"
+    },
+    "@enact/i18n": {
+      "version": "1.15.0",
+      "from": "@enact/i18n@^1.8.0",
+      "resolved": "https://registry.npmjs.org/@enact/i18n/-/i18n-1.15.0.tgz"
+    },
+    "@enact/moonstone": {
+      "version": "1.15.0",
+      "from": "@enact/moonstone@^1.8.0",
+      "resolved": "https://registry.npmjs.org/@enact/moonstone/-/moonstone-1.15.0.tgz"
+    },
+    "@enact/spotlight": {
+      "version": "1.15.0",
+      "from": "@enact/spotlight@^1.8.0",
+      "resolved": "https://registry.npmjs.org/@enact/spotlight/-/spotlight-1.15.0.tgz"
+    },
+    "@enact/ui": {
+      "version": "1.15.0",
+      "from": "@enact/ui@^1.8.0",
+      "resolved": "https://registry.npmjs.org/@enact/ui/-/ui-1.15.0.tgz"
+    },
+    "@enact/webos": {
+      "version": "1.15.0",
+      "from": "@enact/webos@^1.8.0",
+      "resolved": "https://registry.npmjs.org/@enact/webos/-/webos-1.15.0.tgz"
+    },
+    "asap": {
+      "version": "2.0.6",
+      "from": "asap@~2.0.3",
+      "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz"
+    },
+    "change-emitter": {
+      "version": "0.1.6",
+      "from": "change-emitter@^0.1.2",
+      "resolved": "https://registry.npmjs.org/change-emitter/-/change-emitter-0.1.6.tgz"
+    },
+    "classnames": {
+      "version": "2.2.5",
+      "from": "classnames@~2.2.5",
+      "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.5.tgz"
+    },
+    "core-js": {
+      "version": "1.2.7",
+      "from": "core-js@^1.0.0",
+      "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz"
+    },
+    "create-react-class": {
+      "version": "15.6.3",
+      "from": "create-react-class@^15.6.0",
+      "resolved": "https://registry.npmjs.org/create-react-class/-/create-react-class-15.6.3.tgz"
+    },
+    "dom-walk": {
+      "version": "0.1.1",
+      "from": "dom-walk@^0.1.0",
+      "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.1.tgz"
+    },
+    "eases": {
+      "version": "1.0.8",
+      "from": "eases@~1.0.8",
+      "resolved": "https://registry.npmjs.org/eases/-/eases-1.0.8.tgz"
+    },
+    "encoding": {
+      "version": "0.1.12",
+      "from": "encoding@^0.1.11",
+      "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz"
+    },
+    "fbjs": {
+      "version": "0.8.16",
+      "from": "fbjs@^0.8.16",
+      "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.16.tgz"
+    },
+    "for-each": {
+      "version": "0.3.2",
+      "from": "for-each@^0.3.2",
+      "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.2.tgz"
+    },
+    "global": {
+      "version": "4.3.2",
+      "from": "global@~4.3.0",
+      "resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz"
+    },
+    "hoist-non-react-statics": {
+      "version": "1.2.0",
+      "from": "hoist-non-react-statics@^1.0.0",
+      "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-1.2.0.tgz"
+    },
+    "iconv-lite": {
+      "version": "0.4.19",
+      "from": "iconv-lite@~0.4.13",
+      "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz"
+    },
+    "invariant": {
+      "version": "2.2.4",
+      "from": "invariant@~2.2.2",
+      "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz"
+    },
+    "is-function": {
+      "version": "1.0.1",
+      "from": "is-function@^1.0.1",
+      "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.1.tgz"
+    },
+    "is-stream": {
+      "version": "1.1.0",
+      "from": "is-stream@^1.0.1",
+      "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz"
+    },
+    "isomorphic-fetch": {
+      "version": "2.2.1",
+      "from": "isomorphic-fetch@^2.1.1",
+      "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz"
+    },
+    "js-tokens": {
+      "version": "3.0.2",
+      "from": "js-tokens@^3.0.0",
+      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz"
+    },
+    "lodash": {
+      "version": "4.17.5",
+      "from": "lodash@^4.17.5",
+      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz"
+    },
+    "lodash-es": {
+      "version": "4.17.7",
+      "from": "lodash-es@^4.17.5",
+      "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.7.tgz"
+    },
+    "loose-envify": {
+      "version": "1.3.1",
+      "from": "loose-envify@^1.0.0",
+      "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz"
+    },
+    "min-document": {
+      "version": "2.19.0",
+      "from": "min-document@^2.19.0",
+      "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz"
+    },
+    "node-fetch": {
+      "version": "1.7.3",
+      "from": "node-fetch@^1.0.1",
+      "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz"
+    },
+    "object-assign": {
+      "version": "4.1.1",
+      "from": "object-assign@^4.1.1",
+      "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz"
+    },
+    "parse-headers": {
+      "version": "2.0.1",
+      "from": "parse-headers@^2.0.0",
+      "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.1.tgz"
+    },
+    "process": {
+      "version": "0.5.2",
+      "from": "process@~0.5.1",
+      "resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz"
+    },
+    "promise": {
+      "version": "7.3.1",
+      "from": "promise@^7.1.1",
+      "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz"
+    },
+    "prop-types": {
+      "version": "15.6.1",
+      "from": "prop-types@^15.5.10",
+      "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.1.tgz"
+    },
+    "ramda": {
+      "version": "0.24.1",
+      "from": "ramda@~0.24.1",
+      "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.24.1.tgz"
+    },
+    "react": {
+      "version": "15.6.2",
+      "from": "react@^15.6.1",
+      "resolved": "https://registry.npmjs.org/react/-/react-15.6.2.tgz"
+    },
+    "react-dom": {
+      "version": "15.6.2",
+      "from": "react-dom@^15.6.1",
+      "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-15.6.2.tgz"
+    },
+    "react-redux": {
+      "version": "5.0.7",
+      "from": "react-redux@^5.0.7",
+      "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-5.0.7.tgz",
+      "dependencies": {
+        "hoist-non-react-statics": {
+          "version": "2.5.0",
+          "from": "hoist-non-react-statics@^2.5.0",
+          "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.5.0.tgz"
+        }
+      }
+    },
+    "recompose": {
+      "version": "0.23.5",
+      "from": "recompose@~0.23.5",
+      "resolved": "https://registry.npmjs.org/recompose/-/recompose-0.23.5.tgz"
+    },
+    "redux": {
+      "version": "3.7.2",
+      "from": "redux@^3.7.2",
+      "resolved": "https://registry.npmjs.org/redux/-/redux-3.7.2.tgz"
+    },
+    "redux-thunk": {
+      "version": "2.2.0",
+      "from": "redux-thunk@^2.2.0",
+      "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.2.0.tgz"
+    },
+    "setimmediate": {
+      "version": "1.0.5",
+      "from": "setimmediate@^1.0.5",
+      "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz"
+    },
+    "symbol-observable": {
+      "version": "1.2.0",
+      "from": "symbol-observable@^1.0.4",
+      "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz"
+    },
+    "trim": {
+      "version": "0.0.1",
+      "from": "trim@0.0.1",
+      "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz"
+    },
+    "ua-parser-js": {
+      "version": "0.7.17",
+      "from": "ua-parser-js@^0.7.9",
+      "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.17.tgz"
+    },
+    "warning": {
+      "version": "3.0.0",
+      "from": "warning@~3.0.0",
+      "resolved": "https://registry.npmjs.org/warning/-/warning-3.0.0.tgz"
+    },
+    "whatwg-fetch": {
+      "version": "2.0.3",
+      "from": "whatwg-fetch@>=0.10.0",
+      "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz"
+    },
+    "xhr": {
+      "version": "2.4.1",
+      "from": "xhr@~2.4.0",
+      "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.4.1.tgz"
+    },
+    "xtend": {
+      "version": "4.0.1",
+      "from": "xtend@^4.0.0",
+      "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz"
+    }
+  }
+}
diff --git a/resource/csdk/stack/samples/webos/com.example.app.iotivity/package.json b/resource/csdk/stack/samples/webos/com.example.app.iotivity/package.json
new file mode 100644 (file)
index 0000000..c09a70a
--- /dev/null
@@ -0,0 +1,45 @@
+{
+  "name": "com.example.app.iotivity",
+  "version": "1.0.0",
+  "description": "iotivity sample app with enact framework",
+  "author": "jy.jeong@lge.com",
+  "main": "src/index.js",
+  "scripts": {
+    "serve": "enact serve",
+    "pack": "enact pack",
+    "pack-p": "enact pack -p",
+    "watch": "enact pack --watch",
+    "clean": "enact clean",
+    "lint": "enact lint .",
+    "license": "enact license",
+    "test": "enact test start --single-run --browsers PhantomJS",
+    "test-json": "enact test start --single-run --browsers PhantomJS --reporters json",
+    "test-watch": "enact test start --browsers PhantomJS"
+  },
+  "license": "LGE",
+  "private": true,
+  "repository": "",
+  "enact": {
+    "isomorphic": true,
+    "ri": {
+      "baseSize": 24
+    }
+  },
+  "eslintConfig": {
+    "extends": "enact"
+  },
+  "dependencies": {
+    "@enact/core": "^1.8.0",
+    "@enact/i18n": "^1.8.0",
+    "@enact/moonstone": "^1.8.0",
+    "@enact/spotlight": "^1.8.0",
+    "@enact/ui": "^1.8.0",
+    "@enact/webos": "^1.8.0",
+    "prop-types": "^15.5.10",
+    "react": "^15.6.1",
+    "react-dom": "^15.6.1",
+    "react-redux": "^5.0.7",
+    "redux": "^3.7.2",
+    "redux-thunk": "^2.2.0"
+  }
+}
diff --git a/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.client/client-lowlevel.js b/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.client/client-lowlevel.js
new file mode 100644 (file)
index 0000000..590c7c6
--- /dev/null
@@ -0,0 +1,249 @@
+/* ******************************************************************
+ *
+ * Copyright (c) 2018 LG Electronics, Inc.
+ *
+ *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ *
+ * 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
+ *
+ *      https://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.
+ *
+ *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+var intervalId, handleReceptacle = {}, iotivity = require("iotivity-node/lowlevel");
+var StorageHandler = require("iotivity-node/lib/CustomStorageHandler");
+var observeHandles = [];
+var observeCount = 0;
+
+returnNoResponse = function(callback) {
+    setTimeout(function() {
+        console.log("No response");
+        callback({});
+        clearInterval( intervalId );
+        iotivity.OCStop();
+    }, 5000, null);
+};
+
+function assembleRequestUrl( eps, path ) {
+    var endpoint;
+    var endpointIndex;
+    var result;
+    for ( endpointIndex in eps ) {
+        endpoint = eps[ endpointIndex ];
+        if ( endpoint.tps  === "coaps" ) {
+            result = ( endpoint.tps + "://" +
+            ( endpoint.family & iotivity.OCTransportFlags.OC_IP_USE_V6 ? "[" : "" ) +
+            endpoint.addr.replace( /[%].*$/, "" ) +
+            ( endpoint.family & iotivity.OCTransportFlags.OC_IP_USE_V6 ? "]" : "" ) +
+            ":" + endpoint.port ) + path;
+            console.log( "GET request to " + result );
+            return result;
+        }
+    }
+    throw new Error( "No secure endpoint found!" );
+}
+
+module.exports.startDiscovery = function(callback) {
+
+    console.log("Issuing discovery request");
+
+    iotivity.OCInit(null, 0, iotivity.OCMode.OC_CLIENT );
+    clearInterval( intervalId );
+    intervalId = setInterval(function() {
+        iotivity.OCProcess();
+    }, 1000);
+
+    // Discover resources and list them
+    iotivity.OCDoResource(
+
+        // The bindings fill in this object
+        handleReceptacle,
+
+        iotivity.OCMethod.OC_REST_DISCOVER,
+
+        // Standard path for discovering resources
+        iotivity.OC_MULTICAST_DISCOVERY_URI,
+
+        // There is no destination
+        null,
+
+        // There is no payload
+        null,
+        iotivity.OCConnectivityType.CT_DEFAULT,
+        iotivity.OCQualityOfService.OC_HIGH_QOS,
+        function(handle, response) {
+            console.log("Discovery response: "+ JSON.stringify(response, null, 4));
+            callback(response);
+            return iotivity.OCStackApplicationResult.OC_STACK_KEEP_TRANSACTION;
+        },
+
+        // There are no header options
+        null
+    );
+
+    returnNoResponse(callback);
+};
+
+module.exports.getResource = function(uri, destination, question, callback) {
+
+    console.log("Sending GET request");
+    var getHandleReceptacle = {};
+    var payload = {
+        "type":iotivity.OCPayloadType.PAYLOAD_TYPE_REPRESENTATION,
+        "values":{"question":question}
+    };
+
+    var getResourceHandler = function( handle, response ) {
+        var resources = response && response.payload && response.payload.resources,
+            resourceCount = resources ? resources.length : 0;
+
+        for (var index = 0; index < resourceCount; index++ ) {
+            if ( resources[ index ].uri === uri ) {
+                iotivity.OCDoResource(
+                    getHandleReceptacle,
+                    iotivity.OCMethod.OC_REST_GET,
+                    assembleRequestUrl( resources[ index ].eps, uri),
+                    destination,
+                    payload,
+                    iotivity.OCConnectivityType.CT_DEFAULT,
+                    iotivity.OCQualityOfService.OC_HIGH_QOS,
+                    function( handle, response ){
+                        console.log( "Received response to GET request:" );
+                        console.log( JSON.stringify( response, null, 4 ) );
+                        callback( response );
+                        setTimeout(function() {
+                            clearInterval( intervalId );
+                            iotivity.OCStop();
+                        }, 1000, null);
+                        return iotivity.OCStackApplicationResult.OC_STACK_DELETE_TRANSACTION;
+                    },
+                    null
+                );
+            }
+        }
+        return iotivity.OCStackApplicationResult.OC_STACK_DELETE_TRANSACTION;
+    };
+
+    iotivity.OCRegisterPersistentStorageHandler(StorageHandler("oic_svr_db_client.dat"));
+    iotivity.OCInit(null, 0, iotivity.OCMode.OC_CLIENT_SERVER );
+    clearInterval( intervalId );
+    intervalId = setInterval(function() {
+        iotivity.OCProcess();
+    }, 1000);
+
+    iotivity.OCDoResource(
+        getHandleReceptacle,
+        iotivity.OCMethod.OC_REST_DISCOVER,
+        iotivity.OC_MULTICAST_DISCOVERY_URI,
+        null,
+        null,
+        iotivity.OCConnectivityType.CT_DEFAULT,
+        iotivity.OCQualityOfService.OC_HIGH_QOS,
+        getResourceHandler,
+        null
+    );
+
+    returnNoResponse(callback);
+};
+
+module.exports.deleteResource = function(uri, destination, callback) {
+
+    console.log("Sending DELETE request");
+    var deleteHandleReceptacle = {};
+    var deleteResponseHandler = function( handle, response ) {
+        console.log( "Received response to DELETE request:" );
+        console.log( JSON.stringify( response, null, 4 ) );
+        callback( response );
+        return iotivity.OCStackApplicationResult.OC_STACK_DELETE_TRANSACTION;
+    };
+
+    iotivity.OCRegisterPersistentStorageHandler(StorageHandler("oic_svr_db_client.dat"));
+    iotivity.OCInit(null, 0, iotivity.OCMode.OC_CLIENT_SERVER );
+    clearInterval( intervalId );
+    intervalId = setInterval(function() {
+        iotivity.OCProcess();
+    }, 1000);
+
+    iotivity.OCDoResource(
+        deleteHandleReceptacle,
+        iotivity.OCMethod.OC_REST_DELETE,
+        uri,
+        destination,
+        null,
+        iotivity.OCConnectivityType.CT_DEFAULT,
+        iotivity.OCQualityOfService.OC_HIGH_QOS,
+        deleteResponseHandler,
+        null
+    );
+
+    returnNoResponse(callback);
+};
+
+module.exports.observeResource = function(uri, destination, callback) {
+
+    console.log( "Observing " + uri );
+    var observeHandleReceptacle = {};
+    var observeResponseHandler = function( handle, response ) {
+        console.log( "Received response to OBSERVE request:" );
+        console.log( JSON.stringify( response, null, 4 ) );
+        callback(response);
+        return iotivity.OCStackApplicationResult.OC_STACK_KEEP_TRANSACTION;
+    };
+
+    iotivity.OCRegisterPersistentStorageHandler(StorageHandler("oic_svr_db_client.dat"));
+    iotivity.OCInit(null, 0, iotivity.OCMode.OC_CLIENT_SERVER );
+    clearInterval( intervalId );
+    intervalId = setInterval(function() {
+        iotivity.OCProcess();
+    }, 1000);
+
+    iotivity.OCDoResource(
+        observeHandleReceptacle,
+        iotivity.OCMethod.OC_REST_OBSERVE,
+        uri,
+        destination,
+        null,
+        iotivity.OCConnectivityType.CT_DEFAULT,
+        iotivity.OCQualityOfService.OC_HIGH_QOS,
+        observeResponseHandler,
+        null
+    );
+
+    observeHandles[observeCount] = {
+        uri: uri,
+        handle: observeHandleReceptacle.handle
+    };
+    observeCount++;
+};
+
+module.exports.cancelObservation = function(uri) {
+    console.log( "Cancel observation " + uri );
+
+    for (var index = 0; index < observeCount; index++){
+        if (observeHandles[index].uri === uri){
+            iotivity.OCCancel(observeHandles[index].handle, iotivity.OCQualityOfService.OC_HIGH_QOS, null );
+            observeCount--;
+            observeHandles.splice(index, 1);
+            break;
+        }
+    }
+
+    clearInterval( intervalId );
+    iotivity.OCStop();
+};
+
+//Exit gracefully when node service is killed
+process.on( "exit", function() {
+    // Tear down the processing loop and stop iotivity
+    clearInterval( intervalId );
+    iotivity.OCStop();
+    console.log("=== client teardown ===");
+} );
\ No newline at end of file
diff --git a/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.client/client.txt b/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.client/client.txt
new file mode 100644 (file)
index 0000000..6461d12
--- /dev/null
@@ -0,0 +1,310 @@
+API Docs - com.example.service.iotivity.client\r
+\r
+\r
+discoverResources\r
+\r
+    Discovering available resources from all devices.\r
+\r
+    @b Syntax\r
+    luna://com.example.service.iotivity.client/discoverResources\r
+\r
+    @code\r
+    {\r
+    }\r
+    @endcode\r
+    @param\r
+        Parameter   |Requirement    |Type   | Description\r
+        ----------------------------------------------------------\r
+        none\r
+    @return\r
+    <b> For a call: </b>\r
+    @code\r
+    {\r
+        "returnValue"   : boolean,\r
+        "discoveryResponse" : object,\r
+    }\r
+\r
+    @endcode\r
+    @param              returnValue\r
+    Indicates if the call was succesful.\r
+    @param              discoveryResponse\r
+    List of discoverd resources.\r
+\r
+        Parameter         |Requirement    |Type   | Description\r
+        ----------------------------------------------------------\r
+        returnValue       |Required       |boolean| true means success, false means faild\r
+        discoveryResponse |Required       |object | list of all resources from all devices\r
+\r
+    @b Examples:\r
+    @code\r
+    luna-send -n 5 -f luna://com.example.service.iotivity.client/discoverResources '{}'\r
+    @endcode\r
+\r
+    Example response for a succesful call:\r
+    @code\r
+    {\r
+        "discoveryResponse": {\r
+            ...\r
+        },\r
+        "returnValue": true\r
+    }\r
+    @endcode\r
+\r
+\r
+\r
+getResource\r
+\r
+    Fetch the value of resource from specified URI\r
+\r
+    @b Syntax \n\r
+    luna://com.example.service.iotivity.client/getResource\r
+\r
+    @code\r
+    {\r
+    }\r
+    @endcode\r
+    @param\r
+        Parameter   |Requirement    |Type   | Description\r
+        ----------------------------------------------------------\r
+        uri         |Required       |string |\r
+        destination |Required       |object | target device address include adapter, flags, ifindex, port and addr\r
+        question    |Required       |string | payload with specifiied question\r
+    @return\r
+    <b> For a call: </b>\r
+    @code\r
+    {\r
+        "returnValue"   : boolean,\r
+        "response" : object,\r
+        "errorText" : string\r
+    }\r
+\r
+    @endcode\r
+    @param              returnValue\r
+    Indicates if the call was succesful or not.\r
+    @param              response\r
+    Detailed information.\r
+    @param              errorText\r
+    Describes the error if call was not succesful.\r
+\r
+        Parameter         |Requirement    |Type   | Description\r
+        ----------------------------------------------------------\r
+        returnValue       |Required       |boolean| true means success, false means faild\r
+        response          |Optional       |object | value of requested resource\r
+        errorText         |Optional       |object | value of error text\r
+\r
+    @b Examples:\r
+    @code\r
+    luna-send -n 1 -f luna://com.example.service.iotivity.client/getResource '{"uri":"/a/fan", "question":"abc","destination": {"adapter": 1,"flags": 32,"ifindex": 2,"port": 54406,"addr": "fe80::ba27:ebff:fe04:f661%eth0"}}'\r
+    @endcode\r
+\r
+    Example response for a succesful call:\r
+    @code\r
+    {\r
+        "returnValue": true,\r
+        "response": {\r
+            "devAddr": {\r
+                "adapter": 1,\r
+                "flags": 82,\r
+                "ifindex": 0,\r
+                "port": 34711,\r
+                "addr": "10.177.242.177"\r
+            },\r
+            "connType": 65618,\r
+            "addr": {\r
+                "adapter": 1,\r
+                "flags": 82,\r
+                "ifindex": 0,\r
+                "port": 34711,\r
+                "addr": "10.177.242.177"\r
+            },\r
+            "sequenceNumber": 16777216,\r
+            "result": 0,\r
+            "identity": [\r
+                49,\r
+                49,\r
+                49,\r
+                49,\r
+                49,\r
+                49,\r
+                49,\r
+                49,\r
+                49,\r
+                49,\r
+                49,\r
+                49,\r
+                49,\r
+                49,\r
+                49,\r
+                49\r
+            ],\r
+            "payload": {\r
+                "type": 4,\r
+                "values": {\r
+                    "answer": "123"\r
+                }\r
+            },\r
+            "resourceUri": "/a/fan"\r
+        }\r
+    }\r
+    @endcode\r
+\r
+\r
+deleteResource\r
+\r
+    Delete resource from specified URI\r
+\r
+    @b Syntax\r
+    luna://com.example.service.iotivity.client/deleteResource\r
+\r
+    @code\r
+    {\r
+    }\r
+    @endcode\r
+    @param\r
+        Parameter   |Requirement    |Type   | Description\r
+        ----------------------------------------------------------\r
+        uri         |Required       |string | uri which is removed\r
+        destination |Required       |object | target device address include adapter, flags, ifindex, port and addr\r
+    @return\r
+    <b> For a call: </b>\r
+    @code\r
+    {\r
+        "returnValue"   : boolean,\r
+        "response" : object,\r
+        "errorText" : string\r
+    }\r
+\r
+    @endcode\r
+    @param              returnValue\r
+    Indicates if the call was succesful.\r
+    @param              response\r
+    Detailed information for removed resources.\r
+    @param              errorText\r
+    Describes the error if call was not succesful.\r
+\r
+        Parameter         |Requirement    |Type   | Description\r
+        ----------------------------------------------------------\r
+        returnValue       |Required       |boolean| true means success, false means faild\r
+        response          |Optional       |object | value of requested resource\r
+        errorText         |Optional       |string | value of error text\r
+    @remarks\r
+    The \e returnValue will be true as long as the syntax is correct, even if the process ID is not a valid one.\r
+\r
+    @b Examples:\r
+    @code\r
+    luna-send -n 1 -f luna://com.example.service.iotivity.client/deleteResource '{"uri":"/a/fan","destination":{"adapter":1,"flags":32,"ifindex":0,"port":35128,"addr":"fe80::ba27:ebff:fe04:f661%eth0"}}'\r
+    @endcode\r
+\r
+    Example response for a succesful call:\r
+    @code\r
+    {\r
+        "returnValue": true,\r
+        "response": {\r
+            "sequenceNumber": 16777216,\r
+            "identity": [\r
+            ],\r
+            "devAddr": {\r
+                "adapter": 1,\r
+                "flags": 32,\r
+                "ifindex": 2,\r
+                "port": 35128,\r
+                "addr": "fe80::ba27:ebff:fe04:f661%eth0"\r
+            },\r
+            "connType": 65568,\r
+            "result": 2,\r
+            "addr": {\r
+                "adapter": 1,\r
+                "flags": 32,\r
+                "ifindex": 2,\r
+                "port": 35128,\r
+                "addr": "fe80::ba27:ebff:fe04:f661%eth0"\r
+            },\r
+            "resourceUri": "/a/fan"\r
+        }\r
+    }\r
+    @endcode\r
+\r
+\r
+observeResource\r
+\r
+    Observe the value of resource from specified URI\r
+\r
+    @b Syntax \n\r
+    luna://com.example.service.iotivity.client/observeResource\r
+\r
+    @code\r
+    {\r
+    }\r
+    @endcode\r
+    @param\r
+        Parameter   |Requirement    |Type   | Description\r
+        ----------------------------------------------------------\r
+        subscribe   |Required       |boolean |\r
+        uri         |Required       |string |\r
+        destination |Required       |object | target device address include adapter, flags, ifindex, port and addr\r
+    @return\r
+    <b> For a call: </b>\r
+    @code\r
+    {\r
+        "returnValue"   : boolean,\r
+        "response" : object,\r
+        "errorText" : string\r
+    }\r
+\r
+    @endcode\r
+    @param              returnValue\r
+    Indicates if the call was succesful.\r
+    @param              response\r
+    Detailed information for removed resources.\r
+    @param              errorText\r
+    Describes the error if call was not succesful.\r
+\r
+        Parameter         |Requirement    |Type   | Description\r
+        ----------------------------------------------------------\r
+        returnValue       |Required       |boolean| true means success, false means faild\r
+        response          |Required       |object | value of requested resource\r
+        errorText         |Optional       |string | value of error text\r
+    @remarks\r
+    The \e returnValue will be true as long as the syntax is correct, even if the process ID is not a valid one.\r
+\r
+    @b Examples:\r
+    @code\r
+    luna-send -n 1 -f luna://com.example.service.iotivity.client/observeResource '{"uri":"/a/fan","destination":{"adapter":1,"flags":32,"ifindex":0,"port":58941,"addr":"fe80::ba27:ebff:fe04:f661%eth0"},"subscribe":true}'\r
+    @endcode\r
+\r
+    Example response for a succesful call:\r
+    @code\r
+    {\r
+        "subscribed": true,\r
+        "returnValue": true,\r
+        "response": {\r
+            "devAddr": {\r
+                "adapter": 1,\r
+                "flags": 32,\r
+                "ifindex": 2,\r
+                "port": 58941,\r
+                "addr": "fe80::ba27:ebff:fe04:f661%eth0"\r
+            },\r
+            "connType": 65568,\r
+            "addr": {\r
+                "adapter": 1,\r
+                "flags": 32,\r
+                "ifindex": 2,\r
+                "port": 58941,\r
+                "addr": "fe80::ba27:ebff:fe04:f661%eth0"\r
+            },\r
+            "sequenceNumber": 23,\r
+            "result": 0,\r
+            "identity": [\r
+            ],\r
+            "payload": {\r
+                "type": 4,\r
+                "values": {\r
+                    "someOtherValue": "Espoo",\r
+                    "someValue": 18\r
+                }\r
+            },\r
+            "resourceUri": "/a/fan"\r
+        }\r
+    }\r
+    @endcode\r
diff --git a/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.client/com.example.service.iotivity.client.json b/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.client/com.example.service.iotivity.client.json
new file mode 100644 (file)
index 0000000..b353e54
--- /dev/null
@@ -0,0 +1,3 @@
+{
+  "services" : ["com.example.service.iotivity.client"]
+}
diff --git a/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.client/files/sysbus/com.example.service.iotivity.client.api.json b/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.client/files/sysbus/com.example.service.iotivity.client.api.json
new file mode 100644 (file)
index 0000000..b0cfca9
--- /dev/null
@@ -0,0 +1,14 @@
+{
+  "public": [
+       "com.example.service.iotivity.client/discoverResources",
+       "com.example.service.iotivity.client/getResource",
+       "com.example.service.iotivity.client/observeResource",
+       "com.example.service.iotivity.client/deleteResource",
+  ],
+  "private": [
+       "com.example.service.iotivity.client/discoverResources",
+       "com.example.service.iotivity.client/getResource",
+       "com.example.service.iotivity.client/observeResource",
+       "com.example.service.iotivity.client/deleteResource",
+  ]
+}
\ No newline at end of file
diff --git a/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.client/files/sysbus/com.example.service.iotivity.client.manifest.json b/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.client/files/sysbus/com.example.service.iotivity.client.manifest.json
new file mode 100644 (file)
index 0000000..e62142f
--- /dev/null
@@ -0,0 +1,13 @@
+{
+    "roleFiles": [
+        "/usr/share/luna-service2/roles.d/com.example.service.iotivity.client.role.json"
+    ],
+    "id": "com.example.service.iotivity.client",
+    "version": "1.0.0",
+    "clientPermissionFiles": [
+        "/usr/share/luna-service2/client-permissions.d/com.example.service.iotivity.client.perm.json"
+    ],
+    "serviceFiles": [
+        "/usr/share/luna-service2/services.d/com.example.service.iotivity.client.service"
+    ]
+}
\ No newline at end of file
diff --git a/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.client/files/sysbus/com.example.service.iotivity.client.perm.json b/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.client/files/sysbus/com.example.service.iotivity.client.perm.json
new file mode 100644 (file)
index 0000000..35fcfd9
--- /dev/null
@@ -0,0 +1,3 @@
+{
+  "com.example.service.iotivity.client*" : ["activities.manage", "networking.internal"]
+}
diff --git a/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.client/files/sysbus/com.example.service.iotivity.client.role.json b/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.client/files/sysbus/com.example.service.iotivity.client.role.json
new file mode 100644 (file)
index 0000000..d00c1ce
--- /dev/null
@@ -0,0 +1,12 @@
+{
+    "appId" : "com.example.service.iotivity.client",
+    "allowedNames" : ["com.example.service.iotivity.client*"],
+    "type" : "regular",
+    "permissions" : [
+       {
+           "service" : "com.example.service.iotivity.client*",
+           "inbound" : ["*"],
+           "outbound" : ["*"]
+       }
+    ]
+}
diff --git a/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.client/files/sysbus/com.example.service.iotivity.client.service b/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.client/files/sysbus/com.example.service.iotivity.client.service
new file mode 100644 (file)
index 0000000..14518d5
--- /dev/null
@@ -0,0 +1,23 @@
+#******************************************************************
+#
+# Copyright (c) 2018 LG Electronics, Inc.
+#
+#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+#
+# 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
+#
+#      https://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.
+#
+#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+[D-BUS Service]
+Name = com.example.service.iotivity.client*
+Exec = /usr/bin/run-js-service /usr/palm/services/com.example.service.iotivity.client
diff --git a/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.client/main.js b/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.client/main.js
new file mode 100644 (file)
index 0000000..c7f9417
--- /dev/null
@@ -0,0 +1,474 @@
+/* ******************************************************************
+ *
+ * Copyright (c) 2018 LG Electronics, Inc.
+ *
+ *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ *
+ * 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
+ *
+ *      https://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.
+ *
+ *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+var Service = require('webos-service');
+var service = new Service('com.example.service.iotivity.client');
+
+var subscriptions = {};
+
+var client = require('./client-lowlevel');
+
+function isEmpty(obj) {
+    for ( var key in obj) {
+        if (obj.hasOwnProperty(key))
+            return false;
+    }
+    return true;
+};
+
+function subscriptionCallback(response) {
+    for (var i in subscriptions){
+        if (subscriptions.hasOwnProperty(i)) {
+            var s = subscriptions[i];
+            s.respond({
+                response : response,
+                returnValue : true,
+                subscribed : true
+            });
+        }
+    }
+};
+
+function validateUri(_uri){
+    if(_uri.charAt(0)!="/")
+        return "/"+_uri;
+    else return _uri;
+}
+
+/*
+    Discovering available resources from all devices.
+
+    @b Syntax \n
+    luna://com.example.service.iotivity.client/discoverResources
+
+    @code
+    {
+    }
+    @endcode
+    @param
+        Parameter   |Requirement    |Type   | Description
+        ----------------------------------------------------------
+        none
+    @return
+    <b> For a call: </b>
+    @code
+    {
+        "returnValue"   : boolean,
+        "discoveryResponse" : object,
+    }
+
+    @endcode
+    @param              returnValue
+    Indicates if the call was succesful.
+    @param              discoveryResponse
+    List of discoverd resources.
+
+        Parameter         |Requirement    |Type   | Description
+        ----------------------------------------------------------
+        returnValue       |Required       |boolean| true means success, false means faild
+        discoveryResponse |Required       |object | list of all resources from all devices
+
+    @b Examples:
+    @code
+    luna-send -n 5 -f luna://com.example.service.iotivity.client/discoverResources '{}'
+    @endcode
+
+    Example response for a succesful call:
+    @code
+    {
+        "discoveryResponse": {
+            ...
+        },
+        "returnValue": true
+    }
+    @endcode
+*/
+service.register("discoverResources", function(message) {
+    client.startDiscovery(function(response) {
+        message.respond({
+            discoveryResponse : response,
+            returnValue : true
+        });
+    });
+});
+
+/*
+    Fetch the value of resource from specified URI
+
+    @b Syntax \n
+    luna://com.example.service.iotivity.client/getResource
+
+    @code
+    {
+    }
+    @endcode
+    @param
+        Parameter   |Requirement    |Type   | Description
+        ----------------------------------------------------------
+        uri         |Required       |string |
+        destination |Required       |object | target device address include adapter, flags, ifindex, port and addr
+        question    |Required       |string | payload with specifiied question
+    @return
+    <b> For a call: </b>
+    @code
+    {
+        "returnValue"   : boolean,
+        "response" : object,
+        "errorText" : string
+    }
+
+    @endcode
+    @param              returnValue
+    Indicates if the call was succesful or not.
+    @param              response
+    Detailed information.
+    @param              errorText
+    Describes the error if call was not succesful.
+
+        Parameter         |Requirement    |Type   | Description
+        ----------------------------------------------------------
+        returnValue       |Required       |boolean| true means success, false means faild
+        response          |Optional       |object | value of requested resource
+        errorText         |Optional       |object | value of error text
+
+    @b Examples:
+    @code
+    luna-send -n 1 -f luna://com.example.service.iotivity.client/getResource '{"uri":"/a/fan", "question":"abc","destination": {"adapter": 1,"flags": 32,"ifindex": 2,"port": 54406,"addr": "fe80::ba27:ebff:fe04:f661%eth0"}}'
+    @endcode
+
+    Example response for a succesful call:
+    @code
+    {
+        "returnValue": true,
+        "response": {
+            "devAddr": {
+                "adapter": 1,
+                "flags": 82,
+                "ifindex": 0,
+                "port": 34711,
+                "addr": "10.177.242.177"
+            },
+            "connType": 65618,
+            "addr": {
+                "adapter": 1,
+                "flags": 82,
+                "ifindex": 0,
+                "port": 34711,
+                "addr": "10.177.242.177"
+            },
+            "sequenceNumber": 16777216,
+            "result": 0,
+            "identity": [
+                49,
+                49,
+                49,
+                49,
+                49,
+                49,
+                49,
+                49,
+                49,
+                49,
+                49,
+                49,
+                49,
+                49,
+                49,
+                49
+            ],
+            "payload": {
+                "type": 4,
+                "values": {
+                    "answer": "123"
+                }
+            },
+            "resourceUri": "/a/fan"
+        }
+    }
+    @endcode
+*/
+service.register("getResource", function(message) {
+    var uri = message.payload.uri;
+    var question = message.payload.question;
+    var destination = message.payload.destination;
+
+    if(!uri){
+        message.respond({
+            errorText : "invalid uri",
+            returnValue : false
+        });
+        return;
+    }
+    else if(!destination
+        || !destination.adapter
+        || !destination.flags
+        || !destination.port
+        || !destination.addr ){
+        message.respond({
+            errorText : "invalid destination formats",
+            returnValue : false
+        });
+        return;
+    }
+    else if(!question){
+        message.respond({
+            errorText : "invalid question",
+            returnValue : false
+        });
+        return;
+    }
+
+    client.getResource(validateUri(uri), destination, question, function(response) {
+        message.respond({
+            response : response,
+            returnValue : true
+        });
+    });
+});
+
+/*
+    Delete resource from specified URI
+
+    @b Syntax \n
+    luna://com.example.service.iotivity.client/deleteResource
+
+    @code
+    {
+    }
+    @endcode
+    @param
+        Parameter   |Requirement    |Type   | Description
+        ----------------------------------------------------------
+        uri         |Required       |string | uri which is removed
+        destination |Required       |object | target device address include adapter, flags, ifindex, port and addr
+    @return
+    <b> For a call: </b>
+    @code
+    {
+        "returnValue"   : boolean,
+        "response" : object,
+        "errorText" : string
+    }
+
+    @endcode
+    @param              returnValue
+    Indicates if the call was succesful.
+    @param              response
+    Detailed information for removed resources.
+    @param              errorText
+    Describes the error if call was not succesful.
+
+        Parameter         |Requirement    |Type   | Description
+        ----------------------------------------------------------
+        returnValue       |Required       |boolean| true means success, false means faild
+        response          |Optional       |object | value of requested resource
+        errorText         |Optional       |string | value of error text
+    @remarks
+    The \e returnValue will be true as long as the syntax is correct, even if the process ID is not a valid one.
+
+    @b Examples:
+    @code
+    luna-send -n 1 -f luna://com.example.service.iotivity.client/deleteResource '{"uri":"/a/fan","destination":{"adapter":1,"flags":32,"ifindex":0,"port":35128,"addr":"fe80::ba27:ebff:fe04:f661%eth0"}}'
+    @endcode
+
+    Example response for a succesful call:
+    @code
+    {
+        "returnValue": true,
+        "response": {
+            "sequenceNumber": 16777216,
+            "identity": [
+            ],
+            "devAddr": {
+                "adapter": 1,
+                "flags": 32,
+                "ifindex": 2,
+                "port": 35128,
+                "addr": "fe80::ba27:ebff:fe04:f661%eth0"
+            },
+            "connType": 65568,
+            "result": 2,
+            "addr": {
+                "adapter": 1,
+                "flags": 32,
+                "ifindex": 2,
+                "port": 35128,
+                "addr": "fe80::ba27:ebff:fe04:f661%eth0"
+            },
+            "resourceUri": "/a/fan"
+        }
+    }
+    @endcode
+*/
+service.register("deleteResource", function(message) {
+    var uri = message.payload.uri;
+    var destination = message.payload.destination;
+    if(!uri){
+        message.respond({
+            errorText : "invalid uri",
+            returnValue : false
+        });
+        return;
+    }
+    else if(!destination
+        || !destination.adapter
+        || !destination.flags
+        || !destination.port
+        || !destination.addr ){
+        message.respond({
+            errorText : "invalid destination formats",
+            returnValue : false
+        });
+        return;
+    }
+    client.deleteResource(validateUri(uri), destination, function(response) {
+        message.respond({
+            response : response,
+            returnValue : true
+        });
+    });
+});
+
+/*
+    Observe the value of resource from specified URI
+
+    @b Syntax \n
+    luna://com.example.service.iotivity.client/observeResource
+
+    @code
+    {
+    }
+    @endcode
+    @param
+        Parameter   |Requirement    |Type   | Description
+        ----------------------------------------------------------
+        subscribe   |Required       |boolean |
+        uri         |Required       |string |
+        destination |Required       |object | target device address include adapter, flags, ifindex, port and addr
+    @return
+    <b> For a call: </b>
+    @code
+    {
+        "returnValue"   : boolean,
+        "response" : object,
+        "errorText" : string
+    }
+
+    @endcode
+    @param              returnValue
+    Indicates if the call was succesful.
+    @param              response
+    Detailed information for removed resources.
+    @param              errorText
+    Describes the error if call was not succesful.
+
+        Parameter         |Requirement    |Type   | Description
+        ----------------------------------------------------------
+        returnValue       |Required       |boolean| true means success, false means faild
+        response          |Required       |object | value of requested resource
+        errorText         |Optional       |string | value of error text
+    @remarks
+    The \e returnValue will be true as long as the syntax is correct, even if the process ID is not a valid one.
+
+    @b Examples:
+    @code
+    luna-send -n 1 -f luna://com.example.service.iotivity.client/observeResource '{"uri":"/a/fan","destination":{"adapter":1,"flags":32,"ifindex":0,"port":58941,"addr":"fe80::ba27:ebff:fe04:f661%eth0"},"subscribe":true}'
+    @endcode
+
+    Example response for a succesful call:
+    @code
+    {
+        "subscribed": true,
+        "returnValue": true,
+        "response": {
+            "devAddr": {
+                "adapter": 1,
+                "flags": 32,
+                "ifindex": 2,
+                "port": 58941,
+                "addr": "fe80::ba27:ebff:fe04:f661%eth0"
+            },
+            "connType": 65568,
+            "addr": {
+                "adapter": 1,
+                "flags": 32,
+                "ifindex": 2,
+                "port": 58941,
+                "addr": "fe80::ba27:ebff:fe04:f661%eth0"
+            },
+            "sequenceNumber": 23,
+            "result": 0,
+            "identity": [
+            ],
+            "payload": {
+                "type": 4,
+                "values": {
+                    "someOtherValue": "Espoo",
+                    "someValue": 18
+                }
+            },
+            "resourceUri": "/a/fan"
+        }
+    }
+    @endcode
+*/
+var clientObserve = service.register("observeResource");
+clientObserve.on("request", function(message) {
+    var uri = message.payload.uri;
+    var destination = message.payload.destination;
+    if(!uri){
+        message.respond({
+            errorText : "invalid uri",
+            returnValue : false,
+            subscribed : false
+        });
+        return;
+    }
+    else if(!destination
+        || !destination.adapter
+        || !destination.flags
+        || !destination.port
+        || !destination.addr ){
+        message.respond({
+            errorText : "invalid destination formats",
+            returnValue : false,
+            subscribed : false
+        });
+        return;
+    }
+    if (message.isSubscription) {
+        subscriptions[message.uniqueToken] = message;
+        client.observeResource(validateUri(uri), destination, subscriptionCallback);
+    } else {
+        message.respond({
+            returnValue : false,
+            subscribed : false,
+        });
+    }
+});
+clientObserve.on("cancel", function(message) {
+    delete subscriptions[message.uniqueToken];
+    var uri = message.payload.uri;
+    client.cancelObservation(uri);
+    message.respond({
+        returnValue : true,
+        subscribed : false
+    });
+});
\ No newline at end of file
diff --git a/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.client/oic_svr_db_client.dat b/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.client/oic_svr_db_client.dat
new file mode 100644 (file)
index 0000000..091d84d
Binary files /dev/null and b/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.client/oic_svr_db_client.dat differ
diff --git a/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.client/oic_svr_db_client.json b/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.client/oic_svr_db_client.json
new file mode 100644 (file)
index 0000000..54aecee
--- /dev/null
@@ -0,0 +1,61 @@
+{\r
+    "acl": {\r
+        "aclist2": [\r
+            {\r
+                "aceid": 1,\r
+                "subject": { "conntype": "anon-clear" },\r
+                "resources": [\r
+                    { "href": "/oic/res" },\r
+                    { "href": "/oic/d" },\r
+                    { "href": "/oic/p" },\r
+                    { "href": "/oic/sec/doxm" }\r
+                ],\r
+                "permission": 2\r
+            },\r
+            {\r
+                "aceid": 2,\r
+                "subject": { "conntype": "auth-crypt" },\r
+                "resources": [\r
+                    { "href": "/oic/res" },\r
+                    { "href": "/oic/d" },\r
+                    { "href": "/oic/p" },\r
+                    { "href": "/oic/sec/doxm" }\r
+                ],\r
+                "permission": 2\r
+            }\r
+        ],\r
+        "rowneruuid" : "31393139-3139-3139-3139-313931393139"\r
+    },\r
+    "pstat": {\r
+        "dos": {"s": 3, "p": false},\r
+        "isop": true,\r
+        "rowneruuid": "31393139-3139-3139-3139-313931393139",\r
+        "cm": 0,\r
+        "tm": 0,\r
+        "om": 4,\r
+        "sm": 4\r
+        },\r
+    "doxm": {\r
+        "oxms": [0],\r
+        "oxmsel": 0,\r
+        "sct": 9,\r
+        "owned": true,\r
+        "deviceuuid": "31393139-3139-3139-3139-313931393139",\r
+        "devowneruuid": "31393139-3139-3139-3139-313931393139",\r
+        "rowneruuid": "31393139-3139-3139-3139-313931393139"\r
+    },\r
+    "cred": {\r
+        "creds": [\r
+            {\r
+                "credid": 1,\r
+                "subjectuuid": "31313131-3131-3131-3131-313131313131",\r
+                "credtype": 1,\r
+                "privatedata": {\r
+                    "data": "BBBBBBBBBBBBBBBB",\r
+                    "encoding": "oic.sec.encoding.raw"\r
+                }\r
+            }\r
+        ],\r
+        "rowneruuid": "31393139-3139-3139-3139-313931393139"\r
+    }\r
+}\r
diff --git a/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.client/package.json b/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.client/package.json
new file mode 100644 (file)
index 0000000..6b3539b
--- /dev/null
@@ -0,0 +1,4 @@
+{
+   "name" : "com.example.service.iotivity.client",
+   "main" : "main.js"
+}
diff --git a/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.server/com.example.service.iotivity.server.json b/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.server/com.example.service.iotivity.server.json
new file mode 100644 (file)
index 0000000..6ed74bd
--- /dev/null
@@ -0,0 +1,3 @@
+{
+  "services" : ["com.example.service.iotivity.server"]
+}
diff --git a/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.server/files/sysbus/com.example.service.iotivity.server.api.json b/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.server/files/sysbus/com.example.service.iotivity.server.api.json
new file mode 100644 (file)
index 0000000..d7b55c9
--- /dev/null
@@ -0,0 +1,12 @@
+{
+    "public": [
+        "com.example.service.iotivity.server/startServer",
+        "com.example.service.iotivity.server/createResource",
+        "com.example.service.iotivity.server/deleteResource",
+    ],
+    "private": [
+        "com.example.service.iotivity.server/startServer",
+        "com.example.service.iotivity.server/createResource",
+        "com.example.service.iotivity.server/deleteResource",
+    ]
+}
diff --git a/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.server/files/sysbus/com.example.service.iotivity.server.manifest.json b/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.server/files/sysbus/com.example.service.iotivity.server.manifest.json
new file mode 100644 (file)
index 0000000..0234aef
--- /dev/null
@@ -0,0 +1,13 @@
+{
+    "roleFiles": [
+        "/usr/share/luna-service2/roles.d/com.example.service.iotivity.server.role.json"
+    ],
+    "id": "com.example.service.iotivity.server",
+    "version": "1.0.0",
+    "clientPermissionFiles": [
+        "/usr/share/luna-service2/client-permissions.d/com.example.service.iotivity.server.perm.json"
+    ],
+    "serviceFiles": [
+        "/usr/share/luna-service2/services.d/com.example.service.iotivity.server.service"
+    ]
+}
\ No newline at end of file
diff --git a/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.server/files/sysbus/com.example.service.iotivity.server.perm.json b/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.server/files/sysbus/com.example.service.iotivity.server.perm.json
new file mode 100644 (file)
index 0000000..d16dc76
--- /dev/null
@@ -0,0 +1,3 @@
+{
+  "com.example.service.iotivity.server*" : ["activities.manage", "networking.internal"]
+}
diff --git a/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.server/files/sysbus/com.example.service.iotivity.server.role.json b/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.server/files/sysbus/com.example.service.iotivity.server.role.json
new file mode 100644 (file)
index 0000000..a5aaa09
--- /dev/null
@@ -0,0 +1,11 @@
+{
+    "appId" : "com.example.service.iotivity.server",
+    "allowedNames" : ["com.example.service.iotivity.server*"],
+    "type" : "regular",
+    "permissions" : [
+       {
+        "service" : "com.example.service.iotivity.server*",
+        "inbound" : ["*"],
+        "outbound" : ["*"]
+    }]
+}
diff --git a/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.server/files/sysbus/com.example.service.iotivity.server.service b/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.server/files/sysbus/com.example.service.iotivity.server.service
new file mode 100644 (file)
index 0000000..a98ea16
--- /dev/null
@@ -0,0 +1,23 @@
+#******************************************************************
+#
+# Copyright (c) 2018 LG Electronics, Inc.
+#
+#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+#
+# 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
+#
+#      https://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.
+#
+#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+[D-BUS Service]
+Name = com.example.service.iotivity.server*
+Exec = /usr/bin/run-js-service /usr/palm/services/com.example.service.iotivity.server
diff --git a/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.server/main.js b/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.server/main.js
new file mode 100644 (file)
index 0000000..91dc157
--- /dev/null
@@ -0,0 +1,273 @@
+/* ******************************************************************
+ *
+ * Copyright (c) 2018 LG Electronics, Inc.
+ *
+ *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ *
+ * 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
+ *
+ *      https://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.
+ *
+ *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+var Service = require('webos-service');
+var service = new Service('com.example.service.iotivity.server');
+
+var subscriptions = {};
+
+var server = require('./server-lowlevel');
+
+function isEmpty(obj) {
+    for ( var key in obj) {
+        if (obj.hasOwnProperty(key))
+            return false;
+    }
+    return true;
+};
+
+function subscriptionCallback(response) {
+    for (var i in subscriptions){
+        if (subscriptions.hasOwnProperty(i)) {
+            var s = subscriptions[i];
+            s.respond({
+                response : response,
+                returnValue : true,
+                subscribed : true
+            });
+        }
+    }
+};
+
+function validateUri(_uri){
+    if(_uri.charAt(0)!="/")
+        return "/"+_uri;
+    else return _uri;
+}
+
+/*
+    To Start iotivity server with iotivity-node
+
+    @b Syntax \n
+    luna://com.example.service.iotivity.server/startServer
+
+    @code
+    {
+    }
+    @endcode
+    @param
+        Parameter   |Requirement    |Type    | Description
+        ----------------------------------------------------------
+        subscribe   |Required       |boolean |
+    @return
+    <b> For a call: </b>
+    @code
+    {
+        "returnValue"   : boolean,
+        "subscribed" : boolean,
+    }
+
+    @endcode
+    @param              returnValue
+    Indicates if the call was succesful or not.
+    @param              subscribed
+    Detailed information for removed resources.
+
+        Parameter         |Requirement    |Type   | Description
+        ----------------------------------------------------------
+        returnValue       |Required       |boolean| true means success, false means faild
+        subscribed        |Required       |boolean| value of requested resource
+    @remarks
+    The \e returnValue will be true as long as the syntax is correct, even if the process ID is not a valid one.
+
+    @b Examples:
+    @code
+    luna-send -i -f luna://com.example.service.iotivity.server/startServer '{"subscribe":true}'&
+    @endcode
+
+    Example response for a succesful call:
+    @code
+    {
+        "resources": [
+        ],
+        "subscribed": true,
+        "returnValue": true
+    }
+    {
+        "resources": [
+            {
+                "interfaces": [
+                    "oic.if.baseline"
+                ],
+                "types": [
+                    "core.fan"
+                ],
+                "uri": "a/fan"
+            }
+        ],
+        "subscribed": true,
+        "returnValue": true
+    }
+    @endcode
+*/
+var serverDiscoverable = service.register("startServer");
+serverDiscoverable.on("request", function(message) {
+    if (message.isSubscription) {
+        if (isEmpty(subscriptions)){
+            subscriptions[message.uniqueToken] = message;
+            server.startServer(subscriptionCallback);
+        } else {
+            subscriptions[message.uniqueToken] = message;
+        }
+    } else {
+        message.respond({
+            returnValue : false,
+            subscribed : false
+        });
+    }
+});
+serverDiscoverable.on("cancel", function(message) {
+    delete subscriptions[message.uniqueToken];
+    if (isEmpty(subscriptions))
+        server.stopServer();
+    message.respond({returnValue : true});
+});
+
+/*
+    To create resource
+
+    @b Syntax \n
+    luna://com.example.service.iotivity.server/createResource
+
+    @code
+    {
+    }
+    @endcode
+    @param
+        Parameter   |Requirement    |Type   | Description
+        ----------------------------------------------------------
+        uri         |Required       |string |
+        types       |Required       |string |
+        question    |Required       |string |
+        answer      |Required       |string |
+        observable  |Required       |boolean|
+    @return
+    <b> For a call: </b>
+    @code
+    {
+        "returnValue"   : boolean,
+    }
+
+    @endcode
+    @param              returnValue
+    Indicates if the call was succesful or not.
+    @param              subscribed
+    Detailed information for removed resources.
+
+        Parameter         |Requirement    |Type   | Description
+        ----------------------------------------------------------
+        returnValue       |Required       |boolean| true means success, false means faild
+    @remarks
+    The \e returnValue will be true as long as the syntax is correct, even if the process ID is not a valid one.
+
+    @b Examples:
+    @code
+    luna-send -1 -f luna://com.example.service.iotivity.server/createResource '{"uri":"a/fan","question":"abc","answer":"123","observable":true,"types":"core.fan"}'
+    @endcode
+
+    Example response for a succesful call:
+    @code
+    {
+        "returnValue": true
+    }
+    @endcode
+*/
+service.register("createResource", function(message){
+    var uri = message.payload.uri;
+    var types = message.payload.types;
+    var interfaces = message.payload.interfaces;
+    var observable = message.payload.observable;
+    var q = message.payload.question;
+    var a = message.payload.answer;
+
+    if( !uri || !types || !q || !a ){
+        message.respond({
+            errorText : "invalid destination formats",
+            returnValue : false,
+            subscribed : false
+        });
+    }
+    else{
+        server.createResource(validateUri(uri), types, q, a, observable, subscriptionCallback);
+        message.respond({ returnValue : true });
+    }
+});
+
+/*
+    To delete resource with specific URI
+
+    @b Syntax \n
+    luna://com.example.service.iotivity.server/deleteResource
+
+    @code
+    {
+    }
+    @endcode
+    @param
+        Parameter   |Requirement    |Type   | Description
+        ----------------------------------------------------------
+        uri         |Required       |string |
+
+    @return
+    <b> For a call: </b>
+    @code
+    {
+        "returnValue"   : boolean,
+    }
+
+    @endcode
+    @param              returnValue
+    Indicates if the call was succesful or not.
+    @param              subscribed
+    Detailed information for removed resources.
+
+        Parameter         |Requirement    |Type   | Description
+        ----------------------------------------------------------
+        returnValue       |Required       |boolean| true means success, false means faild
+    @remarks
+    The \e returnValue will be true as long as the syntax is correct, even if the process ID is not a valid one.
+
+    @b Examples:
+    @code
+    luna-send -1 -f luna://com.example.service.iotivity.server/deleteResource '{"uri":"/a/fan"}'
+    @endcode
+
+    Example response for a succesful call:
+    @code
+    {
+        "returnValue": true
+    }
+    @endcode
+*/
+service.register("deleteResource", function(message){
+    var uri = message.payload.uri;
+    if(!uri){
+        message.respond({
+            errorText : "invalid uri",
+            returnValue : false,
+            subscribed : false
+        });
+        return;
+    }
+    else{
+        server.deleteResource(validateUri(uri), subscriptionCallback);
+        message.respond({ returnValue : true });
+    }
+});
\ No newline at end of file
diff --git a/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.server/mock-sensor.js b/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.server/mock-sensor.js
new file mode 100644 (file)
index 0000000..cae7e6b
--- /dev/null
@@ -0,0 +1,59 @@
+// Copyright 2016 Intel Corporation
+//
+// 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.
+
+// This mock sensor implementation triggers an event with some data every once in a while
+
+// Return a random integer between 0 and @upperLimit
+function randomInteger( upperLimit ) {
+       return Math.round( Math.random() * upperLimit );
+}
+
+var _ = {
+    extend: require( "iotivity-node/node_modules/lodash.assignin" ),
+    bind: require( "iotivity-node/node_modules/lodash.bind" )
+};
+
+var possibleStrings = [
+    "Helsinki",
+    "Espoo",
+    "Tampere",
+    "Oulu",
+    "Mikkeli",
+    "Ii"
+];
+
+var MockSensor = function MockSensor() {
+    function trigger() {
+        this.emit( "change", this.currentData() );
+        setTimeout( _.bind( trigger, this ), randomInteger( 1000 ) + 1000 );
+    }
+    if ( !this._isMockSensor ) {
+        return new MockSensor();
+    }
+    setTimeout( _.bind( trigger, this ), randomInteger( 1000 ) + 1000 );
+};
+
+require( "util" ).inherits( MockSensor, require( "events" ).EventEmitter );
+
+_.extend( MockSensor.prototype, {
+    _isMockSensor: true,
+    currentData: function() {
+        return {
+            someValue: Math.round( Math.random() * 42 ),
+            someOtherValue: possibleStrings[ randomInteger( possibleStrings.length - 1 ) ]
+        };
+    }
+} );
+
+module.exports = MockSensor;
diff --git a/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.server/oic_svr_db_server.dat b/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.server/oic_svr_db_server.dat
new file mode 100644 (file)
index 0000000..a8d5f72
Binary files /dev/null and b/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.server/oic_svr_db_server.dat differ
diff --git a/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.server/oic_svr_db_server.json b/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.server/oic_svr_db_server.json
new file mode 100644 (file)
index 0000000..384ffc4
--- /dev/null
@@ -0,0 +1,90 @@
+{\r
+    "acl": {\r
+        "aclist2": [\r
+            {\r
+                "aceid": 1,\r
+                "subject": { "conntype": "anon-clear" },\r
+                "resources": [\r
+                    { "href": "/oic/res" },\r
+                    { "href": "/oic/d" },\r
+                    { "href": "/oic/p" },\r
+                    { "href": "/oic/sec/doxm" }\r
+                ],\r
+                "permission": 2\r
+            },\r
+            {\r
+                "aceid": 2,\r
+                "subject": { "conntype": "auth-crypt" },\r
+                "resources": [\r
+                    { "href": "/oic/res" },\r
+                    { "href": "/oic/d" },\r
+                    { "href": "/oic/p" },\r
+                    { "href": "/oic/sec/doxm" }\r
+                ],\r
+                "permission": 2\r
+            },\r
+            {\r
+                "aceid": 3,\r
+                "subject": { "conntype": "anon-clear" },\r
+                "resources": [{ "href": "/a/fan" }],\r
+                "permission": 31\r
+            },\r
+            {\r
+                "aceid": 4,\r
+                "subject": { "conntype": "auth-crypt" },\r
+                "resources": [{ "href": "/a/fan" }],\r
+                "permission": 31\r
+            },\r
+            {\r
+                "aceid": 5,\r
+                "subject": { "uuid": "31393139-3139-3139-3139-313931393139" },\r
+                "resources": [{ "href": "/a/light" }],\r
+                "permission": 31\r
+            }\r
+        ],\r
+        "rowneruuid" : "31313131-3131-3131-3131-313131313131"\r
+    },\r
+    "pstat": {\r
+        "dos": {"s": 3, "p": false},\r
+        "isop": true,\r
+        "rowneruuid": "31313131-3131-3131-3131-313131313131",\r
+        "cm": 0,\r
+        "tm": 0,\r
+        "om": 4,\r
+        "sm": 4\r
+        },\r
+    "doxm": {\r
+        "oxms": [0],\r
+        "oxmsel": 0,\r
+        "sct": 9,\r
+        "owned": true,\r
+        "deviceuuid": "31313131-3131-3131-3131-313131313131",\r
+        "devowneruuid": "32323232-3232-3232-3232-323232323232",\r
+        "rowneruuid": "31313131-3131-3131-3131-313131313131"\r
+    },\r
+    "cred": {\r
+        "creds": [\r
+            {\r
+                "credid": 1,\r
+                "subjectuuid": "32323232-3232-3232-3232-323232323232",\r
+                "credtype": 1,\r
+                "period": "20150630T060000/20990920T220000",\r
+                "privatedata": {\r
+                    "data": "AAAAAAAAAAAAAAAA",\r
+                    "encoding": "oic.sec.encoding.raw"\r
+                }\r
+            },\r
+            {\r
+                "credid": 2,\r
+                "subjectuuid": "31393139-3139-3139-3139-313931393139",\r
+                "credtype": 1,\r
+                "period": "20150630T060000/20990920T220000",\r
+                "privatedata": {\r
+                    "data": "BBBBBBBBBBBBBBBB",\r
+                    "encoding": "oic.sec.encoding.raw"\r
+                }\r
+            }\r
+        ],\r
+        "rowneruuid": "32323232-3232-3232-3232-323232323232"\r
+    }\r
+}\r
diff --git a/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.server/package.json b/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.server/package.json
new file mode 100644 (file)
index 0000000..1dc5321
--- /dev/null
@@ -0,0 +1,4 @@
+{
+   "name" : "com.example.service.iotivity.server",
+   "main" : "main.js"
+}
diff --git a/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.server/server-lowlevel.js b/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.server/server-lowlevel.js
new file mode 100644 (file)
index 0000000..171fec4
--- /dev/null
@@ -0,0 +1,226 @@
+/* ******************************************************************
+ *
+ * Copyright (c) 2018 LG Electronics, Inc.
+ *
+ *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ *
+ * 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
+ *
+ *      https://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.
+ *
+ *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+var intervalId, initialResourceCount;
+var iotivity = require("iotivity-node/lowlevel");
+var StorageHandler = require("iotivity-node/lib/CustomStorageHandler");
+
+module.exports.startServer = function(resourceCallback) {
+    console.log("Starting OCF stack in server mode");
+
+    iotivity.OCRegisterPersistentStorageHandler(StorageHandler("oic_svr_db_server.dat"));
+
+    // Start iotivity and set up the processing loop
+    iotivity.OCInit(null, 0, iotivity.OCMode.OC_SERVER);
+
+    intervalId = setInterval(function() {
+        iotivity.OCProcess();
+    }, 1000);
+
+    iotivity.OCSetPropertyValue(iotivity.OCPayloadType.PAYLOAD_TYPE_DEVICE,
+                    iotivity.OC_RSRVD_SPEC_VERSION, "res.1.3.0");
+    iotivity.OCSetPropertyValue(iotivity.OCPayloadType.PAYLOAD_TYPE_DEVICE,
+                    iotivity.OC_RSRVD_DATA_MODEL_VERSION, "webosose.1.0.0");
+    iotivity.OCSetPropertyValue(iotivity.OCPayloadType.PAYLOAD_TYPE_DEVICE,
+                    iotivity.OC_RSRVD_DEVICE_NAME, "server.example");
+    iotivity.OCSetPropertyValue(iotivity.OCPayloadType.PAYLOAD_TYPE_PLATFORM,
+                    iotivity.OC_RSRVD_MFG_NAME, "lge-iotivity-node");
+
+    console.log("Server ready");
+
+    var countReceptacle = {};
+    var result = iotivity.OCGetNumberOfResources(countReceptacle);
+    initialResourceCount = countReceptacle.count;
+    updateServerStatus(resourceCallback);
+
+};
+
+module.exports.createResource = function(uri, types, q, a, observable, resourceCallback) {
+    console.log("Registering resources");
+
+    var handleReceptacle = {};
+    var observerIds = [];
+    var properties = iotivity.OCResourceProperty.OC_DISCOVERABLE
+        | iotivity.OCResourceProperty.OC_SECURE;
+
+    if(observable){
+        properties= properties|iotivity.OCResourceProperty.OC_OBSERVABLE;
+    }
+
+    var sensor = require( "./mock-sensor" )()
+        .on( "change", function( data ) {
+            iotivity.OCNotifyListOfObservers(
+                handleReceptacle.handle,
+                observerIds,
+                {
+                    type: iotivity.OCPayloadType.PAYLOAD_TYPE_REPRESENTATION,
+                    values: data
+                },
+                iotivity.OCQualityOfService.OC_HIGH_QOS );
+        }
+    );
+
+    iotivity.OCCreateResource(
+
+        // The bindings fill in this object
+        handleReceptacle,
+        types,
+        iotivity.OC_RSRVD_INTERFACE_DEFAULT,
+        uri,
+        function( flag, request ) {
+            console.log( "Entity handler called with flag = " + flag + " and the following request:" );
+            console.log( JSON.stringify( request, null, 4 ) );
+
+            // If we find the magic question in the request, we return the magic answer
+            if ( request && request.payload && request.payload.values &&
+                request.payload.values.question===q) {
+                iotivity.OCDoResponse( {
+                    requestHandle: request.requestHandle,
+                    resourceHandle: request.resource,
+                    ehResult: iotivity.OCEntityHandlerResult.OC_EH_OK,
+                    payload: {
+                        type: iotivity.OCPayloadType.PAYLOAD_TYPE_REPRESENTATION,
+                        values: {
+                            "answer": a
+                        }
+                    },
+                    resourceUri: uri,
+                    sendVendorSpecificHeaderOptions: []
+                } );
+
+                return iotivity.OCEntityHandlerResult.OC_EH_OK;
+            }
+            if ( request && request.method === iotivity.OCMethod.OC_REST_DELETE ) {
+
+                var result = iotivity.OCDeleteResource( handleReceptacle.handle );
+
+                console.log( "OCDeleteResource() has resulted in " + result );
+
+                iotivity.OCDoResponse( {
+                    requestHandle: request.requestHandle,
+                    resourceHandle: null,
+                    ehResult: result ?
+                        iotivity.OCEntityHandlerResult.OC_EH_ERROR :
+                        iotivity.OCEntityHandlerResult.OC_EH_RESOURCE_DELETED,
+                    payload: null,
+                    resourceUri: uri,
+                    sendVendorSpecificHeaderOptions: []
+                } );
+
+                return iotivity.OCEntityHandlerResult.OC_EH_OK;
+            }
+            if ( flag & iotivity.OCEntityHandlerFlag.OC_OBSERVE_FLAG ) {
+                if ( request.obsInfo.obsId !== 0 ) {
+                    if ( request.obsInfo.action === iotivity.OCObserveAction.OC_OBSERVE_REGISTER ) {
+
+                        // Add new observer to list.
+                        observerIds.push( request.obsInfo.obsId );
+                    } else if ( request.obsInfo.action ===
+                            iotivity.OCObserveAction.OC_OBSERVE_DEREGISTER ) {
+
+                        // Remove requested observer from list.
+                        observerIdIndex = observerIds.indexOf( request.obsInfo.obsId );
+                        if ( observerIdIndex >= 0 ) {
+                            observerIds.splice( observerIdIndex, 1 );
+                        }
+                    }
+                }
+            }
+            if ( request.requestHandle ) {
+                iotivity.OCDoResponse( {
+                    requestHandle: request.requestHandle,
+                    resourceHandle: request.resource,
+                    ehResult: iotivity.OCEntityHandlerResult.OC_EH_OK,
+                    payload: {
+                        type: iotivity.OCPayloadType.PAYLOAD_TYPE_REPRESENTATION,
+                        values: sensor.currentData()
+                    },
+                    resourceUri: uri,
+                    sendVendorSpecificHeaderOptions: []
+                } );
+            }
+
+        // By default we error out
+        return iotivity.OCEntityHandlerResult.OC_EH_OK;
+    }, properties);
+
+    console.log(uri + " resource ready");
+
+    updateServerStatus(resourceCallback);
+};
+
+function updateServerStatus(resourceCallback) {
+    var countReceptacle = {};
+    var result = iotivity.OCGetNumberOfResources(countReceptacle);
+    var resources = [];
+    for (var index = initialResourceCount; index < countReceptacle.count; index++) {
+        var resource = {};
+        resource.types = [];
+        resource.interfaces = [];
+
+        var handle = iotivity.OCGetResourceHandle(index);
+        resource.uri = iotivity.OCGetResourceUri(handle);
+
+        var countRecep = {};
+        result = iotivity.OCGetNumberOfResourceTypes(handle, countRecep);
+        for (var i = 0; i < countRecep.count; i++) {
+            resource.types[i] = iotivity.OCGetResourceTypeName(handle, i);
+        }
+
+        result = iotivity.OCGetNumberOfResourceInterfaces(handle, countRecep);
+        for (i = 0; i < countRecep.count; i++) {
+            resource.interfaces[i] = iotivity.OCGetResourceInterfaceName(handle, i);
+        }
+
+        resources[index - initialResourceCount] = resource;
+    }
+    resourceCallback(resources);
+};
+
+module.exports.stopServer = function() {
+    // Tear down the processing loop and stop iotivity
+    clearInterval(intervalId);
+    iotivity.OCStop();
+    console.log("=== server teardown ===");
+};
+
+module.exports.deleteResource = function(uri, resourceCallback) {
+    var countReceptacle = {};
+    var handle;
+
+    var result = iotivity.OCGetNumberOfResources(countReceptacle);
+    var count = countReceptacle.count;
+    for (var index = initialResourceCount; index < count; index++) {
+        handle = iotivity.OCGetResourceHandle(index);
+        if (uri == null) {
+            iotivity.OCDeleteResource(handle);
+            index--;
+            count--;
+            continue;
+        }
+
+        if (uri == iotivity.OCGetResourceUri(handle)) {
+            iotivity.OCDeleteResource(handle);
+            break;
+        }
+    }
+
+    updateServerStatus(resourceCallback);
+};
\ No newline at end of file
diff --git a/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.server/server.txt b/resource/csdk/stack/samples/webos/com.example.app.iotivity/services/com.example.service.iotivity.server/server.txt
new file mode 100644 (file)
index 0000000..3514482
--- /dev/null
@@ -0,0 +1,167 @@
+API Docs - com.exampel.service.iotivity.server\r
+\r
+\r
+startServer\r
+\r
+    To Start iotivity server with iotivity-node\r
+\r
+    @b Syntax \n\r
+    luna://com.example.service.iotivity.server/startServer\r
+\r
+    @code\r
+    {\r
+    }\r
+    @endcode\r
+    @param\r
+        Parameter   |Requirement    |Type    | Description\r
+        ----------------------------------------------------------\r
+        subscribe   |Required       |boolean |\r
+    @return\r
+    <b> For a call: </b>\r
+    @code\r
+    {\r
+        "returnValue"   : boolean,\r
+        "subscribed" : boolean,\r
+    }\r
+\r
+    @endcode\r
+    @param              returnValue\r
+    Indicates if the call was succesful or not.\r
+    @param              subscribed\r
+    Detailed information for removed resources.\r
+\r
+        Parameter         |Requirement    |Type   | Description\r
+        ----------------------------------------------------------\r
+        returnValue       |Required       |boolean| true means success, false means faild\r
+        subscribed        |Required       |boolean| value of requested resource\r
+    @remarks\r
+    The \e returnValue will be true as long as the syntax is correct, even if the process ID is not a valid one.\r
+\r
+    @b Examples:\r
+    @code\r
+    luna-send -i -f luna://com.example.service.iotivity.server/startServer '{"subscribe":true}'&\r
+    @endcode\r
+\r
+    Example response for a succesful call:\r
+    @code\r
+    {\r
+        "resources": [\r
+        ],\r
+        "subscribed": true,\r
+        "returnValue": true\r
+    }\r
+    {\r
+        "resources": [\r
+            {\r
+                "interfaces": [\r
+                    "oic.if.baseline"\r
+                ],\r
+                "types": [\r
+                    "core.fan"\r
+                ],\r
+                "uri": "a/fan"\r
+            }\r
+        ],\r
+        "subscribed": true,\r
+        "returnValue": true\r
+    }\r
+    @endcode\r
+\r
+\r
+createResource\r
+\r
+    To create resource\r
+\r
+    @b Syntax \n\r
+    luna://com.example.service.iotivity.server/createResource\r
+\r
+    @code\r
+    {\r
+    }\r
+    @endcode\r
+    @param\r
+        Parameter   |Requirement    |Type   | Description\r
+        ----------------------------------------------------------\r
+        uri         |Required       |string |\r
+        types       |Required       |string |\r
+        question    |Required       |string |\r
+        answer      |Required       |string |\r
+        observable  |Optional       |boolean|\r
+    @return\r
+    <b> For a call: </b>\r
+    @code\r
+    {\r
+        "returnValue"   : boolean,\r
+    }\r
+\r
+    @endcode\r
+    @param              returnValue\r
+    Indicates if the call was succesful or not.\r
+    @param              subscribed\r
+    Detailed information for removed resources.\r
+\r
+        Parameter         |Requirement    |Type   | Description\r
+        ----------------------------------------------------------\r
+        returnValue       |Required       |boolean| true means success, false means faild\r
+    @remarks\r
+    The \e returnValue will be true as long as the syntax is correct, even if the process ID is not a valid one.\r
+\r
+    @b Examples:\r
+    @code\r
+    luna-send -1 -f luna://com.example.service.iotivity.server/createResource '{"uri":"a/fan","question":"abc","answer":"123","observable":true,"types":"core.fan"}'\r
+    @endcode\r
+\r
+    Example response for a succesful call:\r
+    @code\r
+    {\r
+        "returnValue": true\r
+    }\r
+    @endcode\r
+\r
+\r
+deleteResource\r
+\r
+    To delete resource with specific URI\r
+\r
+    @b Syntax \n\r
+    luna://com.example.service.iotivity.server/deleteResource\r
+\r
+    @code\r
+    {\r
+    }\r
+    @endcode\r
+    @param\r
+        Parameter   |Requirement    |Type   | Description\r
+        ----------------------------------------------------------\r
+        uri         |Required       |string |\r
+\r
+    @return\r
+    <b> For a call: </b>\r
+    @code\r
+    {\r
+        "returnValue"   : boolean,\r
+    }\r
+\r
+    @endcode\r
+    @param              returnValue\r
+    Indicates if the call was succesful or not.\r
+    @param              subscribed\r
+    Detailed information for removed resources.\r
+\r
+        Parameter         |Requirement    |Type   | Description\r
+        ----------------------------------------------------------\r
+        returnValue       |Required       |boolean| true means success, false means faild\r
+    @remarks\r
+    The \e returnValue will be true as long as the syntax is correct, even if the process ID is not a valid one.\r
+\r
+    @b Examples:\r
+    @code\r
+    luna-send -1 -f luna://com.example.service.iotivity.server/deleteResource '{"uri":"/a/fan"}'\r
+    @endcode\r
+\r
+    Example response for a succesful call:\r
+    @code\r
+    {\r
+        "returnValue": true\r
+    }\r
+    @endcode
\ No newline at end of file
diff --git a/resource/csdk/stack/samples/webos/com.example.app.iotivity/src/App/App.js b/resource/csdk/stack/samples/webos/com.example.app.iotivity/src/App/App.js
new file mode 100644 (file)
index 0000000..9741448
--- /dev/null
@@ -0,0 +1,27 @@
+import kind from '@enact/core/kind';
+import MoonstoneDecorator from '@enact/moonstone/MoonstoneDecorator';
+import Panels from '@enact/moonstone/Panels';
+import React from 'react';
+
+import MainPanel from '../views/MainPanel';
+
+import css from './App.less';
+
+const App = kind({
+    name: 'App',
+
+    styles: {
+        css,
+        className: 'app'
+    },
+
+    render: (props) => (
+        <div {...props}>
+            <Panels>
+                <MainPanel />
+            </Panels>
+        </div>
+    )
+});
+
+export default MoonstoneDecorator(App);
diff --git a/resource/csdk/stack/samples/webos/com.example.app.iotivity/src/App/App.less b/resource/csdk/stack/samples/webos/com.example.app.iotivity/src/App/App.less
new file mode 100755 (executable)
index 0000000..2b4173d
--- /dev/null
@@ -0,0 +1,3 @@
+.app {
+    // styles can be put here
+}
diff --git a/resource/csdk/stack/samples/webos/com.example.app.iotivity/src/App/package.json b/resource/csdk/stack/samples/webos/com.example.app.iotivity/src/App/package.json
new file mode 100755 (executable)
index 0000000..498cf52
--- /dev/null
@@ -0,0 +1,3 @@
+{
+    "main": "App.js"
+}
diff --git a/resource/csdk/stack/samples/webos/com.example.app.iotivity/src/actions/ActionCreators.js b/resource/csdk/stack/samples/webos/com.example.app.iotivity/src/actions/ActionCreators.js
new file mode 100644 (file)
index 0000000..f3cc86f
--- /dev/null
@@ -0,0 +1,269 @@
+import * as actions from './ActionTypes';
+import LS2Request from '@enact/webos/LS2Request';
+
+const ls2instances = {};
+
+export const LS2RequestSingleton = {
+    instance: function (skey, preventRepeat) {
+        if (preventRepeat && ls2instances[skey]) {
+            return false;
+        }
+
+        ls2instances[skey] = ls2instances[skey] || new LS2Request();
+        return ls2instances[skey];
+    },
+    deleteInstance: function (skey) {
+        ls2instances[skey] = null;
+    }
+};
+
+export function actionUpdateServerState (tf) {
+    return {
+        type: actions.UPDATE_SERVER,
+        payload: {"enabled":tf}
+    };
+}
+
+export function actionUpdateDiscoveredList (res) {
+    if(!res.addr){
+        setTimeout(function() {
+            const ls = LS2RequestSingleton.instance('discoverResources');
+            if (ls) {
+                ls.cancel();
+                LS2RequestSingleton.deleteInstance('discoverResources');
+            }
+        }, 5000, null)
+        return {
+            type: actions.SHOW_RESOURCES_LIST,
+            payload: res
+        };
+    }
+    else{
+        return {
+            type: actions.UPDATE_DISCOVERED_RESOURCES,
+            payload: res
+        };
+    }
+}
+
+export function actionResetDiscoveredList () {
+    return {
+        type: actions.RESET_DISCOVERED_RESOURCES,
+    };
+}
+
+export function actionEnableServerResourceControlUI(){
+    return {
+        type: actions.SHOW_SERVER_RESOURCE_CONTROL_UI,
+    };
+}
+
+export function actionDisableServerResourceControlUI(){
+    return {
+        type: actions.HIDE_SERVER_RESOURCE_CONTROL_UI,
+    };
+}
+
+export function actionEnableClientResourceControlUI(){
+    return {
+        type: actions.SHOW_CLIENT_RESOURCE_CONTROL_UI,
+    };
+}
+
+export function actionDisableClientResourceControlUI(){
+    return {
+        type: actions.HIDE_CLIENT_RESOURCE_CONTROL_UI,
+    };
+}
+
+export function actionUpdateGetResourceResults(result){
+    return {
+        type: actions.UPDATE_GET_RESOURCE_RESULTS,
+        payload: result
+    };
+}
+
+export function actionUpdateObserveResourceResults(result){
+    return {
+        type: actions.UPDATE_OBSERVE_RESOURCE_RESULTS,
+        payload: result
+    };
+}
+
+export const createToast = params => {
+    console.log('createToast');
+    return new LS2Request().send({
+        service: 'luna://com.webos.notification/',
+        method: 'createToast',
+        parameters:{noaction:true, message:params},
+        onComplete: (res) => {
+            console.log(res);
+            return;
+        }
+    });
+};
+
+export const startServer = (dispatch) =>  {
+    const ls = LS2RequestSingleton.instance('startServer', true);
+    if (ls) {
+        ls.send({
+            service: 'luna://com.example.service.iotivity.server/',
+            method: 'startServer',
+            parameters: {
+                subscribe: true
+            },
+            onComplete: (res) => {
+                if (res.subscribed) {
+                    dispatch(actionUpdateServerState(true));
+                    return;
+                }
+            },
+        });
+    }
+};
+
+export const stopServer = (dispatch) =>  {
+    const ls = LS2RequestSingleton.instance('startServer');
+    if (ls) {
+        ls.cancel();
+        dispatch(actionUpdateServerState(false));
+        dispatch(actionResetDiscoveredList([]));
+        LS2RequestSingleton.deleteInstance('startServer');
+    }
+};
+
+export const discoverResources = (dispatch) =>  {
+    const ls = LS2RequestSingleton.instance('discoverResources', true);
+    if (ls) {
+        ls.send({
+            service: 'luna://com.example.service.iotivity.client/',
+            method: 'discoverResources',
+            parameters: {
+                subscribe: true
+            },
+            onComplete: (res) => {
+                dispatch(actionUpdateDiscoveredList(res.discoveryResponse));
+            },
+        });
+    }
+};
+
+export const resetDiscoveredList = (dispatch) =>  {
+    const ls = LS2RequestSingleton.instance('discoverResources');
+    const ls2 = LS2RequestSingleton.instance('observeResource');
+    if (ls) {
+        ls.cancel();
+        dispatch(actionResetDiscoveredList([]));
+        LS2RequestSingleton.deleteInstance('discoverResources');
+    }
+    if (ls2) {
+        ls2.cancel();
+        dispatch(actionResetDiscoveredList([]));
+        LS2RequestSingleton.deleteInstance('observeResource');
+    }
+};
+
+export const createResource = params => dispatch => {
+    console.log('createResource');
+    return new LS2Request().send({
+        service: 'luna://com.example.service.iotivity.server/',
+        method: 'createResource',
+        parameters:params,
+        onComplete: (res) => {
+            if(res.returnValue){
+                createToast(params.uri +" resource is ready");
+                console.log(res);
+                dispatch(actionEnableServerResourceControlUI());
+                               return;
+            }
+        }
+    });
+};
+
+export const deleteResource = params => dispatch => {
+    console.log('deleteServerResource');
+    return new LS2Request().send({
+        service: 'luna://com.example.service.iotivity.server/',
+        method: 'deleteResource',
+        parameters:params,
+        onComplete: (res) => {
+            if(res.returnValue){
+                createToast(params.uri +" resource is deleted");
+                console.log(res);
+                dispatch(actionEnableServerResourceControlUI());
+                return;
+            }
+        }
+    });
+};
+
+export const getResource = params => dispatch => {
+    console.log('getResource');
+    return new LS2Request().send({
+        service: 'luna://com.example.service.iotivity.client/',
+        method: 'getResource',
+        parameters:params,
+        onComplete: (res) => {
+            console.log(res);
+            if(res.response.payload){
+                dispatch(actionUpdateGetResourceResults(res.response));
+            }
+            else{
+                createToast("Fail to get resource");
+                dispatch(actionEnableClientResourceControlUI());
+            }
+            return;
+        }
+    });
+};
+
+export const requestDeleteResource = params => dispatch => {
+    console.log('requestDeleteResource');
+    return new LS2Request().send({
+        service: 'luna://com.example.service.iotivity.client/',
+        method: 'deleteResource',
+        parameters:params,
+        onComplete: (res) => {
+            if(res.returnValue){
+                createToast(params.uri +" resource is deleted");
+                console.log(res);
+                dispatch(actionDisableClientResourceControlUI());
+                return;
+            }
+        }
+    });
+};
+
+export const observeResource = params => dispatch => {
+    const ls = LS2RequestSingleton.instance('observeResource', true);
+    if (ls) {
+        ls.send({
+            service: 'luna://com.example.service.iotivity.client/',
+            method: 'observeResource',
+            parameters: {
+                subscribe:true,
+                uri:params.uri,
+                destination:params.destination
+            },
+            onComplete: (res) => {
+                console.log(res);
+                if(res.response.payload){
+                    dispatch(actionUpdateGetResourceResults(res.response));
+                }
+                else{
+                    createToast("Fail to observe resource");
+                    dispatch(actionEnableClientResourceControlUI());
+                }
+                return;
+            }
+        });
+    }
+};
+
+export const stopObserveResource = () =>  {
+    const ls = LS2RequestSingleton.instance('observeResource');
+    if (ls) {
+        ls.cancel();
+        LS2RequestSingleton.deleteInstance('observeResource');
+    }
+};
diff --git a/resource/csdk/stack/samples/webos/com.example.app.iotivity/src/actions/ActionTypes.js b/resource/csdk/stack/samples/webos/com.example.app.iotivity/src/actions/ActionTypes.js
new file mode 100644 (file)
index 0000000..0db73d2
--- /dev/null
@@ -0,0 +1,10 @@
+export const UPDATE_SERVER = 'UPDATE_SERVER';
+export const UPDATE_DISCOVERED_RESOURCES = 'UPDATE_DISCOVERED_RESOURCES';
+export const RESET_DISCOVERED_RESOURCES = 'RESET_DISCOVERED_RESOURCES';
+export const HIDE_SERVER_RESOURCE_CONTROL_UI = 'HIDE_SERVER_RESOURCE_CONTROL_UI';
+export const SHOW_SERVER_RESOURCE_CONTROL_UI = 'SHOW_SERVER_RESOURCE_CONTROL_UI';
+export const HIDE_CLIENT_RESOURCE_CONTROL_UI = 'HIDE_CLIENT_RESOURCE_CONTROL_UI';
+export const SHOW_CLIENT_RESOURCE_CONTROL_UI = 'SHOW_CLIENT_RESOURCE_CONTROL_UI';
+export const UPDATE_GET_RESOURCE_RESULTS='UPDATE_GET_RESOURCE_RESULTS';
+export const UPDATE_OBSERVE_RESOURCE_RESULTS='UPDATE_OBSERVE_RESOURCE_RESULTS';
+export const SHOW_RESOURCES_LIST='SHOW_RESOURCES_LIST';
\ No newline at end of file
diff --git a/resource/csdk/stack/samples/webos/com.example.app.iotivity/src/index.js b/resource/csdk/stack/samples/webos/com.example.app.iotivity/src/index.js
new file mode 100644 (file)
index 0000000..b475c4a
--- /dev/null
@@ -0,0 +1,40 @@
+import React from 'react';
+import {render} from 'react-dom';
+import {createStore, applyMiddleware, compose} from 'redux';
+import {Provider} from 'react-redux';
+import reducer from './reducer/Reducer';
+import thunkMiddleware from 'redux-thunk';
+
+import App from './App';
+
+const composeEnhancers = (typeof window === 'object' && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__) || compose;
+
+function configureStore (initialState) {
+    const ret = createStore(
+        reducer,
+        initialState,
+        composeEnhancers(
+            applyMiddleware(thunkMiddleware)
+        )
+    );
+
+    return ret;
+}
+
+const store = configureStore();
+
+let appElement = (
+    <Provider store={store}>
+        <App />
+    </Provider>
+);
+
+// In a browser environment, render instead of exporting
+if (typeof window !== 'undefined') {
+    render(
+        appElement,
+        document.getElementById('root')
+    );
+}
+
+export default appElement;
diff --git a/resource/csdk/stack/samples/webos/com.example.app.iotivity/src/reducer/Reducer.js b/resource/csdk/stack/samples/webos/com.example.app.iotivity/src/reducer/Reducer.js
new file mode 100644 (file)
index 0000000..bc83572
--- /dev/null
@@ -0,0 +1,45 @@
+import * as actions from './../actions/ActionTypes';
+
+const initialState = {
+    serverEnabled:false,
+    discoveredResources:null,
+    showDiscoveredResources:false,
+    enableServerResourceControlUI:true,
+    enableClientResourceControlUI:true,
+    detailResourceInfo:null,
+};
+
+let arr=[];
+
+export function reducer (state = initialState, action) {
+    switch (action.type) {
+        case actions.UPDATE_SERVER:
+            return Object.assign({}, state, {serverEnabled: action.payload.enabled});
+        case actions.UPDATE_DISCOVERED_RESOURCES:
+            if(action.payload.addr){
+                arr.push(action.payload);
+                return Object.assign({}, state, {discoveredResources: arr});
+            }
+            return state;
+        case actions.SHOW_RESOURCES_LIST:
+            return Object.assign({}, state, {showDiscoveredResources: true});
+        case actions.RESET_DISCOVERED_RESOURCES:
+            arr=[];
+            return Object.assign({}, state, {showDiscoveredResources: false, discoveredResources: null, detailResourceInfo:null});
+        case actions.HIDE_SERVER_RESOURCE_CONTROL_UI:
+            return Object.assign({}, state, {enableServerResourceControlUI: false});
+        case actions.SHOW_SERVER_RESOURCE_CONTROL_UI:
+            return Object.assign({}, state, {enableServerResourceControlUI: true});
+        case actions.HIDE_CLIENT_RESOURCE_CONTROL_UI:
+            return Object.assign({}, state, {enableClientResourceControlUI: false});
+        case actions.SHOW_CLIENT_RESOURCE_CONTROL_UI:
+            return Object.assign({}, state, {enableClientResourceControlUI: true, detailResourceInfo:null});
+        case actions.UPDATE_GET_RESOURCE_RESULTS:
+        case actions.UPDATE_OBSERVE_RESOURCE_RESULTS:
+            return Object.assign({}, state, {detailResourceInfo: action.payload.payload});
+        default:
+            return state;
+    }
+}
+
+export default reducer;
diff --git a/resource/csdk/stack/samples/webos/com.example.app.iotivity/src/views/Client.js b/resource/csdk/stack/samples/webos/com.example.app.iotivity/src/views/Client.js
new file mode 100644 (file)
index 0000000..deb07c0
--- /dev/null
@@ -0,0 +1,204 @@
+import React from 'react';
+import {connect} from 'react-redux';
+import PropTypes from 'prop-types';
+
+import Button from '@enact/moonstone/Button';
+import Divider from '@enact/moonstone/Divider';
+import CheckboxItem from '@enact/moonstone/CheckboxItem';
+import BodyText from '@enact/moonstone/BodyText';
+import SpotlightContainerDecorator from '@enact/moonstone/Scroller';
+import ExpandableInput from '@enact/moonstone/ExpandableInput';
+
+import * as ActionCreators from '../actions/ActionCreators';
+
+import Changeable from '@enact/ui/Changeable';
+import {Group} from '@enact/ui/Group';
+import {Layout} from '@enact/ui/Layout';
+
+const SelectableGroup = Changeable({mutable: true}, Group);
+let discoveredItems=[];
+
+class Client extends React.Component {
+    constructor (props) {
+        super(props);
+        this.state = {
+            isSelectDiscoveredItem:false,
+            selectedDiscoveredItemIndex:null,
+            resourceUri:null,
+            resourceQuestion:null,
+            requestResourceCompleted:true,
+        };
+    }
+    componentWillReceiveProps (props) {
+        console.log(props);
+        if(props.discoveredResources&&props.discoveredResources.length>0){
+            discoveredItems=[];
+            for(let i=0; i<props.discoveredResources.length; i++){
+                discoveredItems.push({
+                    value:props.discoveredResources[i],
+                    children:props.discoveredResources[i].addr.addr+" (port:"+props.discoveredResources[i].addr.port+")",
+                });
+            }
+        }
+        else {
+            discoveredItems=[];
+            this.setState({
+                isSelectDiscoveredItem:false,
+            });
+        }
+    }
+    resourceUriChanged(ev){
+        this.setState({
+            resourceUri: ev.value,
+            requestResourceCompleted:false,
+        });
+        console.log(this.state.resourceUri);
+    }
+    resourceQuestionChanged(ev){
+        this.setState({
+            resourceQuestion: ev.value,
+            requestResourceCompleted:false,
+        });
+        console.log(this.state.resourceQuestion);
+    }
+    getResource(){
+        let param={
+            uri:this.state.resourceUri,
+            question:this.state.resourceQuestion,
+            destination:this.state.selectedDiscoveredItemIndex.addr
+        }
+        this.props.actionDisableClientResourceControlUI();
+        this.props.getResource(param);
+        this.setState({
+            resourceUri: null,
+            resourceQuestion: null,
+            requestResourceCompleted:true,
+            isSelectDiscoveredItem:false,
+            selectedDiscoveredItemIndex: null,
+        });
+    }
+    requestDeleteResource(){
+        let param={
+            uri:this.state.resourceUri,
+            destination:this.state.selectedDiscoveredItemIndex.addr
+        }
+        this.props.actionDisableClientResourceControlUI();
+        this.props.requestDeleteResource(param);
+        this.setState({
+            resourceUri: null,
+            resourceQuestion: null,
+            resourceCompleted:true,
+            isSelectDiscoveredItem:false,
+            selectedDiscoveredItemIndex: null,
+        });
+    }
+    requestObserveResource(){
+        let param={
+            uri:this.state.resourceUri,
+            destination:this.state.selectedDiscoveredItemIndex.addr,
+        }
+        this.props.actionDisableClientResourceControlUI();
+        this.props.requestObserveResource(param);
+        this.setState({
+            resourceUri: null,
+            resourceQuestion: null,
+            resourceCompleted:true,
+            isSelectDiscoveredItem:false,
+            selectedDiscoveredItemIndex: null,
+        });
+    }
+    onSelectedResource (ev){
+        console.log(ev);
+        for(let i=0 ; i<this.props.discoveredResources.length; i++){
+            if(JSON.stringify(this.props.discoveredResources[i]).indexOf(ev.data.slice(0,30))>0){
+                console.log(this.props.discoveredResources[i]);
+                this.setState({
+                    isSelectDiscoveredItem:true,
+                    selectedDiscoveredItemIndex:this.props.discoveredResources[i]
+                });
+                console.log(this.state.selectedDiscoveredItemIndex);
+            }
+        }
+        this.props.actionEnableClientResourceControlUI();
+    }
+    render() {
+        const {discoveredResources,showDiscoveredResources,enableClientResourceControlUI,detailResourceInfo,...rest} = this.props;
+        const onToggleHandler=this.onSelectedResource.bind(this);
+        const onResourceUriChanged = this.resourceUriChanged.bind(this);
+        const onResourceQuestionChanged = this.resourceQuestionChanged.bind(this);
+        const onGetResourceTapped = this.getResource.bind(this);
+        const onDeleteResourceTapped = this.requestDeleteResource.bind(this);
+        const onObserveResourceTapped = this.requestObserveResource.bind(this);
+        return(
+            <div>
+                <Layout align="start">
+                    {showDiscoveredResources?
+                    <SpotlightContainerDecorator focusableScrollbar style={{"height":210+"px"}} direction="both" horizontalScrollbar="auto" verticalScrollbar="auto">
+                        <SelectableGroup
+                            childComponent={CheckboxItem}
+                            onSelect={onToggleHandler}
+                            selectedProp="selected"
+                            select="radio"
+                        >
+                        {discoveredItems}
+                        </SelectableGroup>
+                        <div style={{"paddingTop": 9+"px"}} >
+                            <Button small onClick={this.props.resetDiscoveredList}>OK</Button>
+                        </div>
+
+                    </SpotlightContainerDecorator>
+                    :<Button small onClick={this.props.discoverResources}>Discover Resources</Button>
+                    }
+                </Layout>
+                <Divider />
+                <Layout align="start">
+                    {this.state.isSelectDiscoveredItem&&enableClientResourceControlUI?
+                    <SpotlightContainerDecorator focusableScrollbar style={{"height":600+"px"}} direction="both" horizontalScrollbar="auto" verticalScrollbar="auto">
+                        <div>{JSON.stringify(this.state.selectedDiscoveredItemIndex.payload,null,4)}</div>
+                        <ExpandableInput title="uri" onChange={onResourceUriChanged} />
+                        <ExpandableInput title="question" onChange={onResourceQuestionChanged} />
+                        <div style={{"paddingTop": 9+"px"}}>
+                            <Button disabled={this.state.resourceUri&&this.state.resourceQuestion?false:true} small onClick={onGetResourceTapped}>get resource</Button>
+                            <Button disabled={this.state.resourceUri?false:true} small onClick={onDeleteResourceTapped}>delete resource</Button>
+                            <Button disabled={this.state.resourceUri?false:true} small onClick={onObserveResourceTapped}>observe resource</Button>
+                        </div>
+                    </SpotlightContainerDecorator>
+                    :null}
+                    {detailResourceInfo?
+                    <SpotlightContainerDecorator focusableScrollbar style={{"height":600+"px"}} direction="both" horizontalScrollbar="auto" verticalScrollbar="auto">
+                        <BodyText>{JSON.stringify(detailResourceInfo,null,4)}</BodyText>
+                    </SpotlightContainerDecorator>
+                    :null}
+                </Layout>
+            </div>
+        )
+    }
+}
+Client.propTypes = {
+    getResource: PropTypes.func,
+    requestDeleteResource: PropTypes.func,
+    requestObserveResource: PropTypes.func,
+    discoverResources: PropTypes.func,
+    resetDiscoveredList: PropTypes.func,
+    actionDisableCreateResourceUI: PropTypes.func,
+};
+const mapDispatchToProps = (dispatch) => {
+    return {
+        getResource: (params) => dispatch(ActionCreators.getResource(params)),
+        requestDeleteResource: (params) => dispatch(ActionCreators.requestDeleteResource(params)),
+        requestObserveResource: (params) => dispatch(ActionCreators.observeResource(params)),
+        discoverResources: () => ActionCreators.discoverResources(dispatch),
+        resetDiscoveredList: () => ActionCreators.resetDiscoveredList(dispatch),
+        actionDisableClientResourceControlUI: () => dispatch(ActionCreators.actionDisableClientResourceControlUI()),
+        actionEnableClientResourceControlUI: () => dispatch(ActionCreators.actionEnableClientResourceControlUI()),
+    };
+};
+let mapStateToProps = (state) => {
+    return {
+        discoveredResources:state.discoveredResources,
+        showDiscoveredResources:state.showDiscoveredResources,
+        detailResourceInfo:state.detailResourceInfo,
+        enableClientResourceControlUI:state.enableClientResourceControlUI,
+    };
+};
+export default connect(mapStateToProps, mapDispatchToProps)(Client);
diff --git a/resource/csdk/stack/samples/webos/com.example.app.iotivity/src/views/MainPanel.js b/resource/csdk/stack/samples/webos/com.example.app.iotivity/src/views/MainPanel.js
new file mode 100644 (file)
index 0000000..56a960d
--- /dev/null
@@ -0,0 +1,31 @@
+import React from 'react';
+import kind from '@enact/core/kind';
+
+import {Panel, Header} from '@enact/moonstone/Panels';
+import Divider from '@enact/moonstone/Divider';
+
+import Server from './Server';
+import Client from './Client';
+
+import {Layout, Cell} from '@enact/ui/Layout';
+
+const MainPanel = kind({
+    name: 'MainPanel',
+    render: () => (
+        <Panel>
+            <Header title="iotivity sampler" type="compact" />
+            <Layout align="start">
+                <Cell>
+                    <Divider casing="word">Server role</Divider>
+                    <Server />
+                </Cell>
+                <Cell>
+                    <Divider casing="word">Client role</Divider>
+                    <Client />
+                </Cell>
+            </Layout>
+        </Panel>
+    )
+});
+
+export default MainPanel;
diff --git a/resource/csdk/stack/samples/webos/com.example.app.iotivity/src/views/Server.js b/resource/csdk/stack/samples/webos/com.example.app.iotivity/src/views/Server.js
new file mode 100644 (file)
index 0000000..b5b2ef8
--- /dev/null
@@ -0,0 +1,186 @@
+import React from 'react';
+import {connect} from 'react-redux';
+import PropTypes from 'prop-types';
+
+import {MarqueeText} from '@enact/moonstone/Marquee';
+import Button from '@enact/moonstone/Button';
+import Divider from '@enact/moonstone/Divider';
+import ExpandableList from '@enact/moonstone/ExpandableList';
+import ExpandableInput from '@enact/moonstone/ExpandableInput';
+import SwitchItem from '@enact/moonstone/SwitchItem';
+
+import * as ActionCreators from '../actions/ActionCreators';
+
+import {Layout, Cell} from '@enact/ui/Layout';
+
+class Server extends React.Component {
+    constructor (props) {
+        super(props);
+        this.state = {
+            resourceUri: null,
+            resourceType: null,
+            resourceQuestion: null,
+            resourceAnswer:null,
+            resourceUpdateCompleted:true,
+            resourceObservable:false,
+        };
+    }
+    resourceTypeChanged(ev){
+        this.setState({
+            resourceType: ev.data,
+            resourceUpdateCompleted:false,
+        });
+        console.log(this.state.resourceType);
+    }
+    resourceUriChanged(ev){
+        this.setState({
+            resourceUri: ev.value,
+            resourceUpdateCompleted:false,
+        });
+        console.log(this.state.resourceUri);
+    }
+    resourceQuestionChanged(ev){
+        this.setState({
+            resourceQuestion: ev.value,
+            resourceUpdateCompleted:false,
+        });
+        console.log(this.state.resourceQuestion);
+    }
+    resourceAnswerChanged(ev){
+        this.setState({
+            resourceAnswer: ev.value,
+            resourceUpdateCompleted:false,
+        });
+        console.log(this.state.resourceAnswer);
+    }
+    resourceObservableChanged(ev){
+        //console.log(ev);
+        this.setState({
+            resourceObservable: ev.selected,
+            resourceUpdateCompleted:false,
+        });
+        console.log(this.state.resourceObservable);
+    }
+    createResource(){
+        let param={
+            uri:this.state.resourceUri,
+            question:this.state.resourceQuestion,
+            answer:this.state.resourceAnswer,
+            types:this.state.resourceType,
+            observable:this.state.resourceObservable
+        }
+        this.props.actionDisableServerResourceControlUI();
+        this.props.createResource(param);
+        this.setState({
+            resourceUri: null,
+            resourceType: null,
+            resourceQuestion: null,
+            resourceAnswer:null,
+            resourceObservable:false,
+            resourceUpdateCompleted:true,
+        });
+    }
+    deleteResource(){
+        let param={
+            uri:this.state.resourceUri,
+        }
+        this.props.actionDisableServerResourceControlUI();
+        this.props.deleteResource(param);
+        this.setState({
+            resourceUri: null,
+            resourceType: null,
+            resourceQuestion: null,
+            resourceAnswer:null,
+            resourceUpdateCompleted:true,
+        });
+    }
+    render() {
+        const {serverEnabled, enableServerResourceControlUI} = this.props;
+        const onResourceUriChanged = this.resourceUriChanged.bind(this);
+        const onResourceQuestionChanged = this.resourceQuestionChanged.bind(this);
+        const onResourceAnswerChanged = this.resourceAnswerChanged.bind(this);
+        const onResourceTypeChanged = this.resourceTypeChanged.bind(this);
+        const onObservableResourceChanged = this.resourceObservableChanged.bind(this);
+        const onCreateResourceTapped = this.createResource.bind(this);
+        const onDeleteResourceTapped = this.deleteResource.bind(this);
+        return(
+            <div>
+                <Layout align="start">
+                    <Cell shrink>
+                        {serverEnabled?
+                            <Button small onClick={this.props.stopServer}>stop server</Button>
+                            :<Button small onClick={this.props.startServer}>start server</Button>
+                        }
+                    </Cell>
+                    <Cell>
+                        {serverEnabled?
+                            <div style={{"lineHeight":60+"px"}}>
+                                <MarqueeText marqueeOn="render">Server is running</MarqueeText>
+                            </div>
+                            :null
+                        }
+                    </Cell>
+                </Layout>
+                <Layout align="start">
+                    <Cell>
+                    <Divider />
+                    {(serverEnabled&&enableServerResourceControlUI)?
+                        <div>
+                            <ExpandableInput title="uri" onChange={onResourceUriChanged} />
+                            <ExpandableList
+                                closeOnSelect
+                                onSelect={onResourceTypeChanged}
+                                select={'radio'}
+                                title={'type'}
+                            >
+                            {[
+                                {disabled:false, children: 'core.fan'},
+                                {disabled:false, children: 'core.light'},
+                            ]}
+                            </ExpandableList>
+                            <ExpandableInput title="question" noneText="ex) How many angels can dance on the head of a pin?" onChange={onResourceQuestionChanged} />
+                            <ExpandableInput title="answer" noneText="ex) As many as wanting." onChange={onResourceAnswerChanged} />
+                            <SwitchItem disabled={false} onToggle={onObservableResourceChanged}>observable</SwitchItem>
+                            <div style={{"paddingTop": 9+"px"}}>
+                                <Button
+                                    disabled={this.state.resourceQuestion&&this.state.resourceAnswer&&this.state.resourceUri&&this.state.resourceType?false:true}
+                                    small
+                                    onClick={onCreateResourceTapped}>
+                                    create resource
+                                </Button>
+                                <Button disabled={this.state.resourceUri?false:true} small onClick={onDeleteResourceTapped}>delete resource</Button>
+                            </div>
+                        </div>
+                        :null
+                    }
+                    </Cell>
+                </Layout>
+            </div>
+        )
+    }
+}
+Server.propTypes = {
+    startServer: PropTypes.func,
+    stopServer: PropTypes.func,
+    createResource: PropTypes.func,
+    deleteResource: PropTypes.func,
+    actionDisableServerResourceControlUI: PropTypes.func,
+};
+const mapDispatchToProps = (dispatch) => {
+    return {
+        startServer: () => ActionCreators.startServer(dispatch),
+        stopServer: () => ActionCreators.stopServer(dispatch),
+        createResource: (params) => dispatch(ActionCreators.createResource(params)),
+        deleteResource: (params) => dispatch(ActionCreators.deleteResource(params)),
+        actionDisableServerResourceControlUI: () => dispatch(ActionCreators.actionDisableServerResourceControlUI()),
+    };
+};
+let mapStateToProps = (state) => {
+    return {
+        serverEnabled:state.serverEnabled,
+        discoveredResources:state.discoveredResources,
+        showDiscoveredResources:state.showDiscoveredResources,
+        enableServerResourceControlUI:state.enableServerResourceControlUI,
+    };
+};
+export default connect(mapStateToProps, mapDispatchToProps)(Server);
diff --git a/resource/csdk/stack/samples/webos/secure/SConscript b/resource/csdk/stack/samples/webos/secure/SConscript
new file mode 100644 (file)
index 0000000..a297dcd
--- /dev/null
@@ -0,0 +1,24 @@
+#******************************************************************
+#
+# Copyright (c) 2018 LG Electronics, Inc.
+#
+#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+#
+# 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
+#
+#      https://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.
+#
+#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+Import('stacksamples_env')
+
+SConscript('ocserverbasicops/SConscript', 'stacksamples_env')
+SConscript('occlientbasicops/SConscript', 'stacksamples_env')
diff --git a/resource/csdk/stack/samples/webos/secure/common.cpp b/resource/csdk/stack/samples/webos/secure/common.cpp
new file mode 100644 (file)
index 0000000..9a214a6
--- /dev/null
@@ -0,0 +1,143 @@
+/*******************************************************************
+ *
+ * Copyright (c) 2018 LG Electronics, Inc.
+ * Copyright 2014 Intel Mobile Communications GmbH 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
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+
+#include "common.h"
+
+#include "ocstack.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+
+/// This example is using experimental API, so there is no guarantee of support for future release,
+/// nor any there any guarantee that breaking changes will not occur across releases.
+#include "experimental/logger.h"
+
+#define TAG "sample-common"
+
+const char *getResult(OCStackResult result) {
+    switch (result) {
+    case OC_STACK_OK:
+        return "OC_STACK_OK";
+    case OC_STACK_RESOURCE_CREATED:
+        return "OC_STACK_RESOURCE_CREATED";
+    case OC_STACK_RESOURCE_DELETED:
+        return "OC_STACK_RESOURCE_DELETED";
+    case OC_STACK_CONTINUE:
+        return "OC_STACK_CONTINUE";
+    case OC_STACK_RESOURCE_CHANGED:
+        return "OC_STACK_RESOURCE_CHANGED";
+    case OC_STACK_INVALID_URI:
+        return "OC_STACK_INVALID_URI";
+    case OC_STACK_INVALID_QUERY:
+        return "OC_STACK_INVALID_QUERY";
+    case OC_STACK_INVALID_IP:
+        return "OC_STACK_INVALID_IP";
+    case OC_STACK_INVALID_PORT:
+        return "OC_STACK_INVALID_PORT";
+    case OC_STACK_INVALID_CALLBACK:
+        return "OC_STACK_INVALID_CALLBACK";
+    case OC_STACK_INVALID_METHOD:
+        return "OC_STACK_INVALID_METHOD";
+    case OC_STACK_INVALID_PARAM:
+        return "OC_STACK_INVALID_PARAM";
+    case OC_STACK_INVALID_OBSERVE_PARAM:
+        return "OC_STACK_INVALID_OBSERVE_PARAM";
+    case OC_STACK_NO_MEMORY:
+        return "OC_STACK_NO_MEMORY";
+    case OC_STACK_COMM_ERROR:
+        return "OC_STACK_COMM_ERROR";
+    case OC_STACK_TIMEOUT:
+        return "OC_STACK_TIMEOUT";
+    case OC_STACK_ADAPTER_NOT_ENABLED:
+        return "OC_STACK_ADAPTER_NOT_ENABLED";
+    case OC_STACK_NOTIMPL:
+        return "OC_STACK_NOTIMPL";
+    case OC_STACK_NO_RESOURCE:
+        return "OC_STACK_NO_RESOURCE";
+    case OC_STACK_RESOURCE_ERROR:
+        return "OC_STACK_RESOURCE_ERROR";
+    case OC_STACK_SLOW_RESOURCE:
+        return "OC_STACK_SLOW_RESOURCE";
+    case OC_STACK_DUPLICATE_REQUEST:
+        return "OC_STACK_DUPLICATE_REQUEST";
+    case OC_STACK_NO_OBSERVERS:
+        return "OC_STACK_NO_OBSERVERS";
+    case OC_STACK_OBSERVER_NOT_FOUND:
+        return "OC_STACK_OBSERVER_NOT_FOUND";
+    case OC_STACK_VIRTUAL_DO_NOT_HANDLE:
+        return "OC_STACK_VIRTUAL_DO_NOT_HANDLE";
+    case OC_STACK_INVALID_OPTION:
+        return "OC_STACK_INVALID_OPTION";
+    case OC_STACK_MALFORMED_RESPONSE:
+        return "OC_STACK_MALFORMED_RESPONSE";
+    case OC_STACK_INVALID_REQUEST_HANDLE:
+        return "OC_STACK_INVALID_REQUEST_HANDLE";
+    case OC_STACK_INVALID_DEVICE_INFO:
+        return "OC_STACK_INVALID_DEVICE_INFO";
+    case OC_STACK_INVALID_JSON:
+        return "OC_STACK_INVALID_JSON";
+    case OC_STACK_UNAUTHORIZED_REQ:
+        return "OC_STACK_UNAUTHORIZED_REQ";
+    case OC_STACK_TOO_LARGE_REQ:
+        return "OC_STACK_TOO_LARGE_REQ";
+    #ifdef WITH_PRESENCE
+    case OC_STACK_PRESENCE_STOPPED:
+        return "OC_STACK_PRESENCE_STOPPED";
+    case OC_STACK_PRESENCE_TIMEOUT:
+        return "OC_STACK_PRESENCE_TIMEOUT";
+    case OC_STACK_PRESENCE_DO_NOT_HANDLE:
+        return "OC_STACK_PRESENCE_DO_NOT_HANDLE";
+    #endif
+    case OC_STACK_USER_DENIED_REQ:
+        return "OC_STACK_USER_DENIED_REQ";
+    case OC_STACK_NOT_ACCEPTABLE:
+        return "OC_STACK_NOT_ACCEPTABLE";
+    case OC_STACK_FORBIDDEN_REQ:
+        return "OC_STACK_FORBIDDEN_REQ";
+    case OC_STACK_INTERNAL_SERVER_ERROR:
+        return "OC_STACK_INTERNAL_SERVER_ERROR";
+    case OC_STACK_GATEWAY_TIMEOUT:
+        return "OC_STACK_GATEWAY_TIMEOUT";
+    case OC_STACK_SERVICE_UNAVAILABLE:
+        return "OC_STACK_SERVICE_UNAVAILABLE";
+    case OC_STACK_ERROR:
+        return "OC_STACK_ERROR";
+    default:
+        return "UNKNOWN";
+    }
+}
+
+void StripNewLineChar(char* str) {
+    int i = 0;
+    if (str)
+    {
+        while( str[i])
+        {
+            if (str[i] == '\n')
+                str[i] = '\0';
+            i++;
+        }
+    }
+}
+
diff --git a/resource/csdk/stack/samples/webos/secure/common.h b/resource/csdk/stack/samples/webos/secure/common.h
new file mode 100644 (file)
index 0000000..ed773b1
--- /dev/null
@@ -0,0 +1,36 @@
+/*******************************************************************
+ *
+ * Copyright (c) 2018 LG Electronics, Inc.
+ * Copyright 2014 Intel Mobile Communications GmbH 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
+ *
+ *      https://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 OCSAMPLE_COMMON_H_
+#define OCSAMPLE_COMMON_H_
+
+#include "ocstack.h"
+
+/* Get the result in string format. */
+const char *getResult(OCStackResult result);
+
+/* Removes the new line character from a NULL terminated C string. */
+void StripNewLineChar(char* str);
+
+#endif //OCSAMPLE_COMMON_H_
+
+
diff --git a/resource/csdk/stack/samples/webos/secure/files/sysbus/occlientbasicops.api.json b/resource/csdk/stack/samples/webos/secure/files/sysbus/occlientbasicops.api.json
new file mode 100644 (file)
index 0000000..2c63c08
--- /dev/null
@@ -0,0 +1,2 @@
+{
+}
diff --git a/resource/csdk/stack/samples/webos/secure/files/sysbus/occlientbasicops.manifest.json b/resource/csdk/stack/samples/webos/secure/files/sysbus/occlientbasicops.manifest.json
new file mode 100644 (file)
index 0000000..e2f1130
--- /dev/null
@@ -0,0 +1,16 @@
+{
+    "serviceFiles": [
+        "/usr/share/luna-service2/services.d/occlientbasicops.service"
+    ],
+    "roleFiles": [
+        "/usr/share/luna-service2/roles.d/occlientbasicops.role.json"
+    ],
+    "apiPermissionFiles": [
+        "/usr/share/luna-service2/api-permissions.d/occlientbasicops.api.json"
+    ],
+    "version": "1.0.0",
+    "id": "occlientbasicops",
+    "clientPermissionFiles": [
+        "/usr/share/luna-service2/client-permissions.d/occlientbasicops.perm.json"
+    ]
+}
diff --git a/resource/csdk/stack/samples/webos/secure/files/sysbus/occlientbasicops.perm.json b/resource/csdk/stack/samples/webos/secure/files/sysbus/occlientbasicops.perm.json
new file mode 100644 (file)
index 0000000..37aab83
--- /dev/null
@@ -0,0 +1,5 @@
+{
+    "org.ocf.webossample.occlientbasicops*": [
+        "networking.internal"
+    ]
+}
diff --git a/resource/csdk/stack/samples/webos/secure/files/sysbus/occlientbasicops.role.json b/resource/csdk/stack/samples/webos/secure/files/sysbus/occlientbasicops.role.json
new file mode 100644 (file)
index 0000000..0d87b01
--- /dev/null
@@ -0,0 +1,11 @@
+{
+    "exeName":"/usr/palm/services/org.ocf.webossample.occlientbasicops//occlientbasicops",
+    "type":"regular",
+    "allowedNames":["org.ocf.webossample.occlientbasicops*"],
+    "permissions": [
+        {
+            "service":"org.ocf.webossample.occlientbasicops*",
+            "outbound":["com.webos.service.connectionmanager"]
+        }
+    ]
+}
diff --git a/resource/csdk/stack/samples/webos/secure/files/sysbus/occlientbasicops.service b/resource/csdk/stack/samples/webos/secure/files/sysbus/occlientbasicops.service
new file mode 100644 (file)
index 0000000..cedab9e
--- /dev/null
@@ -0,0 +1,24 @@
+#******************************************************************
+#
+# Copyright (c) 2018 LG Electronics, Inc.
+#
+#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+#
+# 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
+#
+#      https://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.
+#
+#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+[D-BUS Service]
+Name=org.ocf.webossample.occlientbasicops*
+Exec=/usr/palm/services/org.ocf.webossample.occlientbasicops/occlientbasicops
+Type=static
diff --git a/resource/csdk/stack/samples/webos/secure/files/sysbus/ocserverbasicops.api.json b/resource/csdk/stack/samples/webos/secure/files/sysbus/ocserverbasicops.api.json
new file mode 100644 (file)
index 0000000..2c63c08
--- /dev/null
@@ -0,0 +1,2 @@
+{
+}
diff --git a/resource/csdk/stack/samples/webos/secure/files/sysbus/ocserverbasicops.manifest.json b/resource/csdk/stack/samples/webos/secure/files/sysbus/ocserverbasicops.manifest.json
new file mode 100644 (file)
index 0000000..8dadac8
--- /dev/null
@@ -0,0 +1,16 @@
+{
+    "serviceFiles": [
+        "/usr/share/luna-service2/services.d/ocserverbasicops.service"
+    ],
+    "roleFiles": [
+        "/usr/share/luna-service2/roles.d/ocserverbasicops.role.json"
+    ],
+    "apiPermissionFiles": [
+        "/usr/share/luna-service2/api-permissions.d/ocserverbasicops.api.json"
+    ],
+    "version": "1.0.0",
+    "id": "ocserverbasicops",
+    "clientPermissionFiles": [
+        "/usr/share/luna-service2/client-permissions.d/ocserverbasicops.perm.json"
+    ]
+}
diff --git a/resource/csdk/stack/samples/webos/secure/files/sysbus/ocserverbasicops.perm.json b/resource/csdk/stack/samples/webos/secure/files/sysbus/ocserverbasicops.perm.json
new file mode 100644 (file)
index 0000000..212f0cd
--- /dev/null
@@ -0,0 +1,5 @@
+{
+    "org.ocf.webossample.ocserverbasicops*": [
+        "networking.internal"
+    ]
+}
diff --git a/resource/csdk/stack/samples/webos/secure/files/sysbus/ocserverbasicops.role.json b/resource/csdk/stack/samples/webos/secure/files/sysbus/ocserverbasicops.role.json
new file mode 100644 (file)
index 0000000..be1346b
--- /dev/null
@@ -0,0 +1,11 @@
+{
+    "exeName":"/usr/palm/services/org.ocf.webossample.ocserverbasicops/ocserverbasicops",
+    "type":"regular",
+    "allowedNames":["org.ocf.webossample.ocserverbasicops*"],
+    "permissions": [
+        {
+            "service":"org.ocf.webossample.ocserverbasicops*",
+            "outbound":["com.webos.service.connectionmanager"]
+        }
+    ]
+}
diff --git a/resource/csdk/stack/samples/webos/secure/files/sysbus/ocserverbasicops.service b/resource/csdk/stack/samples/webos/secure/files/sysbus/ocserverbasicops.service
new file mode 100644 (file)
index 0000000..399712f
--- /dev/null
@@ -0,0 +1,24 @@
+#******************************************************************
+#
+# Copyright (c) 2018 LG Electronics, Inc.
+#
+#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+#
+# 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
+#
+#      https://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.
+#
+#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+[D-BUS Service]
+Name=org.ocf.webossample.ocserverbasicops*
+Exec=/usr/palm/services/org.ocf.webossample.ocserverbasicops/ocserverbasicops
+Type=static
diff --git a/resource/csdk/stack/samples/webos/secure/occlientbasicops/SConscript b/resource/csdk/stack/samples/webos/secure/occlientbasicops/SConscript
new file mode 100644 (file)
index 0000000..74e1596
--- /dev/null
@@ -0,0 +1,107 @@
+#******************************************************************
+#
+# Copyright (c) 2018 LG Electronics, Inc.
+# Copyright 2014 Intel Mobile Communications GmbH 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
+#
+#      https://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.
+#
+#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+Import('stacksamples_env')
+
+samples_env = stacksamples_env.Clone()
+
+######################################################################
+# Build flags
+######################################################################
+samples_env.PrependUnique(CPPPATH=[
+    '../../../../../logger/include',
+    '../../../../../include',
+    '../../../../../stack/include',
+    '../../../../../security/include',
+    '../../../../../../oc_logger/include',
+    '../'
+])
+
+target_os = samples_env.get('TARGET_OS')
+if target_os not in ['windows']:
+    samples_env.AppendUnique(CXXFLAGS=['-std=c++0x', '-Wall', '-pthread'])
+
+    # Note: 'pthread' is in libc for android.
+    if target_os != 'android':
+        samples_env.AppendUnique(LIBS=['pthread'])
+    samples_env.Append(LINKFLAGS=['-Wl,--no-as-needed'])
+
+if target_os in ['windows', 'msys_nt']:
+    samples_env.PrependUnique(LIBS=['coap', 'ocsrm'])
+else:
+    samples_env.PrependUnique(LIBS=['connectivity_abstraction', 'coap', 'm'])
+
+samples_env.PrependUnique(LIBS=['octbstack'])
+
+if samples_env.get('SECURED') == '1':
+    samples_env.AppendUnique(LIBS=['mbedtls', 'mbedx509', 'mbedcrypto'])
+
+if target_os == 'android':
+    samples_env.AppendUnique(CXXFLAGS=['-frtti', '-fexceptions'])
+    samples_env.AppendUnique(LIBS=['gnustl_shared'])
+    samples_env.AppendUnique(
+        CPPDEFINES=['_GLIBCXX_USE_C99=1', '_GLIBCXX_HAVE_WCSTOF=1'])
+
+    if not samples_env.get('RELEASE'):
+        samples_env.AppendUnique(LIBS=['log'])
+
+if target_os in ['darwin', 'ios']:
+    samples_env.AppendUnique(CPPDEFINES=['_DARWIN_C_SOURCE'])
+
+samples_env.AppendUnique(CPPDEFINES=['TB_LOG'])
+
+samples_env.ParseConfig("pkg-config --cflags --libs glib-2.0")
+samples_env.ParseConfig("pkg-config --cflags --libs luna-service2")
+samples_env.ParseConfig("pkg-config --cflags --libs pbnjson_c")
+
+######################################################################
+# Source files and Targets
+######################################################################
+
+occlientbasicops = samples_env.Program(
+    'occlientbasicops', ['../common.cpp', 'occlientbasicops.cpp'])
+
+ocsamples = [occlientbasicops]
+Alias("samples", ocsamples)
+samples_env.AppendTarget('samples')
+
+src_dir = samples_env.get('SRC_DIR')
+sec_samples_src_dir = src_dir + '/resource/csdk/stack/samples/linux/secure/'
+sec_samples_build_dir = samples_env.get(
+    'BUILD_DIR') + '/resource/csdk/stack/samples/linux/secure'
+
+samples_env.Alias(
+    "install",
+    samples_env.Install(sec_samples_build_dir,
+                        sec_samples_src_dir + 'oic_svr_db_client_devowner.json'))
+samples_env.Alias(
+    "install",
+    samples_env.Install(sec_samples_build_dir,
+                        sec_samples_src_dir + 'oic_svr_db_client_nondevowner.json'))
+
+samples_env.Alias(
+    "install",
+    samples_env.Install(sec_samples_build_dir,
+                        sec_samples_src_dir + 'oic_svr_db_client_devowner.dat'))
+samples_env.Alias(
+    "install",
+    samples_env.Install(sec_samples_build_dir,
+                        sec_samples_src_dir + 'oic_svr_db_client_nondevowner.dat'))
diff --git a/resource/csdk/stack/samples/webos/secure/occlientbasicops/logging.h b/resource/csdk/stack/samples/webos/secure/occlientbasicops/logging.h
new file mode 100644 (file)
index 0000000..455b268
--- /dev/null
@@ -0,0 +1,69 @@
+/*******************************************************************
+ *
+ * Copyright (c) 2018 LG Electronics, Inc.
+ *
+ *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ *
+ * 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
+ *
+ *      https://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 __LOGGING_H__
+#define __LOGGING_H__
+
+#include <PmLogLib.h>
+
+extern PmLogContext gLogContext;
+
+/* Logging for ocserverbasciops context ********
+ * The parameters needed are
+ * msgid - unique message id
+ * kvcount - count for key-value pairs
+ * ... - key-value pairs and free text. key-value pairs are formed using PMLOGKS or PMLOGKFV
+ * e.g.)
+ * WCALOG_CRITICAL(msgid, 2, PMLOGKS("key1", "value1"), PMLOGKFV("key2", "%d", value2), "free text message");
+ **********************************************/
+#define OCSAMPLE_LOG_CRITICAL(msgid, kvcount, ...) \
+        PmLogCritical(gLogContext, msgid, kvcount, ##__VA_ARGS__)
+
+#define OCSAMPLE_LOG_ERROR(msgid, kvcount, ...) \
+        PmLogError(gLogContext, msgid, kvcount,##__VA_ARGS__)
+
+#define OCSAMPLE_LOG_WARNING(msgid, kvcount, ...) \
+        PmLogWarning(gLogContext, msgid, kvcount, ##__VA_ARGS__)
+
+#define OCSAMPLE_LOG_INFO(msgid, kvcount, ...) \
+        PmLogInfo(gLogContext, msgid, kvcount, ##__VA_ARGS__)
+
+#define OCSAMPLE_LOG_DEBUG(...) \
+        PmLogDebug(gLogContext, ##__VA_ARGS__)
+
+#define OCSAMPLE_LOG_ESCAPED_ERRMSG(msgid, errmsg) \
+    do { \
+    gchar *escaped_errtext = g_strescape(errmsg, NULL); \
+    WCALOG_ERROR(msgid, 1, PMLOGKS("Error", escaped_errtext), ""); \
+    g_free(escaped_errtext); \
+    } while(0)
+
+#define OCSAMPLE_LOG_ADDR_INFOMSG(msgid, name, addr) \
+    do { \
+    gchar straddr[16]; \
+    snprintf(straddr, 16, "%p", addr); \
+    WCALOG_INFO(msgid, 1, PMLOGKS(name, straddr), ""); \
+    } while(0)
+
+/** list of MSGID's */
+#define MSGID_WIFI_SRVC_REGISTER_FAIL                   "WIFI_SRVC_REGISTER_FAIL"
+
+#endif // __LOGGING_H__
diff --git a/resource/csdk/stack/samples/webos/secure/occlientbasicops/occlientbasicops.cpp b/resource/csdk/stack/samples/webos/secure/occlientbasicops/occlientbasicops.cpp
new file mode 100644 (file)
index 0000000..5c434f5
--- /dev/null
@@ -0,0 +1,612 @@
+/*******************************************************************
+ *
+ * Copyright (c) 2018 LG Electronics, Inc.
+ * Copyright 2014 Intel Mobile Communications GmbH 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
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+
+#include "iotivity_config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <iostream>
+#include <sstream>
+#include <getopt.h>
+#include "ocstack.h"
+#include "occlientbasicops.h"
+#include "ocpayload.h"
+#include "sample_payload_logging.h"
+#include "oic_string.h"
+#include "common.h"
+
+
+/// This example is using experimental API, so there is no guarantee of support for future release,
+/// nor any there any guarantee that breaking changes will not occur across releases.
+#include "experimental/logger.h"
+
+#include <luna-service2/lunaservice.h>
+#include <pbnjson.h>
+#include <pthread.h>
+#include "logging.h"
+
+pthread_t threadId_client;
+PmLogContext gLogContext;
+
+#define TAG "occlientbasicops"
+static int UnicastDiscovery = 0;
+static int TestCase = 0;
+static int ConnType = 0;
+static int DevOwner = 0;
+static int WithTcp = 0;
+
+static char DISCOVERY_QUERY[] = "%s/oic/res";
+OCConnectivityType discoveryReqConnType = CT_ADAPTER_IP;
+
+static std::string coapServerResource;
+static int coapSecureResource;
+static OCConnectivityType ocConnType;
+
+//Secure Virtual Resource database for Iotivity Client application
+//It contains Client's Identity and the PSK credentials
+//of other devices which the client trusts
+static char CRED_FILE_DEVOWNER[] = "oic_svr_db_client_devowner.dat";
+static char CRED_FILE_NONDEVOWNER[] = "oic_svr_db_client_nondevowner.dat";
+
+//Standard uri prefix for secure virtual resources
+const char * OIC_STD_URI_PREFIX = "/oic/";
+
+const char * COAPS_STR = "coaps";
+#ifdef __WITH_TLS__
+const char * COAPS_TCP_STR = "coaps+tcp";
+#endif
+
+int gQuitFlag = 0;
+const char * COAPS_TCP_STR = "coaps+tcp";
+
+static LSHandle *pLsHandle = NULL;
+static GMainLoop *mainloop = NULL;
+static const char *gResourceUri = "/a/led";
+
+/* SIGINT handler: set gQuitFlag to 1 for graceful termination */
+void handleSigInt(int signum)
+{
+    if (signum == SIGINT)
+    {
+        gQuitFlag = 1;
+        g_main_loop_quit(mainloop);
+    }
+}
+
+OCPayload *putPayload()
+{
+    OCRepPayload *payload = OCRepPayloadCreate();
+
+    if (!payload)
+    {
+        std::cout << "Failed to create put payload object" << std::endl;
+        std::exit(1);
+    }
+
+    OCRepPayloadSetPropInt(payload, "power", 15);
+    OCRepPayloadSetPropBool(payload, "state", true);
+
+    return (OCPayload *) payload;
+}
+
+static void PrintUsage()
+{
+    printf("Usage : occlient -u <0|1> -t <1|2|3> -c <0|1>\n");
+    printf("-u <0|1> : Perform multicast/unicast discovery of resources\n");
+    printf("-t 1 : Discover Resources\n");
+    printf("-t 2 : Discover Resources and\n"
+            " Initiate Nonconfirmable Get/Put/Post Requests\n");
+    printf("-t 3 : Discover Resources and Initiate Confirmable Get/Put/Post Requests\n");
+    printf("-c 0 : Default auto-selection\n");
+    printf("-c 1 : IP Connectivity Type\n");
+    printf("-d 0 : Client as Non Device Owner\n");
+    printf("-d 1 : Client as Device Owner\n");
+    printf("-p 0 : Use UDP protocol\n");
+    printf("-p 1 : Use TCP protocol\n");
+}
+
+OCStackResult InvokeOCDoResource(std::ostringstream &query,
+                                 OCMethod method,
+                                 const OCDevAddr *dest,
+                                 OCQualityOfService qos,
+                                 OCClientResponseHandler cb,
+                                 OCHeaderOption *options, uint8_t numOptions)
+{
+    OCStackResult ret;
+    OCCallbackData cbData;
+
+    cbData.cb = cb;
+    cbData.context = NULL;
+    cbData.cd = NULL;
+
+    OCPayload *payload = (method == OC_REST_PUT || method == OC_REST_POST) ? putPayload() : NULL;
+
+    ret = OCDoRequest(NULL, method, query.str().c_str(), dest,
+                      payload, ocConnType, qos, &cbData, options, numOptions);
+
+    OCPayloadDestroy(payload);
+
+    if (ret != OC_STACK_OK)
+    {
+        OCSAMPLE_LOG_ERROR(TAG, 0, "OCDoResource returns error %d with method %d", ret, method);
+    }
+
+    return ret;
+}
+
+OCStackApplicationResult putReqCB(void *, OCDoHandle, OCClientResponse *clientResponse)
+{
+    OCSAMPLE_LOG_INFO(TAG, 0, "Callback Context for PUT recvd successfully");
+
+    if (clientResponse)
+    {
+        OCSAMPLE_LOG_INFO(TAG, 0, "StackResult: %s",  getResult(clientResponse->result));
+        OCSAMPLE_LOG_PAYLOAD(INFO, clientResponse->payload);
+        OCSAMPLE_LOG_INFO(TAG, 0, "=============> Put Response");
+    }
+    return OC_STACK_DELETE_TRANSACTION;
+}
+
+OCStackApplicationResult postReqCB(void *, OCDoHandle, OCClientResponse *clientResponse)
+{
+    OCSAMPLE_LOG_INFO(TAG, 0, "Callback Context for POST recvd successfully");
+
+    if (clientResponse)
+    {
+        OCSAMPLE_LOG_INFO(TAG, 0, "StackResult: %s",  getResult(clientResponse->result));
+        OCSAMPLE_LOG_PAYLOAD(INFO, clientResponse->payload);
+        OCSAMPLE_LOG_INFO(TAG, 0, "=============> Post Response");
+    }
+    return OC_STACK_DELETE_TRANSACTION;
+}
+
+OCStackApplicationResult getReqCB(void *, OCDoHandle, OCClientResponse *clientResponse)
+{
+    OCSAMPLE_LOG_INFO(TAG, 0, "Callback Context for GET query recvd successfully");
+
+    if (clientResponse)
+    {
+        OCSAMPLE_LOG_INFO(TAG, 0, "StackResult: %s",  getResult(clientResponse->result));
+        OCSAMPLE_LOG_INFO(TAG, 0, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
+        OCSAMPLE_LOG_PAYLOAD(INFO, clientResponse->payload);
+        OCSAMPLE_LOG_INFO(TAG, 0, "=============> Get Response");
+    }
+    return OC_STACK_DELETE_TRANSACTION;
+}
+
+// This is a function called back when a device is discovered
+OCStackApplicationResult discoveryReqCB(void *, OCDoHandle,
+                                        OCClientResponse *clientResponse)
+{
+    OCSAMPLE_LOG_INFO(TAG, 0, "Callback Context for DISCOVER query recvd successfully");
+
+    if (clientResponse)
+    {
+        OCSAMPLE_LOG_INFO(TAG, 0, "StackResult: %s", getResult(clientResponse->result));
+        OCSAMPLE_LOG_INFO(TAG, 0,
+                  "Device =============> Discovered @ %s:%d",
+                  clientResponse->devAddr.addr,
+                  clientResponse->devAddr.port);
+
+        if (clientResponse->result == OC_STACK_OK)
+        {
+            OCSAMPLE_LOG_PAYLOAD(INFO, clientResponse->payload);
+
+            ocConnType = clientResponse->connType;
+
+            if (parseClientResponse(clientResponse) != -1)
+            {
+                OCDiscoveryPayload *payload = (OCDiscoveryPayload *) clientResponse->payload;
+                OCResourcePayload *resource = (OCResourcePayload *) payload->resources;
+                for (;resource; resource = resource->next)
+                {
+                    if ((0 == strcmp(gResourceUri, resource->uri))
+                         && (0 == strcmp(COAPS_STR, resource->eps->tps)))
+                    {
+                        OCDevAddr* endpoint = &clientResponse->devAddr;
+                        strcpy(endpoint->addr, resource->eps->addr);
+                        endpoint->port = resource->eps->port;
+                        endpoint->flags = resource->eps->family;
+
+                        switch (TestCase)
+                        {
+                        case TEST_NON_CON_OP:
+                            InitGetRequest(endpoint, OC_LOW_QOS);
+                            InitPutRequest(endpoint, OC_LOW_QOS);
+                            InitPostRequest(endpoint, OC_LOW_QOS);
+                            break;
+                        case TEST_CON_OP:
+                            InitGetRequest(endpoint, OC_HIGH_QOS);
+                            InitPutRequest(endpoint, OC_HIGH_QOS);
+                            InitPostRequest(endpoint, OC_HIGH_QOS);
+
+                        break;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    return (UnicastDiscovery) ? OC_STACK_DELETE_TRANSACTION : OC_STACK_KEEP_TRANSACTION ;
+
+}
+int InitPutRequest(OCDevAddr *endpoint, OCQualityOfService qos)
+{
+    OCSAMPLE_LOG_INFO(TAG, 0, "Executing %s", __func__);
+    std::ostringstream query;
+    query << coapServerResource;
+
+    return (InvokeOCDoResource(query, OC_REST_PUT, endpoint,
+                               ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS : OC_LOW_QOS), putReqCB, NULL, 0));
+}
+
+int InitPostRequest(OCDevAddr *endpoint, OCQualityOfService qos)
+{
+    OCStackResult result;
+
+    OCSAMPLE_LOG_INFO(TAG, 0, "Executing %s", __func__);
+    std::ostringstream query;
+    query << coapServerResource;
+
+    // First PUT operation (to create an LED instance)
+    result = InvokeOCDoResource(query, OC_REST_PUT, endpoint,
+                                ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS : OC_LOW_QOS),
+                                putReqCB, NULL, 0);
+    if (OC_STACK_OK != result)
+    {
+        // Error can happen if for example, network connectivity is down
+        OCSAMPLE_LOG_INFO(TAG, 0, "First POST call did not succeed");
+    }
+
+    // Second PUT operation (to create an LED instance)
+    result = InvokeOCDoResource(query, OC_REST_PUT, endpoint,
+                                ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS : OC_LOW_QOS),
+                                putReqCB, NULL, 0);
+    if (OC_STACK_OK != result)
+    {
+        OCSAMPLE_LOG_INFO(TAG, 0, "Second POST call did not succeed");
+    }
+
+    // This POST operation will update the original resourced /a/led (as long as
+    // the server is set to max 2 /lcd resources)
+    result = InvokeOCDoResource(query, OC_REST_POST, endpoint,
+                                ((qos == OC_HIGH_QOS) ? OC_HIGH_QOS : OC_LOW_QOS),
+                                postReqCB, NULL, 0);
+    if (OC_STACK_OK != result)
+    {
+        OCSAMPLE_LOG_INFO(TAG, 0, "Third POST call did not succeed");
+    }
+    return result;
+}
+
+int InitGetRequest(OCDevAddr *endpoint, OCQualityOfService qos)
+{
+    OCSAMPLE_LOG_INFO(TAG, 0, "Executing %s", __func__);
+    std::ostringstream query;
+    query << coapServerResource;
+
+    return (InvokeOCDoResource(query, OC_REST_GET, endpoint,
+                               ((qos == OC_HIGH_QOS) ?  OC_HIGH_QOS : OC_LOW_QOS),
+                               getReqCB, NULL, 0));
+}
+
+int InitDiscovery()
+{
+    OCStackResult ret;
+    OCCallbackData cbData;
+    char queryUri[200];
+    char ipaddr[100] = { '\0' };
+
+    if (UnicastDiscovery)
+    {
+        OCSAMPLE_LOG_INFO(TAG, 0, "Enter IP address (with optional port) of the Server hosting resource\n");
+        OCSAMPLE_LOG_INFO(TAG, 0, "IPv4: 192.168.0.15:45454\n");
+        OCSAMPLE_LOG_INFO(TAG, 0, "IPv6: [fe80::20c:29ff:fe1b:9c5]:45454\n");
+
+        if (fgets(ipaddr, sizeof (ipaddr), stdin))
+        {
+            StripNewLineChar(ipaddr); //Strip newline char from ipaddr
+        }
+        else
+        {
+            OCSAMPLE_LOG_ERROR(TAG, 0, "!! Bad input for IP address. !!");
+            return OC_STACK_INVALID_PARAM;
+        }
+    }
+    snprintf(queryUri, sizeof (queryUri), DISCOVERY_QUERY, ipaddr);
+
+    cbData.cb = discoveryReqCB;
+    cbData.context = NULL;
+    cbData.cd = NULL;
+
+    /* Start a discovery query*/
+    OCSAMPLE_LOG_INFO(TAG, 0, "Initiating %s Resource Discovery : %s\n",
+              (UnicastDiscovery) ? "Unicast" : "Multicast",
+              queryUri);
+
+    ret = OCDoRequest(NULL, OC_REST_DISCOVER, queryUri, 0, 0, CT_DEFAULT,
+                      OC_LOW_QOS, &cbData, NULL, 0);
+    if (ret != OC_STACK_OK)
+    {
+        OCSAMPLE_LOG_ERROR(TAG, 0, "OCStack resource error");
+    }
+    return ret;
+}
+
+FILE *client_fopen_devowner(const char *path, const char *mode)
+{
+    if (0 == strcmp(path, OC_SECURITY_DB_DAT_FILE_NAME))
+    {
+        return fopen(CRED_FILE_DEVOWNER, mode);
+    }
+    else
+    {
+        return fopen(path, mode);
+    }
+}
+
+FILE *client_fopen_nondevowner(const char *path, const char *mode)
+{
+    if (0 == strcmp(path, OC_SECURITY_DB_DAT_FILE_NAME))
+    {
+        return fopen(CRED_FILE_NONDEVOWNER, mode);
+    }
+    else
+    {
+        return fopen(path, mode);
+    }
+}
+
+static gboolean clientStarter(gpointer user_data)
+{
+    if (!gQuitFlag)
+    {   
+        if (OCProcess() != OC_STACK_OK)
+        {
+            OCSAMPLE_LOG_ERROR(TAG, 0, "OCStack process error");
+        }
+        return TRUE;
+    }   
+    else
+    {   
+        OCSAMPLE_LOG_INFO(TAG, 0, "Stopping clientStarter loop...");
+        return FALSE;
+    }   
+}
+
+int main(int argc, char *argv[])
+{
+    int opt;
+    struct timespec timeout;
+    OCPersistentStorage ps;
+
+    LSError lserror;
+    LSErrorInit(&lserror);
+
+    (void) PmLogGetContext("OCCLIENTBASICOPS", &gLogContext);
+
+    // Initialize g_main_loop
+    mainloop = g_main_loop_new(NULL, FALSE);
+    if (!mainloop) {
+        OCSAMPLE_LOG_ERROR(TAG, 0, "Failed to create main loop");
+        return 0;
+    }
+
+    if (!LSRegister("org.ocf.webossample.occlientbasicops", &pLsHandle, &lserror)) {
+        OCSAMPLE_LOG_ERROR(TAG, 0, "Failed to register LS Handle");
+        LSErrorLog(gLogContext, "LS_SRVC_ERROR", &lserror);
+        return 0;
+    }
+
+    if (!LSGmainAttach(pLsHandle, mainloop, &lserror)) {
+        OCSAMPLE_LOG_ERROR(TAG, 0, "Failed to attach main loop");
+        LSErrorLog(gLogContext, "LS_SRVC_ATTACH_ERROR", &lserror);
+        return 0;
+    }
+
+    while ((opt = getopt(argc, argv, "u:t:c:d:p:")) != -1)
+    {
+        switch (opt)
+        {
+            case 'u':
+                UnicastDiscovery = atoi(optarg);
+                break;
+            case 't':
+                TestCase = atoi(optarg);
+                break;
+            case 'c':
+                ConnType = atoi(optarg);
+                break;
+            case 'd':
+                DevOwner = atoi(optarg);
+                break;
+            case 'p':
+                {
+                    WithTcp = atoi(optarg);
+                    if (WithTcp > 1)
+                    {
+                        PrintUsage();
+                        return -1;
+                    }
+                }
+                break;
+            default:
+                PrintUsage();
+                return -1;
+        }
+    }
+
+    if ((UnicastDiscovery != 0 && UnicastDiscovery != 1) ||
+        (TestCase < TEST_DISCOVER_REQ || TestCase >= MAX_TESTS) ||
+        (ConnType < CT_ADAPTER_DEFAULT || ConnType >= MAX_CT))
+    {
+        PrintUsage();
+        return -1;
+    }
+
+
+    if (ConnType == CT_ADAPTER_DEFAULT || ConnType ==  CT_IP)
+    {
+        discoveryReqConnType = CT_DEFAULT;
+    }
+    else
+    {
+        OCSAMPLE_LOG_INFO(TAG, 0, "Using Default Connectivity type");
+        PrintUsage();
+    }
+
+
+    // Initialize Persistent Storage for SVR database
+    if (DevOwner)
+        ps = { client_fopen_devowner, fread, fwrite, fclose, unlink };
+    else
+        ps = { client_fopen_nondevowner, fread, fwrite, fclose, unlink };
+    OCRegisterPersistentStorageHandler(&ps);
+
+    /* Initialize OCStack*/
+    if (OCInit(NULL, 0, OC_CLIENT_SERVER) != OC_STACK_OK)
+    {
+        OCSAMPLE_LOG_ERROR(TAG, 0, "OCStack init error");
+        return 0;
+    }
+
+    InitDiscovery();
+
+    timeout.tv_sec  = 0;
+    timeout.tv_nsec = 100000000L;
+
+    // Break from loop with Ctrl+C
+    OCSAMPLE_LOG_INFO(TAG, 0, "Entering clientStarter main loop...");
+    signal(SIGINT, handleSigInt);
+    g_timeout_add_seconds(1, clientStarter, NULL);
+    g_main_loop_run(mainloop);
+
+    OCSAMPLE_LOG_INFO(TAG, 0, "Exiting occlient main loop...");
+
+    if (OCStop() != OC_STACK_OK)
+    {
+        OCSAMPLE_LOG_ERROR(TAG, 0, "OCStack stop error");
+    }
+
+    return 0;
+}
+
+int parseClientResponse(OCClientResponse *clientResponse)
+{
+    OCResourcePayload *res = ((OCDiscoveryPayload *)clientResponse->payload)->resources;
+
+    // Initialize all global variables
+    coapServerResource.clear();
+    coapSecureResource = 0;
+
+    while (res)
+    {
+        coapServerResource.assign(res->uri);
+        OCSAMPLE_LOG_INFO(TAG, 0, "Uri -- %s", coapServerResource.c_str());
+
+        if (0 == strncmp(coapServerResource.c_str(), OIC_STD_URI_PREFIX, strlen(OIC_STD_URI_PREFIX)) ||
+            0 == strncmp(coapServerResource.c_str(), "/introspection", strlen("/introspection")))
+        {
+            OCSAMPLE_LOG_INFO(TAG, 0, "Skip resource");
+            res = res->next;
+            continue;
+        }
+
+        OCDevAddr *endpoint = &clientResponse->devAddr;
+        if (res && res->eps)
+        {
+            endpoint->port = 0;
+            OCEndpointPayload* eps = res->eps;
+            while (NULL != eps)
+            {
+                if (eps->family & OC_FLAG_SECURE)
+                {
+#ifdef __WITH_TLS__
+                    if (WithTcp && 0 == strcmp(eps->tps, COAPS_TCP_STR))
+                    {
+                        strncpy(endpoint->addr, eps->addr, sizeof(endpoint->addr));
+                        endpoint->port = eps->port;
+                        endpoint->flags = (OCTransportFlags)(eps->family | OC_SECURE);
+                        endpoint->adapter = OC_ADAPTER_TCP;
+                        coapSecureResource = 1;
+                        OCSAMPLE_LOG_INFO(TAG, 0, "TLS port: %d", endpoint->port);
+                        break;
+                    }
+#endif
+                    if (!WithTcp && 0 == strcmp(eps->tps, COAPS_STR))
+                    {
+                        strncpy(endpoint->addr, eps->addr, sizeof(endpoint->addr));
+                        endpoint->port = eps->port;
+                        endpoint->flags = (OCTransportFlags)(eps->family | OC_SECURE);
+                        endpoint->adapter = OC_ADAPTER_IP;
+                        coapSecureResource = 1;
+                        OCSAMPLE_LOG_INFO(TAG, 0, "DTLS port: %d", endpoint->port);
+                    }
+                }
+                eps = eps->next;
+            }
+            if (!endpoint->port)
+            {
+                OCSAMPLE_LOG_INFO(TAG, 0, "Can not find secure port information.");
+            }
+        }
+
+        //old servers support
+        if (0 == coapSecureResource && res->secure)
+        {
+#ifdef __WITH_TLS__
+            if (WithTcp)
+            {
+                endpoint->flags = (OCTransportFlags)(endpoint->flags | OC_SECURE);
+                endpoint->adapter = OC_ADAPTER_TCP;
+                endpoint->port = res->tcpPort;
+                OCSAMPLE_LOG_INFO(TAG, 0, "TLS port: %d", endpoint->port);
+            }
+            else
+#endif
+            {
+                endpoint->port = res->port;
+                endpoint->flags = (OCTransportFlags)(endpoint->flags | OC_SECURE);
+                endpoint->adapter = OC_ADAPTER_IP;
+                OCSAMPLE_LOG_INFO(TAG, 0, "DTLS port: %d", endpoint->port);
+            }
+            coapSecureResource = 1;
+        }
+
+        OCSAMPLE_LOG_INFO(TAG, 0, "Secure -- %s", coapSecureResource == 1 ? "YES" : "NO");
+
+        // If we discovered a secure resource, exit from here
+        if (coapSecureResource)
+        {
+            break;
+        }
+
+        res = res->next;
+    }
+
+    return 0;
+}
diff --git a/resource/csdk/stack/samples/webos/secure/occlientbasicops/occlientbasicops.h b/resource/csdk/stack/samples/webos/secure/occlientbasicops/occlientbasicops.h
new file mode 100644 (file)
index 0000000..ab00f9e
--- /dev/null
@@ -0,0 +1,108 @@
+/*******************************************************************
+ *
+ * Copyright (c) 2018 LG Electronics, Inc.
+ * Copyright 2014 Intel Mobile Communications GmbH 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
+ *
+ *      https://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 OCCLIENT_BASICOPS_H_
+#define OCCLIENT_BASICOPS_H_
+
+#include "ocstack.h"
+
+//-----------------------------------------------------------------------------
+// Defines
+//-----------------------------------------------------------------------------
+#define DEFAULT_CONTEXT_VALUE 0x99
+
+//-----------------------------------------------------------------------------
+// Typedefs
+//-----------------------------------------------------------------------------
+
+/**
+ * List of methods that can be inititated from the client
+ */
+typedef enum {
+    TEST_DISCOVER_REQ = 1,
+    TEST_NON_CON_OP,
+    TEST_CON_OP,
+    MAX_TESTS
+} CLIENT_TEST;
+
+/**
+ * List of connectivity types that can be initiated from the client
+ * Required for user input validation
+ */
+typedef enum {
+    CT_ADAPTER_DEFAULT = 0,
+    CT_IP,
+    MAX_CT
+} CLIENT_CONNECTIVITY_TYPE;
+
+//-----------------------------------------------------------------------------
+// Function prototype
+//-----------------------------------------------------------------------------
+
+/* Get the IP address of the server */
+std::string getIPAddrTBServer(OCClientResponse * clientResponse);
+
+/* Get the port number the server is listening on */
+std::string getPortTBServer(OCClientResponse * clientResponse);
+
+/* Returns the query string for GET and PUT operations */
+std::string getQueryStrForGetPut(OCClientResponse * clientResponse);
+
+/* Following are initialization functions for GET, PUT
+ * POST & Discovery operations
+ */
+int InitPutRequest(OCDevAddr *endpoint, OCQualityOfService qos);
+int InitGetRequest(OCDevAddr *endpoint, OCQualityOfService qos);
+int InitPostRequest(OCDevAddr *endpoint, OCQualityOfService qos);
+int InitDiscovery();
+
+/* Function to retrieve ip address, port no. of the server
+ *  and query for the operations to be performed.
+ */
+int parseClientResponse(OCClientResponse * clientResponse);
+
+/* This method calls OCDoResource() which in turn makes calls
+ * to the lower layers
+ */
+OCStackResult InvokeOCDoResource(std::ostringstream &query,
+        OCMethod method, OCQualityOfService qos,
+        OCClientResponseHandler cb, OCHeaderOption * options, uint8_t numOptions);
+
+//-----------------------------------------------------------------------------
+// Callback functions
+//-----------------------------------------------------------------------------
+
+/* Following are callback functions for the  GET, PUT
+ * POST & Discovery operations
+ */
+
+OCStackApplicationResult putReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse);
+
+OCStackApplicationResult postReqCB(void *ctx, OCDoHandle handle, OCClientResponse *clientResponse);
+
+OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse);
+
+OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle handle,
+        OCClientResponse * clientResponse);
+
+#endif
+
diff --git a/resource/csdk/stack/samples/webos/secure/occlientbasicops/oic_svr_db_client_devowner.dat b/resource/csdk/stack/samples/webos/secure/occlientbasicops/oic_svr_db_client_devowner.dat
new file mode 100644 (file)
index 0000000..dc9fd24
Binary files /dev/null and b/resource/csdk/stack/samples/webos/secure/occlientbasicops/oic_svr_db_client_devowner.dat differ
diff --git a/resource/csdk/stack/samples/webos/secure/occlientbasicops/oic_svr_db_client_devowner.json b/resource/csdk/stack/samples/webos/secure/occlientbasicops/oic_svr_db_client_devowner.json
new file mode 100644 (file)
index 0000000..286428b
--- /dev/null
@@ -0,0 +1,61 @@
+{\r
+    "acl": {\r
+        "aclist2": [\r
+            {\r
+                "aceid": 1,\r
+                "subject": { "conntype": "anon-clear" },\r
+                "resources": [\r
+                    { "href": "/oic/res" },\r
+                    { "href": "/oic/d" },\r
+                    { "href": "/oic/p" },\r
+                    { "href": "/oic/sec/doxm" }\r
+                ],\r
+                "permission": 2\r
+            },\r
+            {\r
+                "aceid": 2,\r
+                "subject": { "conntype": "auth-crypt" },\r
+                "resources": [\r
+                    { "href": "/oic/res" },\r
+                    { "href": "/oic/d" },\r
+                    { "href": "/oic/p" },\r
+                    { "href": "/oic/sec/doxm" }\r
+                ],\r
+                "permission": 2\r
+            }\r
+        ],\r
+        "rowneruuid" : "32323232-3232-3232-3232-323232323232"\r
+    },\r
+    "pstat": {\r
+        "dos": {"s": 3, "p": false},\r
+        "isop": true,\r
+        "rowneruuid": "32323232-3232-3232-3232-323232323232",\r
+        "cm": 0,\r
+        "tm": 0,\r
+        "om": 4,\r
+        "sm": 4\r
+        },\r
+    "doxm": {\r
+        "oxms": [0],\r
+        "oxmsel": 0,\r
+        "sct": 9,\r
+        "owned": true,\r
+        "deviceuuid": "32323232-3232-3232-3232-323232323232",\r
+        "devowneruuid": "32323232-3232-3232-3232-323232323232",\r
+        "rowneruuid": "32323232-3232-3232-3232-323232323232"\r
+    },\r
+    "cred": {\r
+        "creds": [\r
+            {\r
+                "credid": 1,\r
+                "subjectuuid": "31313131-3131-3131-3131-313131313131",\r
+                "credtype": 1,\r
+                "privatedata": {\r
+                    "data": "AAAAAAAAAAAAAAAA",\r
+                    "encoding": "oic.sec.encoding.raw"\r
+                }\r
+            }\r
+        ],\r
+        "rowneruuid": "32323232-3232-3232-3232-323232323232"\r
+    }\r
+}\r
diff --git a/resource/csdk/stack/samples/webos/secure/occlientbasicops/oic_svr_db_client_nondevowner.dat b/resource/csdk/stack/samples/webos/secure/occlientbasicops/oic_svr_db_client_nondevowner.dat
new file mode 100644 (file)
index 0000000..c654ff9
Binary files /dev/null and b/resource/csdk/stack/samples/webos/secure/occlientbasicops/oic_svr_db_client_nondevowner.dat differ
diff --git a/resource/csdk/stack/samples/webos/secure/occlientbasicops/oic_svr_db_client_nondevowner.json b/resource/csdk/stack/samples/webos/secure/occlientbasicops/oic_svr_db_client_nondevowner.json
new file mode 100644 (file)
index 0000000..54aecee
--- /dev/null
@@ -0,0 +1,61 @@
+{\r
+    "acl": {\r
+        "aclist2": [\r
+            {\r
+                "aceid": 1,\r
+                "subject": { "conntype": "anon-clear" },\r
+                "resources": [\r
+                    { "href": "/oic/res" },\r
+                    { "href": "/oic/d" },\r
+                    { "href": "/oic/p" },\r
+                    { "href": "/oic/sec/doxm" }\r
+                ],\r
+                "permission": 2\r
+            },\r
+            {\r
+                "aceid": 2,\r
+                "subject": { "conntype": "auth-crypt" },\r
+                "resources": [\r
+                    { "href": "/oic/res" },\r
+                    { "href": "/oic/d" },\r
+                    { "href": "/oic/p" },\r
+                    { "href": "/oic/sec/doxm" }\r
+                ],\r
+                "permission": 2\r
+            }\r
+        ],\r
+        "rowneruuid" : "31393139-3139-3139-3139-313931393139"\r
+    },\r
+    "pstat": {\r
+        "dos": {"s": 3, "p": false},\r
+        "isop": true,\r
+        "rowneruuid": "31393139-3139-3139-3139-313931393139",\r
+        "cm": 0,\r
+        "tm": 0,\r
+        "om": 4,\r
+        "sm": 4\r
+        },\r
+    "doxm": {\r
+        "oxms": [0],\r
+        "oxmsel": 0,\r
+        "sct": 9,\r
+        "owned": true,\r
+        "deviceuuid": "31393139-3139-3139-3139-313931393139",\r
+        "devowneruuid": "31393139-3139-3139-3139-313931393139",\r
+        "rowneruuid": "31393139-3139-3139-3139-313931393139"\r
+    },\r
+    "cred": {\r
+        "creds": [\r
+            {\r
+                "credid": 1,\r
+                "subjectuuid": "31313131-3131-3131-3131-313131313131",\r
+                "credtype": 1,\r
+                "privatedata": {\r
+                    "data": "BBBBBBBBBBBBBBBB",\r
+                    "encoding": "oic.sec.encoding.raw"\r
+                }\r
+            }\r
+        ],\r
+        "rowneruuid": "31393139-3139-3139-3139-313931393139"\r
+    }\r
+}\r
diff --git a/resource/csdk/stack/samples/webos/secure/occlientbasicops/sample_payload_logging.h b/resource/csdk/stack/samples/webos/secure/occlientbasicops/sample_payload_logging.h
new file mode 100644 (file)
index 0000000..e14813b
--- /dev/null
@@ -0,0 +1,356 @@
+/*******************************************************************
+ *
+ * Copyright (c) 2018 LG Electronics, Inc.
+ * Copyright 2015 Intel Mobile Communications GmbH 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
+ *
+ *      https://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 SAMPLE_PAYLOAD_LOGGING_H_
+#define SAMPLE_PAYLOAD_LOGGING_H_
+
+#ifndef __STDC_FORMAT_MACROS
+#define __STDC_FORMAT_MACROS
+#endif
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS
+#endif
+
+#include "experimental/logger.h"
+#include "oic_malloc.h"
+#include "ocpayload.h"
+#include "ocstack.h"
+
+#include "logging.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+// PL_TAG is made as generic predefined tag because of build problems in arduino for using logging
+#define PL_TAG "PayloadLog"
+
+#ifdef TB_LOG
+    #define OCSAMPLE_LOG_PAYLOAD(level, payload) OCPayloadLog((level),(payload))
+    #define UUID_SIZE (16)
+
+const char *OC_CALL convertTriggerEnumToString(OCPresenceTrigger trigger);
+OCPresenceTrigger OC_CALL convertTriggerStringToEnum(const char * triggerStr);
+
+INLINE_API void OCPayloadLogRep(LogLevel level, OCRepPayload* payload);
+
+INLINE_API void OCPayloadLogRepValues(LogLevel level, OCRepPayloadValue* val)
+{
+    while (val)
+    {
+        switch(val->type)
+        {
+            case OCREP_PROP_NULL:
+                OCSAMPLE_LOG_INFO(PL_TAG, 0, "        %s: NULL", val->name);
+                break;
+            case OCREP_PROP_INT:
+                OCSAMPLE_LOG_INFO(PL_TAG, 0, "        %s(int):%" PRId64, val->name, val->i);
+                break;
+            case OCREP_PROP_DOUBLE:
+                OCSAMPLE_LOG_INFO(PL_TAG, 0, "        %s(double):%f", val->name, val->d);
+                break;
+            case OCREP_PROP_BOOL:
+                OCSAMPLE_LOG_INFO(PL_TAG, 0, "        %s(bool):%s", val->name, val->b ? "true" : "false");
+                break;
+            case OCREP_PROP_STRING:
+                OCSAMPLE_LOG_INFO(PL_TAG, 0, "        %s(string):%s", val->name, val->str);
+                break;
+            case OCREP_PROP_BYTE_STRING:
+                OCSAMPLE_LOG_INFO(PL_TAG, 0, "        %s(binary):", val->name);
+                OIC_LOG_BUFFER(level, PL_TAG, val->ocByteStr.bytes, val->ocByteStr.len);
+                break;
+            case OCREP_PROP_OBJECT:
+                // Note: Only prints the URI (if available), to print further, you'll
+                // need to dig into the object better!
+                OCSAMPLE_LOG_INFO(PL_TAG, 0, "        %s(object):", val->name);
+                OCPayloadLogRep(level, val->obj);
+                break;
+            case OCREP_PROP_ARRAY:
+                switch(val->arr.type)
+                {
+                    case OCREP_PROP_INT:
+                        OCSAMPLE_LOG_INFO(PL_TAG, 0, "        %s(int array):%" PRIuPTR " x %" PRIuPTR " x %" PRIuPTR ": ",
+                                val->name,
+                                val->arr.dimensions[0], val->arr.dimensions[1],
+                                val->arr.dimensions[2]);
+                        OCSAMPLE_LOG_INFO(PL_TAG, 0,  "         Values:");
+                        for (size_t i = 0; i < val->arr.dimensions[0]; i++)
+                        {
+                            OCSAMPLE_LOG_INFO(PL_TAG, 0, "             %" PRId64, val->arr.iArray[i]);
+                        }
+                        break;
+                    case OCREP_PROP_DOUBLE:
+                        OCSAMPLE_LOG_INFO(PL_TAG, 0, "        %s(double array):%" PRIuPTR " x %" PRIuPTR " x %" PRIuPTR ": ",
+                                val->name,
+                                val->arr.dimensions[0], val->arr.dimensions[1],
+                                val->arr.dimensions[2]);
+                        OCSAMPLE_LOG_INFO(PL_TAG, 0,  "         Values:");
+                        for (size_t i = 0; i < val->arr.dimensions[0]; i++)
+                        {
+                            OCSAMPLE_LOG_INFO(PL_TAG, 0, "             %lf", val->arr.dArray[i]);
+                        }
+                        break;
+                    case OCREP_PROP_BOOL:
+                        OCSAMPLE_LOG_INFO(PL_TAG, 0, "        %s(bool array):%" PRIuPTR " x %" PRIuPTR " x %" PRIuPTR ": ",
+                                val->name,
+                                val->arr.dimensions[0], val->arr.dimensions[1],
+                                val->arr.dimensions[2]);
+                        OCSAMPLE_LOG_INFO(PL_TAG, 0,  "         Values:");
+                        for (size_t i = 0; i < val->arr.dimensions[0]; i++)
+                        {
+                            OCSAMPLE_LOG_INFO(PL_TAG, 0, "             %d", val->arr.bArray[i]);
+                        }
+                        break;
+                    case OCREP_PROP_STRING:
+                        OCSAMPLE_LOG_INFO(PL_TAG, 0, "        %s(string array):%" PRIuPTR " x %" PRIuPTR " x %" PRIuPTR ": ",
+                                val->name,
+                                val->arr.dimensions[0], val->arr.dimensions[1],
+                                val->arr.dimensions[2]);
+                        OCSAMPLE_LOG_INFO(PL_TAG, 0,  "         Values:");
+                        for (size_t i = 0; i < val->arr.dimensions[0]; i++)
+                        {
+                            OCSAMPLE_LOG_INFO(PL_TAG, 0, "             %s", val->arr.strArray[i]);
+                        }
+                        break;
+                    case OCREP_PROP_BYTE_STRING:
+                        OCSAMPLE_LOG_INFO(PL_TAG, 0, "        %s(byte array):%" PRIuPTR " x %" PRIuPTR " x %" PRIuPTR ": ",
+                                val->name,
+                                val->arr.dimensions[0], val->arr.dimensions[1],
+                                val->arr.dimensions[2]);
+                        OCSAMPLE_LOG_INFO(PL_TAG, 0,  "         Values:");
+                        for (size_t i = 0; i < val->arr.dimensions[0]; i++)
+                        {
+                            OIC_LOG_BUFFER(level, PL_TAG, val->arr.ocByteStrArray[i].bytes, val->arr.ocByteStrArray[i].len);
+                        }
+                        break;
+                    case OCREP_PROP_OBJECT:
+                        OCSAMPLE_LOG_INFO(PL_TAG, 0, "        %s(object array):%" PRIuPTR " x %" PRIuPTR " x %" PRIuPTR ": ",
+                                val->name,
+                                val->arr.dimensions[0], val->arr.dimensions[1],
+                                val->arr.dimensions[2]);
+                        OCSAMPLE_LOG_INFO(PL_TAG, 0,  "         Values:");
+
+                        for (size_t i = 0; i < val->arr.dimensions[0]; i++)
+                        {
+                            OCPayloadLogRep(level, val->arr.objArray[i]);
+                        }
+                        break;
+                    case OCREP_PROP_ARRAY: //Seems as nested arrays doesn't not supported in API
+                    default:
+                        OCSAMPLE_LOG_ERROR(PL_TAG, 0, "%s <-- Unknown/unsupported array type!",
+                                val->name);
+                        break;
+                }
+                break;
+            default:
+                OCSAMPLE_LOG_ERROR(PL_TAG, 0, "%s <-- Unknown type!", val->name);
+                break;
+        }
+        val = val -> next;
+    }
+}
+
+INLINE_API void OCPayloadLogRep(LogLevel level, OCRepPayload* payload)
+{
+    OCSAMPLE_LOG_INFO(PL_TAG, 0, "Payload Type: Representation");
+    uint32_t i = 1;
+    for (OCRepPayload* rep = payload; rep; rep = rep->next, ++i)
+    {
+        OCSAMPLE_LOG_INFO(PL_TAG, 0, "    Resource #%d", i);
+        if (rep->uri)
+        {
+            OCSAMPLE_LOG_INFO(PL_TAG, 0, "    URI:%s", rep->uri);
+        }
+        if (rep->types)
+        {
+            OCSAMPLE_LOG_INFO(PL_TAG, 0,  "    Resource Types:");
+            for (OCStringLL* strll = rep->types; strll; strll = strll->next)
+            {
+                OCSAMPLE_LOG_INFO(PL_TAG, 0, "        %s", strll->value);
+            }
+        }
+        if (rep->interfaces)
+        {
+            OCSAMPLE_LOG_INFO(PL_TAG, 0,  "    Interfaces:");
+            for (OCStringLL* strll = rep->interfaces; strll; strll = strll->next)
+            {
+                OCSAMPLE_LOG_INFO(PL_TAG, 0, "        %s", strll->value);
+            }
+        }
+        OCSAMPLE_LOG_INFO(PL_TAG, 0,  "    Values:");
+        OCPayloadLogRepValues(level, rep->values);
+    }
+}
+
+static void OCStringLLPrint(LogLevel level, OCStringLL *type)
+{
+    for (OCStringLL *strll = type; strll; strll = strll->next)
+    {
+        OCSAMPLE_LOG_INFO(PL_TAG, 0, "         %s", strll->value);
+    }
+}
+
+INLINE_API void OCPayloadLogDiscovery(LogLevel level, OCDiscoveryPayload* payload)
+{
+    OCSAMPLE_LOG_INFO(PL_TAG, 0,  "Payload Type: Discovery");
+
+    while(payload && payload->resources)
+    {
+        OCSAMPLE_LOG_INFO(PL_TAG, 0, "    DI: %s", payload->sid);
+        if (payload->name)
+        {
+            OCSAMPLE_LOG_INFO(PL_TAG, 0, "    NAME: %s", payload->name);
+        }
+
+        if (payload->type)
+        {
+            OCSAMPLE_LOG_INFO(PL_TAG, 0,  "    Resource Type:");
+            OCStringLLPrint(level, payload->type);
+        }
+
+        if (payload->iface)
+        {
+            OCSAMPLE_LOG_INFO(PL_TAG, 0,  "    Interface:");
+            OCStringLLPrint(level, payload->iface);
+        }
+
+        OCResourcePayload* res = payload->resources;
+
+        uint32_t i = 1;
+        while(res)
+        {
+            OCSAMPLE_LOG_INFO(PL_TAG, 0, "    Link#%d", i);
+            OCSAMPLE_LOG_INFO(PL_TAG, 0, "    URI:%s", res->uri);
+            if (res->rel)
+            {
+                OCSAMPLE_LOG_INFO(PL_TAG, 0, "    Relation:%s", res->rel);
+            }
+            if (res->anchor)
+            {
+                OCSAMPLE_LOG_INFO(PL_TAG, 0, "    Anchor:%s", res->anchor);
+            }
+            OCSAMPLE_LOG_INFO(PL_TAG, 0,  "    Resource Types:");
+            OCStringLL* strll =  res->types;
+            while(strll)
+            {
+                OCSAMPLE_LOG_INFO(PL_TAG, 0, "        %s", strll->value);
+                strll = strll->next;
+            }
+            OCSAMPLE_LOG_INFO(PL_TAG, 0,  "    Interfaces:");
+            strll =  res->interfaces;
+            while(strll)
+            {
+                OCSAMPLE_LOG_INFO(PL_TAG, 0, "        %s", strll->value);
+                strll = strll->next;
+            }
+
+            OCSAMPLE_LOG_INFO(PL_TAG, 0, "    Bitmap: %u", res->bitmap);
+            OCSAMPLE_LOG_INFO(PL_TAG, 0, "    Secure?: %s", res->secure ? "true" : "false");
+            OCSAMPLE_LOG_INFO(PL_TAG, 0, "    Port: %u", res->port);
+
+            uint32_t j = 1;
+            OCEndpointPayload* eps = res->eps;
+            while (eps)
+            {
+                OCSAMPLE_LOG_INFO(PL_TAG, 0, "    Endpoint #%d", j);
+                OCSAMPLE_LOG_INFO(PL_TAG, 0, "        tps: %s", eps->tps);
+                OCSAMPLE_LOG_INFO(PL_TAG, 0, "        addr: %s", eps->addr);
+                OCSAMPLE_LOG_INFO(PL_TAG, 0, "        port: %d", eps->port);
+                OCSAMPLE_LOG_INFO(PL_TAG, 0, "        pri: %d", eps->pri);
+                eps = eps->next;
+                ++j;
+            }
+
+            OCSAMPLE_LOG_INFO(PL_TAG, 0,  "");
+            res = res->next;
+            ++i;
+        }
+        payload = payload->next;
+    }
+}
+
+INLINE_API void OCPayloadLogPresence(LogLevel level, OCPresencePayload* payload)
+{
+    OCSAMPLE_LOG_INFO(PL_TAG, 0,  "Payload Type: Presence");
+    OCSAMPLE_LOG_INFO(PL_TAG, 0, "    Sequence Number:%u", payload->sequenceNumber);
+    OCSAMPLE_LOG_INFO(PL_TAG, 0, "    Max Age:%d", payload->maxAge);
+    OCSAMPLE_LOG_INFO(PL_TAG, 0, "    Trigger:%s", convertTriggerEnumToString(payload->trigger));
+    OCSAMPLE_LOG_INFO(PL_TAG, 0, "    Resource Type:%s", payload->resourceType);
+}
+
+INLINE_API void OCPayloadLogSecurity(LogLevel level, OCSecurityPayload* payload)
+{
+    size_t payloadSize = payload->payloadSize;
+    OCSAMPLE_LOG_INFO(PL_TAG, 0,  "Payload Type: Security");
+
+    if (payloadSize > 0)
+    {
+        // Add a zero-character string terminator.
+        char *securityData = (char *)OICMalloc(payloadSize + 1);
+
+        if (securityData)
+        {
+            memcpy(securityData, payload->securityData, payloadSize);
+            // assert(securityData[payloadSize - 1] != '\0');
+            securityData[payloadSize] = '\0';
+            OCSAMPLE_LOG_INFO(PL_TAG, 0, "    Security Data: %s", securityData);
+            OICFree(securityData);
+        }
+    }
+}
+
+INLINE_API void OCPayloadLog(LogLevel level, OCPayload* payload)
+{
+    if(!payload)
+    {
+        OCSAMPLE_LOG_INFO(PL_TAG, 0,  "NULL Payload");
+        return;
+    }
+    switch(payload->type)
+    {
+        case PAYLOAD_TYPE_REPRESENTATION:
+            OCPayloadLogRep(level, (OCRepPayload*)payload);
+            break;
+        case PAYLOAD_TYPE_DISCOVERY:
+            OCPayloadLogDiscovery(level, (OCDiscoveryPayload*)payload);
+            break;
+        case PAYLOAD_TYPE_PRESENCE:
+            OCPayloadLogPresence(level, (OCPresencePayload*)payload);
+            break;
+        case PAYLOAD_TYPE_SECURITY:
+            OCPayloadLogSecurity(level, (OCSecurityPayload*)payload);
+            break;
+        default:
+            OCSAMPLE_LOG_INFO(PL_TAG, 0, "Unknown Payload Type: %d", payload->type);
+            break;
+    }
+}
+#else
+    #define OCSAMPLE_LOG_PAYLOAD(level, payload)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/resource/csdk/stack/samples/webos/secure/ocserverbasicops/SConscript b/resource/csdk/stack/samples/webos/secure/ocserverbasicops/SConscript
new file mode 100644 (file)
index 0000000..b18eabe
--- /dev/null
@@ -0,0 +1,98 @@
+#******************************************************************
+#
+# Copyright (c) 2018 LG Electronics, Inc.
+# Copyright 2014 Intel Mobile Communications GmbH 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
+#
+#      https://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.
+#
+#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+Import('stacksamples_env')
+
+samples_env = stacksamples_env.Clone()
+######################################################################
+# Build flags
+######################################################################
+samples_env.PrependUnique(CPPPATH=[
+    '../../../../../logger/include',
+    '../../../../../include',
+    '../../../../../stack/include',
+    '../../../../../security/include',
+    '../../../../../../oc_logger/include',
+    '../'
+])
+
+target_os = samples_env.get('TARGET_OS')
+if target_os not in ['windows']:
+    samples_env.AppendUnique(CXXFLAGS=['-std=c++0x', '-Wall', '-pthread'])
+
+    # Note: 'pthread' is in libc for android.
+    if target_os != 'android':
+        samples_env.AppendUnique(LIBS=['pthread'])
+    samples_env.Append(LINKFLAGS=['-Wl,--no-as-needed'])
+
+if target_os in ['windows', 'msys_nt']:
+    samples_env.PrependUnique(LIBS=['coap', 'ocsrm'])
+else:
+    samples_env.PrependUnique(LIBS=['connectivity_abstraction', 'coap', 'm'])
+
+samples_env.PrependUnique(LIBS=['octbstack'])
+
+if samples_env.get('SECURED') == '1':
+    samples_env.AppendUnique(LIBS=['mbedtls', 'mbedx509', 'mbedcrypto'])
+
+if target_os == 'android':
+    samples_env.AppendUnique(CXXFLAGS=['-frtti', '-fexceptions'])
+    samples_env.AppendUnique(LIBS=['gnustl_shared'])
+    samples_env.AppendUnique(
+        CPPDEFINES=['_GLIBCXX_USE_C99=1', '_GLIBCXX_HAVE_WCSTOF=1'])
+
+    if not samples_env.get('RELEASE'):
+        samples_env.AppendUnique(LIBS=['log'])
+
+if target_os in ['darwin', 'ios']:
+    samples_env.AppendUnique(CPPDEFINES=['_DARWIN_C_SOURCE'])
+
+samples_env.AppendUnique(CPPDEFINES=['TB_LOG'])
+
+samples_env.ParseConfig("pkg-config --cflags --libs glib-2.0")
+samples_env.ParseConfig("pkg-config --cflags --libs luna-service2")
+samples_env.ParseConfig("pkg-config --cflags --libs pbnjson_c")
+
+######################################################################
+# Source files and Targets
+######################################################################
+
+ocserverbasicops = samples_env.Program(
+    'ocserverbasicops', ['../common.cpp', 'ocserverbasicops.cpp'])
+
+ocsamples = [ocserverbasicops]
+Alias("samples", ocsamples)
+samples_env.AppendTarget('samples')
+
+src_dir = samples_env.get('SRC_DIR')
+sec_samples_src_dir = src_dir + '/resource/csdk/stack/samples/linux/secure/'
+sec_samples_build_dir = samples_env.get(
+    'BUILD_DIR') + '/resource/csdk/stack/samples/linux/secure'
+
+samples_env.Alias(
+    "install",
+    samples_env.Install(sec_samples_build_dir,
+                        sec_samples_src_dir + 'oic_svr_db_server.json'))
+
+samples_env.Alias(
+    "install",
+    samples_env.Install(sec_samples_build_dir,
+                        sec_samples_src_dir + 'oic_svr_db_server.dat'))
diff --git a/resource/csdk/stack/samples/webos/secure/ocserverbasicops/logging.h b/resource/csdk/stack/samples/webos/secure/ocserverbasicops/logging.h
new file mode 100644 (file)
index 0000000..455b268
--- /dev/null
@@ -0,0 +1,69 @@
+/*******************************************************************
+ *
+ * Copyright (c) 2018 LG Electronics, Inc.
+ *
+ *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ *
+ * 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
+ *
+ *      https://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 __LOGGING_H__
+#define __LOGGING_H__
+
+#include <PmLogLib.h>
+
+extern PmLogContext gLogContext;
+
+/* Logging for ocserverbasciops context ********
+ * The parameters needed are
+ * msgid - unique message id
+ * kvcount - count for key-value pairs
+ * ... - key-value pairs and free text. key-value pairs are formed using PMLOGKS or PMLOGKFV
+ * e.g.)
+ * WCALOG_CRITICAL(msgid, 2, PMLOGKS("key1", "value1"), PMLOGKFV("key2", "%d", value2), "free text message");
+ **********************************************/
+#define OCSAMPLE_LOG_CRITICAL(msgid, kvcount, ...) \
+        PmLogCritical(gLogContext, msgid, kvcount, ##__VA_ARGS__)
+
+#define OCSAMPLE_LOG_ERROR(msgid, kvcount, ...) \
+        PmLogError(gLogContext, msgid, kvcount,##__VA_ARGS__)
+
+#define OCSAMPLE_LOG_WARNING(msgid, kvcount, ...) \
+        PmLogWarning(gLogContext, msgid, kvcount, ##__VA_ARGS__)
+
+#define OCSAMPLE_LOG_INFO(msgid, kvcount, ...) \
+        PmLogInfo(gLogContext, msgid, kvcount, ##__VA_ARGS__)
+
+#define OCSAMPLE_LOG_DEBUG(...) \
+        PmLogDebug(gLogContext, ##__VA_ARGS__)
+
+#define OCSAMPLE_LOG_ESCAPED_ERRMSG(msgid, errmsg) \
+    do { \
+    gchar *escaped_errtext = g_strescape(errmsg, NULL); \
+    WCALOG_ERROR(msgid, 1, PMLOGKS("Error", escaped_errtext), ""); \
+    g_free(escaped_errtext); \
+    } while(0)
+
+#define OCSAMPLE_LOG_ADDR_INFOMSG(msgid, name, addr) \
+    do { \
+    gchar straddr[16]; \
+    snprintf(straddr, 16, "%p", addr); \
+    WCALOG_INFO(msgid, 1, PMLOGKS(name, straddr), ""); \
+    } while(0)
+
+/** list of MSGID's */
+#define MSGID_WIFI_SRVC_REGISTER_FAIL                   "WIFI_SRVC_REGISTER_FAIL"
+
+#endif // __LOGGING_H__
diff --git a/resource/csdk/stack/samples/webos/secure/ocserverbasicops/ocserverbasicops.cpp b/resource/csdk/stack/samples/webos/secure/ocserverbasicops/ocserverbasicops.cpp
new file mode 100644 (file)
index 0000000..c34c123
--- /dev/null
@@ -0,0 +1,451 @@
+/*******************************************************************
+ *
+ * Copyright (c) 2018 LG Electronics, Inc.
+ * Copyright 2014 Intel Mobile Communications GmbH 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
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+
+#include "iotivity_config.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <signal.h>
+#ifdef HAVE_PTHREAD_H
+#include <pthread.h>
+#endif
+#include "ocstack.h"
+#include "ocpayload.h"
+#include "ocserverbasicops.h"
+#include "common.h"
+
+
+/// This example is using experimental API, so there is no guarantee of support for future release,
+/// nor any there any guarantee that breaking changes will not occur across releases.
+#include "experimental/logger.h"
+
+#include <luna-service2/lunaservice.h>
+#include <glib.h>
+#include <pbnjson.h>
+#include <pthread.h>
+#include "logging.h"
+
+pthread_t threadId_server;
+PmLogContext gLogContext;
+PmLogContext gLogLibContext;
+
+int gQuitFlag = 0;
+
+static LEDResource LED;
+// This variable determines instance number of the LED resource.
+// Used by POST method to create a new instance of LED resource.
+static int gCurrLedInstance = 0;
+#define SAMPLE_MAX_NUM_POST_INSTANCE  2
+static LEDResource gLedInstance[SAMPLE_MAX_NUM_POST_INSTANCE];
+
+char *gResourceUri= (char *)"/a/led";
+
+//Secure Virtual Resource database for Iotivity Server
+//It contains Server's Identity and the PSK credentials
+//of other devices which the server trusts
+static char CRED_FILE[] = "oic_svr_db_server.dat";
+
+static LSHandle *pLsHandle = NULL;
+static GMainLoop *mainloop = NULL;
+
+OCRepPayload* getPayload(const char* uri, int64_t power, bool state)
+{
+    OCRepPayload* payload = OCRepPayloadCreate();
+    if(!payload)
+    {
+        OCSAMPLE_LOG_ERROR(TAG, 0, "Failed to allocate Payload");
+        return nullptr;
+    }
+
+    OCRepPayloadSetUri(payload, uri);
+    OCRepPayloadSetPropBool(payload, "state", state);
+    OCRepPayloadSetPropInt(payload, "power", power);
+
+    return payload;
+}
+
+//This function takes the request as an input and returns the response
+OCRepPayload* constructResponse (OCEntityHandlerRequest *ehRequest)
+{
+    if(ehRequest->payload && ehRequest->payload->type != PAYLOAD_TYPE_REPRESENTATION)
+    {
+        OCSAMPLE_LOG_ERROR(TAG, 0, "Incoming payload not a representation");
+        return nullptr;
+    }
+
+    OCRepPayload* input = reinterpret_cast<OCRepPayload*>(ehRequest->payload);
+
+    LEDResource *currLEDResource = &LED;
+
+    if (ehRequest->resource == gLedInstance[0].handle)
+    {
+        currLEDResource = &gLedInstance[0];
+        gResourceUri = (char *) "/a/led/0";
+    }
+    else if (ehRequest->resource == gLedInstance[1].handle)
+    {
+        currLEDResource = &gLedInstance[1];
+        gResourceUri = (char *) "/a/led/1";
+    }
+
+    if(OC_REST_PUT == ehRequest->method
+        || OC_REST_POST == ehRequest->method)
+    {
+        // Get pointer to query
+        int64_t pow;
+        if(OCRepPayloadGetPropInt(input, "power", &pow))
+        {
+            currLEDResource->power = pow;
+        }
+
+        bool state;
+        if(OCRepPayloadGetPropBool(input, "state", &state))
+        {
+            currLEDResource->state = state;
+        }
+    }
+
+    return getPayload(gResourceUri, currLEDResource->power, currLEDResource->state);
+}
+
+OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest,
+        OCRepPayload **payload)
+{
+    OCEntityHandlerResult ehResult;
+
+    OCRepPayload *getResp = constructResponse(ehRequest);
+
+    if(getResp)
+    {
+        *payload = getResp;
+        ehResult = OC_EH_OK;
+    }
+    else
+    {
+        ehResult = OC_EH_ERROR;
+    }
+
+    return ehResult;
+}
+
+OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest,
+        OCRepPayload **payload)
+{
+    OCEntityHandlerResult ehResult;
+
+    OCRepPayload *putResp = constructResponse(ehRequest);
+
+    if(putResp)
+    {
+        *payload = putResp;
+        ehResult = OC_EH_OK;
+    }
+    else
+    {
+        ehResult = OC_EH_ERROR;
+    }
+
+    return ehResult;
+}
+
+OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
+        OCEntityHandlerResponse *response, OCRepPayload **payload)
+{
+    OCRepPayload *respPLPost_led = nullptr;
+    OCEntityHandlerResult ehResult = OC_EH_OK;
+
+    /*
+     * The entity handler determines how to process a POST request.
+     * Per the REST paradigm, POST can also be used to update representation of existing
+     * resource or create a new resource.
+     * In the sample below, if the POST is for /a/led then a new instance of the LED
+     * resource is created with default representation (if representation is included in
+     * POST payload it can be used as initial values) as long as the instance is
+     * lesser than max new instance count. Once max instance count is reached, POST on
+     * /a/led updated the representation of /a/led.
+     */
+
+    if (ehRequest->resource == LED.handle)
+    {
+        if (gCurrLedInstance < SAMPLE_MAX_NUM_POST_INSTANCE)
+        {
+            // Create new LED instance
+            char newLedUri[15] = "/a/led/";
+            size_t newLedUriLength = strlen(newLedUri);
+            snprintf((newLedUri + newLedUriLength), (sizeof(newLedUri) - newLedUriLength), "%d", gCurrLedInstance);
+
+            respPLPost_led = OCRepPayloadCreate();
+            OCRepPayloadSetUri(respPLPost_led, gResourceUri);
+            OCRepPayloadSetPropString(respPLPost_led, "createduri", newLedUri);
+
+            if (0 == createLEDResource (newLedUri, &gLedInstance[gCurrLedInstance], false, 0))
+            {
+                OCSAMPLE_LOG_INFO(TAG, 0, "Created new LED instance");
+                gLedInstance[gCurrLedInstance].state = 0;
+                gLedInstance[gCurrLedInstance].power = 0;
+                gCurrLedInstance++;
+                strncpy ((char *)response->resourceUri, newLedUri, MAX_URI_LENGTH);
+                ehResult = OC_EH_RESOURCE_CREATED;
+            }
+        }
+        else
+        {
+            respPLPost_led = constructResponse(ehRequest);
+        }
+    }
+    else
+    {
+        for (int i = 0; i < SAMPLE_MAX_NUM_POST_INSTANCE; i++)
+        {
+            if (ehRequest->resource == gLedInstance[i].handle)
+            {
+                if (i == 0)
+                {
+                    respPLPost_led = constructResponse(ehRequest);
+                    break;
+                }
+                else if (i == 1)
+                {
+                    respPLPost_led = constructResponse(ehRequest);
+                }
+            }
+        }
+    }
+
+    if (respPLPost_led != NULL)
+    {
+        *payload = respPLPost_led;
+        ehResult = OC_EH_OK;
+    }
+    else
+    {
+        OCSAMPLE_LOG_INFO(TAG, 0, "Payload was NULL");
+        ehResult = OC_EH_ERROR;
+    }
+
+    return ehResult;
+}
+
+OCEntityHandlerResult
+OCEntityHandlerCb (OCEntityHandlerFlag flag,
+        OCEntityHandlerRequest *entityHandlerRequest,
+        void* /*callbackParam*/)
+{
+    OCSAMPLE_LOG_INFO(TAG, 0, "Inside entity handler - flags: 0x%x", flag);
+
+    OCEntityHandlerResult ehResult = OC_EH_ERROR;
+    OCEntityHandlerResponse response = { 0, 0, OC_EH_ERROR, 0, 0, { },{ 0 }, false };
+    // Validate pointer
+    if (!entityHandlerRequest)
+    {
+        OCSAMPLE_LOG_ERROR(TAG, 0, "Invalid request pointer");
+        return OC_EH_ERROR;
+    }
+
+    OCRepPayload* payload = nullptr;
+
+    if (flag & OC_REQUEST_FLAG)
+    {
+        OCSAMPLE_LOG_INFO(TAG, 0, "Flag includes OC_REQUEST_FLAG");
+        if (entityHandlerRequest)
+        {
+            if (OC_REST_GET == entityHandlerRequest->method)
+            {
+                OCSAMPLE_LOG_INFO(TAG, 0, "Received OC_REST_GET from client");
+                ehResult = ProcessGetRequest (entityHandlerRequest, &payload);
+            }
+            else if (OC_REST_PUT == entityHandlerRequest->method)
+            {
+                OCSAMPLE_LOG_INFO(TAG, 0, "Received OC_REST_PUT from client");
+                ehResult = ProcessPutRequest (entityHandlerRequest, &payload);
+            }
+            else if (OC_REST_POST == entityHandlerRequest->method)
+            {
+                OCSAMPLE_LOG_INFO(TAG, 0, "Received OC_REST_POST from client");
+                ehResult = ProcessPostRequest (entityHandlerRequest, &response, &payload);
+            }
+            else
+            {
+                OCSAMPLE_LOG_INFO(TAG, 0, "Received unsupported method %d from client",
+                        entityHandlerRequest->method);
+                ehResult = OC_EH_ERROR;
+            }
+
+            if (ehResult == OC_EH_OK && ehResult != OC_EH_FORBIDDEN)
+            {
+                // Format the response.  Note this requires some info about the request
+                response.requestHandle = entityHandlerRequest->requestHandle;
+                response.resourceHandle = entityHandlerRequest->resource;
+                response.ehResult = ehResult;
+                response.payload = reinterpret_cast<OCPayload*>(payload);
+                response.numSendVendorSpecificHeaderOptions = 0;
+                memset(response.sendVendorSpecificHeaderOptions, 0, sizeof response.sendVendorSpecificHeaderOptions);
+                memset(response.resourceUri, 0, sizeof(response.resourceUri));
+                // Indicate that response is NOT in a persistent buffer
+                response.persistentBufferFlag = 0;
+
+                // Send the response
+                if (OCDoResponse(&response) != OC_STACK_OK)
+                {
+                    OCSAMPLE_LOG_ERROR(TAG, 0, "Error sending response");
+                    ehResult = OC_EH_ERROR;
+                }
+            }
+        }
+    }
+
+    OCRepPayloadDestroy(payload);
+    return ehResult;
+}
+
+/* SIGINT handler: set gQuitFlag to 1 for graceful termination */
+void handleSigInt(int signum)
+{
+    if (signum == SIGINT)
+    {
+        gQuitFlag = 1;
+        g_main_loop_quit(mainloop);
+    }
+}
+
+FILE* server_fopen(const char *path, const char *mode)
+{
+    if (0 == strcmp(path, OC_SECURITY_DB_DAT_FILE_NAME))
+    {
+        return fopen(CRED_FILE, mode);
+    }
+    else
+    {
+        return fopen(path, mode);
+    }
+}
+
+static gboolean serverStarter(gpointer user_data)
+{
+    if (!gQuitFlag)
+    {
+        if (OCProcess() != OC_STACK_OK)
+        {
+            OCSAMPLE_LOG_ERROR(TAG, 0, "OCStack process error");
+        }
+        return TRUE;
+    }
+    else
+    {
+        OCSAMPLE_LOG_INFO(TAG, 0, "Stopping serverStarter loop...");
+        return FALSE;
+    }
+}
+
+int main(int /*argc*/, char* /*argv*/[])
+{
+    struct timespec timeout;
+    LSError lserror;
+    LSErrorInit(&lserror);
+    (void) PmLogGetContext("OCSERVERBASICOPS", &gLogContext);
+    (void) PmLogGetContext("OCSERVERBASICOPS-LIB", &gLogLibContext);
+    PmLogSetLibContext(gLogLibContext);
+
+    mainloop = g_main_loop_new(NULL, FALSE);
+
+    // Initialize g_main_loop
+    if (!mainloop) {
+        OCSAMPLE_LOG_ERROR(TAG, 0, "Failed to create main loop");
+        return 0;
+    }
+
+    OCSAMPLE_LOG_INFO(TAG, 0, "OCServer is starting...");
+
+    if (!LSRegister("org.ocf.webossample.ocserverbasicops", &pLsHandle, &lserror)) {
+        OCSAMPLE_LOG_ERROR(TAG, 0, "Failed to register LS Handle");
+        LSErrorLog(gLogContext, "LS_SRVC_ERROR", &lserror);
+        return 0;
+    }
+
+    if (!LSGmainAttach(pLsHandle, mainloop, &lserror)) {
+        OCSAMPLE_LOG_ERROR(TAG, 0, "Failed to attach main loop: %s", &lserror);
+        LSErrorLog(gLogContext, "LS_SRVC_ATTACH_ERROR", &lserror);
+        return 0;
+    }
+
+    // Initialize Persistent Storage for SVR database
+    OCPersistentStorage ps = { server_fopen, fread, fwrite, fclose, unlink };
+    OCRegisterPersistentStorageHandler(&ps);
+
+    if (OCInit(NULL, 0, OC_SERVER) != OC_STACK_OK)
+    {
+        OCSAMPLE_LOG_ERROR(TAG, 0, "OCStack init error");
+        return 0;
+    }
+
+    /*
+     * Declare and create the example resource: LED
+     */
+    createLEDResource(gResourceUri, &LED, false, 0);
+
+    timeout.tv_sec  = 0;
+    timeout.tv_nsec = 100000000L;
+
+    // Break from loop with Ctrl-C
+    OCSAMPLE_LOG_INFO(TAG, 0, "Entering ocserver main loop...");
+    signal(SIGINT, handleSigInt);
+
+    //pthread_create(&threadId_server, NULL, serverStarter, (void *)NULL);
+    OCSAMPLE_LOG_INFO(TAG, 0, "Entering serverStarter main loop...");
+    g_timeout_add_seconds(1, serverStarter, NULL);
+    g_main_loop_run(mainloop);
+
+    OCSAMPLE_LOG_INFO(TAG, 0, "Exiting ocserver main loop...");
+
+    if (OCStop() != OC_STACK_OK)
+    {
+        OCSAMPLE_LOG_ERROR(TAG, 0, "OCStack process error");
+        return 0;
+    }
+
+    return 0;
+}
+
+int createLEDResource (char *uri, LEDResource *ledResource, bool resourceState, int64_t resourcePower)
+{
+    if (!uri)
+    {
+        OCSAMPLE_LOG_ERROR(TAG, 0, "Resource URI cannot be NULL");
+        return -1;
+    }
+
+    ledResource->state = resourceState;
+    ledResource->power= resourcePower;
+    OCStackResult res = OCCreateResource(&(ledResource->handle),
+            "core.led",
+            OC_RSRVD_INTERFACE_DEFAULT,
+            uri,
+            OCEntityHandlerCb,
+            NULL,
+            OC_DISCOVERABLE|OC_OBSERVABLE | OC_SECURE);
+    OCSAMPLE_LOG_INFO(TAG, 0, "Created LED resource with result: %s", getResult(res));
+
+    return 0;
+}
diff --git a/resource/csdk/stack/samples/webos/secure/ocserverbasicops/ocserverbasicops.h b/resource/csdk/stack/samples/webos/secure/ocserverbasicops/ocserverbasicops.h
new file mode 100644 (file)
index 0000000..ffcaff3
--- /dev/null
@@ -0,0 +1,77 @@
+/*******************************************************************
+ *
+ * Copyright (c) 2018 LG Electronics, Inc.
+ * Copyright 2014 Intel Mobile Communications GmbH 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
+ *
+ *      https://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 OCSERVER_BASICOPS_H_
+#define OCSERVER_BASICOPS_H_
+
+#include "ocstack.h"
+
+//-----------------------------------------------------------------------------
+// Defines
+//-----------------------------------------------------------------------------
+#define TAG "ocserverbasicops"
+
+//-----------------------------------------------------------------------------
+// Typedefs
+//-----------------------------------------------------------------------------
+
+/* Structure to represent a LED resource */
+typedef struct LEDRESOURCE{
+    OCResourceHandle handle;
+    bool state;
+    int64_t power;
+} LEDResource;
+
+//-----------------------------------------------------------------------------
+// Function prototype
+//-----------------------------------------------------------------------------
+
+/* Function that creates a new LED resource by calling the
+ * OCCreateResource() method.
+ */
+int createLEDResource (char *uri, LEDResource *ledResource, bool resourceState, int64_t resourcePower);
+
+/* This method converts the payload to JSON format */
+OCRepPayload* constructResponse (OCEntityHandlerRequest *ehRequest);
+
+/* Following methods process the PUT, GET, POST
+ * requests
+ */
+OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest,
+                                         OCRepPayload **payload);
+OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest,
+                                         OCRepPayload **payload);
+OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
+                                        OCEntityHandlerResponse *response,
+                                        OCRepPayload **payload);
+
+//-----------------------------------------------------------------------------
+// Callback functions
+//-----------------------------------------------------------------------------
+
+/* Entity Handler callback functions */
+
+OCEntityHandlerResult
+OCEntityHandlerCb (OCEntityHandlerFlag flag,
+        OCEntityHandlerRequest *entityHandlerRequest);
+
+#endif
diff --git a/resource/csdk/stack/samples/webos/secure/ocserverbasicops/oic_svr_db_server.json b/resource/csdk/stack/samples/webos/secure/ocserverbasicops/oic_svr_db_server.json
new file mode 100644 (file)
index 0000000..3a8ea10
--- /dev/null
@@ -0,0 +1,90 @@
+{\r
+    "acl": {\r
+        "aclist2": [\r
+            {\r
+                "aceid": 1,\r
+                "subject": { "conntype": "anon-clear" },\r
+                "resources": [\r
+                    { "href": "/oic/res" },\r
+                    { "href": "/oic/d" },\r
+                    { "href": "/oic/p" },\r
+                    { "href": "/oic/sec/doxm" }\r
+                ],\r
+                "permission": 2\r
+            },\r
+            {\r
+                "aceid": 2,\r
+                "subject": { "conntype": "auth-crypt" },\r
+                "resources": [\r
+                    { "href": "/oic/res" },\r
+                    { "href": "/oic/d" },\r
+                    { "href": "/oic/p" },\r
+                    { "href": "/oic/sec/doxm" }\r
+                ],\r
+                "permission": 2\r
+            },\r
+            {\r
+                "aceid": 3,\r
+                "subject": { "uuid": "32323232-3232-3232-3232-323232323232" },\r
+                "resources": [{ "wc": "*" }],\r
+                "permission": 7\r
+            },\r
+            {\r
+                "aceid": 4,\r
+                "subject": { "uuid": "31393139-3139-3139-3139-313931393139" },\r
+                "resources": [{ "href": "/a/led" }],\r
+         &nb