This is a framework soruce code for SmartThings Things SDK.
Framework function
1. Easysetup manager for communication between controller - controlee
2. Data manager for defining and processing resources
3. Security manager related security module and certificate
You can test using st_things sample in /apps/examples/st_things
include src$(DELIM)wifi_manager$(DELIM)Make.defs
endif
+ifeq ($(CONFIG_ST_THINGS), y)
+include src$(DELIM)st_things$(DELIM)Make.defs
+endif
+
ifeq ($(CONFIG_AUDIO), y)
include src$(DELIM)tinyalsa$(DELIM)Make.defs
endif
#include <stdint.h>
#include <stdbool.h>
+#ifdef __ST_THINGS_RTOS__
+#include <st_things/st_things_types.h>
+#else
#include "st_things_types.h"
+#endif // __ST_THINGS_RTOS__
#ifdef __cplusplus
extern "C" {
* If easy-setup is not done, app can either wait for the user interaction before starting the things stack or
* start the things stack directly without waiting for any events(This case is for those things which doesn't
* support input capability and for all other unknown cases).
+ * To use a new json file after initialization, stack should be deinitialized
+ * and stopped(if its started already).
* @param[in] json_path Path to Json file which defines a thing. Definition includes the device information,
* resources and their properties, configuration info for connectivity and easy-setup, etc.
* @param[out] easysetup_complete Indicates whether easysetup is completed already or not.
* @retval #ST_THINGS_ERROR_NONE Successful
* @retval #ST_THINGS_ERROR_INVALID_PARAMETER Invalid parameter
* @retval #ST_THINGS_ERROR_OPERATION_FAILED Operation failed
+ * @retval #ST_THINGS_ERROR_STACK_ALREADY_INITIALIZED Stack already initialized.
+ * To initialize again, stack should be deinitilized first by calling st_things_deinitialize().
+ * @retval #ST_THINGS_ERROR_STACK_RUNNING Stack is currently running.
+ * To initialize again, stack should be stopped first by calling st_things_stop()
+ * and then deinitialized by calling st_things_deinitialize().
* @since Tizen RT v1.1
*/
int st_things_initialize(const char *json_path, bool *easysetup_complete);
/**
* @brief Deinitializes things stack.
+ * Stack should have been initialized before calling this API.
* @return @c 0 on success, otherwise a negative error value
* @retval #ST_THINGS_ERROR_NONE Successful
* @retval #ST_THINGS_ERROR_OPERATION_FAILED Operation failed
+ * @retval #ST_THINGS_ERROR_STACK_NOT_INITIALIZED Stack is not initialized.
+ * Initialize the stack by calling st_things_initialize().
+ * @retval #ST_THINGS_ERROR_STACK_RUNNING Stack is currently running.
+ * Before deinitialize, stack needs to be stopped by calling st_things_stop().
* @since Tizen RT v1.1
*/
int st_things_deinitialize(void);
* Onboarding creates an ad-hoc network between the thing and the client for performing easy-setup.
* If easy-setup is already done, thing will be connected with the cloud.
* Application can know whether easy-setup is done or not through st_things_initialize API.
+ * Stack should have been initialized before calling this API.
* @return @c 0 on success, otherwise a negative error value
- * @retval #ST_THINGS_ERROR_NONE Successful
+ * @retval #ST_THINGS_ERROR_NONE Successful.
+ * It is also used for the case that the stack is started already.
* @retval #ST_THINGS_ERROR_OPERATION_FAILED Operation failed
+ * @retval #ST_THINGS_ERROR_STACK_NOT_INITIALIZED Stack is not initialized.
+ * Initialize the stack by calling st_things_initialize().
* @since Tizen RT v1.1
*/
int st_things_start(void);
/**
* @brief Stops things stack.
* Removes all the data being used internally and releases all the memory allocated for the stack.
+ * Stack should have been initialized and started before calling this API.
* @return @c 0 on success, otherwise a negative error value
* @retval #ST_THINGS_ERROR_NONE Successful
* @retval #ST_THINGS_ERROR_OPERATION_FAILED Operation failed
+ * @retval #ST_THINGS_ERROR_STACK_NOT_INITIALIZED Stack is not initialized.
+ * Initialize the stack by calling st_things_initialize().
+ * @retval #ST_THINGS_ERROR_STACK_NOT_STARTED Stack is not started.
+ * Start the stack by calling st_things_start().
* @since Tizen RT v1.1
*/
int st_things_stop(void);
* @return @c true to confirm, otherwise @c to deny
* @since Tizen RT v1.1
*/
-typedef bool (*st_things_reset_confirm_cb)(void);
+typedef bool(*st_things_reset_confirm_cb) (void);
/**
* @brief Callback for carrying the result of reset.
* @param[in] is_success Result of Stack-reset. (true : success, false : failure)
* @since Tizen RT v1.1
*/
-typedef void (*st_things_reset_result_cb)(bool is_success);
+typedef void (*st_things_reset_result_cb) (bool is_success);
/**
* @brief Callback registration function for Reset-Confirmation and Reset-Result functions.
/**
* @brief Reset all the data related to security and cloud being used in the stack.
+ * Stack should have been initialized and started before calling this API.
* @return @c 0 on success, otherwise a negative error value
* @retval #ST_THINGS_ERROR_NONE Successful
* @retval #ST_THINGS_ERROR_OPERATION_FAILED Operation failed
+ * @retval #ST_THINGS_ERROR_STACK_NOT_INITIALIZED Stack is not intialized.
+ * Initialize the stack by calling st_things_initialize().
+ * @retval #ST_THINGS_ERROR_STACK_NOT_STARTED Stack is not started.
+ * Start the stack by calling st_things_start().
* @since Tizen RT v1.1
*/
int st_things_reset(void);
* @param[in] pin_size Length of the PIN String.
* @since Tizen RT v1.1
*/
-typedef void (*st_things_pin_generated_cb)(const char *pin_data, const size_t pin_size);
+typedef void (*st_things_pin_generated_cb) (const char *pin_data, const size_t pin_size);
/**
* @brief Callback for informing the application to close the PIN display.
* @since Tizen RT v1.1
*/
-typedef void (*st_things_pin_display_close_cb)(void);
+typedef void (*st_things_pin_display_close_cb) (void);
/**
* @brief Callback registration function for getting randomly generated PIN for the PIN-Based Ownership Transfer Request.
* @return @c true true in cse of confirmed, otherwise @c false
* @since Tizen RT v1.1
*/
-typedef bool (*st_things_user_confirm_cb)(void);
+typedef bool(*st_things_user_confirm_cb) (void);
/**
* @brief Callback registration function for getting user confirmation for MUTUAL VERIFICATION BASED JUST WORK Ownership transfer.
* @param[in] things_status ST Things State
* @since Tizen RT v1.1
*/
-typedef void (*st_things_status_change_cb)(st_things_status_e things_status);
+typedef void (*st_things_status_change_cb) (st_things_status_e things_status);
/**
* @brief Callback registration function for getting notified when ST Things state changes.
/**
* @brief Notify the observers of a specific resource.
+ * Stack should have been initialized and started before calling this API.
* @param[in] resource_uri Resource URI of the resource which will be notified to observers.
* @return @c 0 on success, otherwise a negative error value
* @retval #ST_THINGS_ERROR_NONE Successful
* @retval #ST_THINGS_ERROR_INVALID_PARAMETER Invalid parameter
* @retval #ST_THINGS_ERROR_OPERATION_FAILED Operation failed
+ * @retval #ST_THINGS_ERROR_STACK_NOT_INITIALIZED Stack is not intialized.
+ * Initialize the stack by calling st_things_initialize().
+ * @retval #ST_THINGS_ERROR_STACK_NOT_STARTED Stack is not started.
+ * Start the stack by calling st_things_start().
* @since Tizen RT v1.1
*/
int st_things_notify_observers(const char *resource_uri);
/**
- * @brief Send Representation of a specific resource through push service to Samsung Connect client.
- * @param[in] resource_uri Resource uri for which we want to send push message.
- * @param[in] rep Representation for resource uri.
- * @return @c 0 on success, otherwise a negative error value
- * @retval #ST_THINGS_ERROR_NONE Successful
- * @retval #ST_THINGS_ERROR_INVALID_PARAMETER Invalid parameter
- * @retval #ST_THINGS_ERROR_OPERATION_FAILED Operation failed
- * @since Tizen RT v1.1
- */
-int st_things_send_push_message(const char *resource_uri, st_things_representation_s *rep);
-
-/**
* @brief Create an instance of representation.
* @remarks To destroy an instance, st_things_destroy_representation_inst() should be used.
* @return a pointer of the created representation, otherwise a null pointer if the memory is insufficient.
}
#endif /* __cplusplus */
#endif /* __ST_THINGS_H__ */
-/** @} */// end of SmartThings group
+ /** @} */// end of SmartThings group
/**
* @ingroup SmartThings
* @{
- */
+*/
/**
* @file st_things_types.h
* @brief Provides structure definition for SmartThings Things SDK
*/
-
#ifndef __ST_THINGS_TYPES_H__
#define __ST_THINGS_TYPES_H__
* @since Tizen RT v1.1
*/
typedef enum {
- ST_THINGS_ERROR_NONE = 0, /**< Successful */
- ST_THINGS_ERROR_INVALID_PARAMETER = -1, /**< Invalid parameter (If parameter is null or empty)*/
- ST_THINGS_ERROR_OPERATION_FAILED = -2, /**< Operation Failed */
+ ST_THINGS_ERROR_NONE = 0, /**< Successful */
+ ST_THINGS_ERROR_INVALID_PARAMETER = -1, /**< Invalid parameter (If parameter is null or empty)*/
+ ST_THINGS_ERROR_OPERATION_FAILED = -2, /**< Operation Failed */
+ ST_THINGS_ERROR_STACK_NOT_INITIALIZED = -3, /**< Stack is not yet initialized*/
+ ST_THINGS_ERROR_STACK_ALREADY_INITIALIZED = -4, /**< Stack is already initialized*/
+ ST_THINGS_ERROR_STACK_NOT_STARTED = -5, /**< Stack is not yet started*/
+ ST_THINGS_ERROR_STACK_RUNNING = -6, /**< Stack is currently running*/
} st_things_error_e;
/**
ST_THINGS_STATUS_REGISTERED_TO_CLOUD, /**< Publish resource(s) to cloud is complete. Now the Thing is ready to be controlled via Cloud */
ST_THINGS_STATUS_REGISTERING_FAILED_ON_SIGN_IN, /**< Failed to sign-in to Cloud */
ST_THINGS_STATUS_REGISTERING_FAILED_ON_PUB_RES /**< Failed to publish resources to Cloud */
- /**
- * @todo More status needs to be added, especially for failure cases like 'incorrect password to connect to target AP'
- */
} st_things_status_e;
/**
* @return @c true if value exist, otherwise @c false
* @since Tizen RT v1.1
*/
- bool (*get_str_value)(struct _st_things_representation *rep, const char *key, char **value);
+ bool(*get_str_value) (struct _st_things_representation *rep, const char *key, char **value);
/**
* @brief API for getting the value of boolean type property with a key.
* @return @c true if value exist, otherwise @c false
* @since Tizen RT v1.1
*/
- bool (*get_bool_value)(struct _st_things_representation *rep, const char *key, bool *value);
+ bool(*get_bool_value) (struct _st_things_representation *rep, const char *key, bool *value);
/**
* @brief API for getting the value of integer type property with a key.
* @return @c true if value exist, otherwise @c false
* @since Tizen RT v1.1
*/
- bool (*get_int_value)(struct _st_things_representation *rep, const char *key, int64_t *value);
+ bool(*get_int_value) (struct _st_things_representation *rep, const char *key, int64_t *value);
/**
* @brief API for getting the value of double type property with a key.
* @return @c true if value exist, otherwise @c false
* @since Tizen RT v1.1
*/
- bool (*get_double_value)(struct _st_things_representation *rep, const char *key, double *value);
+ bool(*get_double_value) (struct _st_things_representation *rep, const char *key, double *value);
/**
* @brief API for getting the value of byte array type property with a key.
* @return @c true if value exist, otherwise @c false
* @since Tizen RT v1.1
*/
- bool (*get_byte_value)(struct _st_things_representation *rep, const char *key, uint8_t **value, size_t *size);
+ bool(*get_byte_value) (struct _st_things_representation *rep, const char *key, uint8_t **value, size_t *size);
/**
* @brief API for getting the value of object type property with a key.
* @return @c true if value exist, otherwise @c false
* @since Tizen RT v1.1
*/
- bool (*get_object_value)(struct _st_things_representation *rep, const char *key, struct _st_things_representation **value);
+ bool(*get_object_value) (struct _st_things_representation *rep, const char *key, struct _st_things_representation **value);
/**
* @brief API for setting the value of string type property with a key.
* @return @c true if setting value is successful, otherwise @c false
* @since Tizen RT v1.1
*/
- bool (*set_str_value)(struct _st_things_representation *rep, const char *key, const char *value);
+ bool(*set_str_value) (struct _st_things_representation *rep, const char *key, const char *value);
/**
* @brief API for setting the value of boolean type property with a key.
* @return @c true if setting value is successful, otherwise @c false
* @since Tizen RT v1.1
*/
- bool (*set_bool_value)(struct _st_things_representation *rep, const char *key, bool value);
+ bool(*set_bool_value) (struct _st_things_representation *rep, const char *key, bool value);
/**
* @brief API for setting the value of integer type property with a key.
* @return @c true if setting value is successful, otherwise @c false
* @since Tizen RT v1.1
*/
- bool (*set_int_value)(struct _st_things_representation *rep, const char *key, int64_t value);
+ bool(*set_int_value) (struct _st_things_representation *rep, const char *key, int64_t value);
/**
* @brief API for setting the value of double type property with a key.
* @return @c true if setting value is successful, otherwise @c false
* @since Tizen RT v1.1
*/
- bool (*set_double_value)(struct _st_things_representation *rep, const char *key, double value);
+ bool(*set_double_value) (struct _st_things_representation *rep, const char *key, double value);
/**
* @brief API for setting the value of byte array type property with a key.
* @return @c true if setting value is successful, otherwise @c false
* @since Tizen RT v1.1
*/
- bool (*set_byte_value)(struct _st_things_representation *rep, const char *key, const uint8_t *value, size_t size);
+ bool(*set_byte_value) (struct _st_things_representation *rep, const char *key, const uint8_t *value, size_t size);
/**
* @brief API for setting the value of object type property with a key.
* @return @c true if value exist, otherwise @c false
* @since Tizen RT v1.1
*/
- bool (*set_object_value)(struct _st_things_representation *rep, const char *key, const struct _st_things_representation *value);
+ bool(*set_object_value) (struct _st_things_representation *rep, const char *key, const struct _st_things_representation *value);
/**
* @brief API for getting the value of string array type property with a key.
* @return @c true if value exist, otherwise @c false
* @since Tizen RT v1.1
*/
- bool (*get_str_array_value)(struct _st_things_representation *rep, const char *key, char ***array, size_t *length);
+ bool(*get_str_array_value) (struct _st_things_representation *rep, const char *key, char ***array, size_t *length);
/**
* @brief API for getting the value of integer array type property with a key.
* @return @c true if value exist, otherwise @c false
* @since Tizen RT v1.1
*/
- bool (*get_int_array_value)(struct _st_things_representation *rep, const char *key, int64_t **array, size_t *length);
+ bool(*get_int_array_value) (struct _st_things_representation *rep, const char *key, int64_t **array, size_t *length);
/**
* @brief API for getting the value of double array type property with a key.
* @return @c true if value exist, otherwise @c false
* @since Tizen RT v1.1
*/
- bool (*get_double_array_value)(struct _st_things_representation *rep, const char *key, double **array, size_t *length);
+ bool(*get_double_array_value) (struct _st_things_representation *rep, const char *key, double **array, size_t *length);
/**
* @brief API for getting the value of object array type property with a key.
* @return @c true if value exist, otherwise @c false
* @since Tizen RT v1.1
*/
- bool (*get_object_array_value)(struct _st_things_representation *rep, const char *key, struct _st_things_representation ***array, size_t *length);
+ bool(*get_object_array_value) (struct _st_things_representation *rep, const char *key, struct _st_things_representation ***array, size_t *length);
/**
* @brief API for setting the value of string array type property with a key.
* @return @c true if setting value is successful, otherwise @c false
* @since Tizen RT v1.1
*/
- bool (*set_str_array_value)(struct _st_things_representation *rep, const char *key, const char **array, size_t length);
+ bool(*set_str_array_value) (struct _st_things_representation *rep, const char *key, const char **array, size_t length);
/**
* @brief API for setting the value of integer array type property with a key.
* @return @c true if setting value is successful, otherwise @c false
* @since Tizen RT v1.1
*/
- bool (*set_int_array_value)(struct _st_things_representation *rep, const char *key, const int64_t *array, size_t length);
+ bool(*set_int_array_value) (struct _st_things_representation *rep, const char *key, const int64_t *array, size_t length);
/**
* @brief API for setting the value of double array type property with a key.
* @return @c true if setting value is successful, otherwise @c false
* @since Tizen RT v1.1
*/
- bool (*set_double_array_value)(struct _st_things_representation *rep, const char *key, const double *array, size_t length);
+ bool(*set_double_array_value) (struct _st_things_representation *rep, const char *key, const double *array, size_t length);
/**
* @brief API for setting the value of object array type property with a key.
* @return @c true if setting value is successful, otherwise @c false
* @since Tizen RT v1.1
*/
- bool (*set_object_array_value)(struct _st_things_representation *rep, const char *key, const struct _st_things_representation **array, size_t length);
+ bool(*set_object_array_value) (struct _st_things_representation *rep, const char *key, const struct _st_things_representation **array, size_t length);
} st_things_representation_s;
* @return @c true if query exist, otherwise @c false
* @since Tizen RT v1.1
*/
- bool (*get_query_value)(struct _st_things_get_request_message *req_msg, const char *key, char **value);
+ bool(*get_query_value) (struct _st_things_get_request_message *req_msg, const char *key, char **value);
/**
* @brief API for checking whether the request has a specific property key or not.
* @return @c true if the property key exists, otherwise @c false
* @since Tizen RT v1.1
*/
- bool (*has_property_key)(struct _st_things_get_request_message *req_msg, const char *key);
+ bool(*has_property_key) (struct _st_things_get_request_message *req_msg, const char *key);
} st_things_get_request_message_s;
* @return @c true if query exist, otherwise @c false
* @since Tizen RT v1.1
*/
- bool (*get_query_value)(struct _st_things_set_request_message *req_msg, const char *key, char **value);
+ bool(*get_query_value) (struct _st_things_set_request_message *req_msg, const char *key, char **value);
} st_things_set_request_message_s;
--- /dev/null
+#
+# For a description of the syntax of this configuration file,
+# see kconfig-language at https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt
+#
+
+config ST_THINGS
+ bool "SmartThings Things Management"
+ default n
+ select ENABLE_IOTIVITY
+ select ENABLE_IOTIVITY_SECURED
+ select ENABLE_IOTIVITY_CLOUD
+ select NETUTILS_WIFI
+ select WIFI_MANAGER
+ select WPA_SUPPLICANT
+ select SCSC_WLAN
+ select NETUTILS_JSON
+ depends on FS_ROMFS
+ ---help---
+ SmartThings Things Management for applications to use and control devices
--- /dev/null
+###########################################################################
+#
+# Copyright 2017 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.
+#
+###########################################################################
+
+THINGS_LIB_DIR = $(TOPDIR)/../framework/src/st_things
+THINGS_STACK_DIR = $(TOPDIR)/../framework/src/st_things/things_stack
+IOTIVITY_RELEASE=${shell echo $(CONFIG_IOTIVITY_RELEASE_VERSION) | sed 's/"//g'}
+IOTIVITY_BASE_DIR = $(TOPDIR)/../external/iotivity/iotivity_$(IOTIVITY_RELEASE)
+
+CSRCS += st_things.c st_things_util.c st_things_request_handler.c st_things_request_handler_collection.c st_things_representation.c st_things_logger.c
+
+CFLAGS += -D__TIZENRT__
+CFLAGS += -D__TINYARA__
+CFLAGS += -D__ST_THINGS_RTOS__
+CFLAGS += -DUSE_LOG_NO_NEWLINE
+CFLAGS += -std=c99
+CFLAGS += -w
+
+####################################
+# LIBS
+####################################
+CFLAGS += -I$(THINGS_STACK_DIR)/src/common/inc
+CFLAGS += -I$(THINGS_STACK_DIR)/src/common/cloud/inc
+CFLAGS += -I$(THINGS_STACK_DIR)/src/common/easy-setup/inc
+CFLAGS += -I$(THINGS_STACK_DIR)/src/common/framework/inc
+CFLAGS += -I$(THINGS_STACK_DIR)/src/common/logging/inc
+CFLAGS += -I$(THINGS_STACK_DIR)/src/common/memory/inc
+CFLAGS += -I$(THINGS_STACK_DIR)/src/common/security/inc
+CFLAGS += -I$(THINGS_STACK_DIR)/src/common/utils/inc
+CFLAGS += -I$(THINGS_STACK_DIR)/src/common/stack
+CFLAGS += -I$(THINGS_STACK_DIR)/inc
+CFLAGS += -I$(THINGS_STACK_DIR)/src/common/security/ssCrypto/include
+CFLAGS += -I$(THINGS_STACK_DIR)/src/common/framework/inc
+
+
+#
+# THINGS STACK
+#
+CFLAGS += -DWITH_POSIX -DIP_ADAPTER
+CFLAGS += -DWITH_BWT
+#CFLAGS += -D_EXCLUDE_TEST_KEY_
+
+include $(THINGS_STACK_DIR)/Make.defs
+include $(THINGS_STACK_DIR)/src/stack/Make.defs
+include $(THINGS_STACK_DIR)/src/common/utils/Make.defs
+include $(THINGS_STACK_DIR)/src/common/framework/Make.defs
+include $(THINGS_STACK_DIR)/src/common/easy-setup/Make.defs
+include $(THINGS_STACK_DIR)/src/common/cloud/Make.defs
+include $(THINGS_STACK_DIR)/src/common/security/ssCrypto/src/Make.defs
+include $(THINGS_STACK_DIR)/src/common/logging/Make.defs
+include $(THINGS_STACK_DIR)/src/common/memory/Make.defs
+
+####################################
+# IOTIVITY
+####################################
+CFLAGS += -I$(IOTIVITY_BASE_DIR)/resource/c_common
+CFLAGS += -I$(IOTIVITY_BASE_DIR)/resource/csdk/connectivity/api
+CFLAGS += -I$(IOTIVITY_BASE_DIR)/resource/csdk/connectivity/common/inc
+CFLAGS += -I$(IOTIVITY_BASE_DIR)/resource/csdk/logger/include
+CFLAGS += -I$(IOTIVITY_BASE_DIR)/resource/csdk/security/include
+CFLAGS += -I$(IOTIVITY_BASE_DIR)/resource/csdk/security/include/internal
+CFLAGS += -I$(IOTIVITY_BASE_DIR)/resource/csdk/stack/include
+CFLAGS += -I$(IOTIVITY_BASE_DIR)/extlibs/mbedtls/mbedtls/include
+CFLAGS += -I$(IOTIVITY_BASE_DIR)/resource/c_common/oic_malloc/include
+CFLAGS += -I$(IOTIVITY_BASE_DIR)/resource/c_common/oic_string/include
+CFLAGS += -I$(IOTIVITY_BASE_DIR)/resource/c_common/ocrandom/include
+CFLAGS += -I$(IOTIVITY_BASE_DIR)/resource/c_common/oic_time/include
+CFLAGS += -I$(IOTIVITY_BASE_DIR)/resource/csdk/connectivity/api
+CFLAGS += -I$(IOTIVITY_BASE_DIR)/service/notification/src/common/
+CFLAGS += -I$(IOTIVITY_BASE_DIR)/service/notification/include/
+CFLAGS += -I$(IOTIVITY_BASE_DIR)/service/notification/src/provider/
+CFLAGS += -I$(IOTIVITY_BASE_DIR)/resource/csdk/resource-directory/include/
+CFLAGS += -I$(IOTIVITY_BASE_DIR)/resource/csdk/connectivity/lib/libcoap-4.1.1/include/
+CFLAGS += -I$(IOTIVITY_BASE_DIR)/resource/csdk/stack/include/internal/
+
+
+ifeq ($(CONFIG_IOTIVITY_ROUTING),"EP")
+CFLAGS += -DROUTING_EP
+else
+CFLAGS += -DROUTING_GW
+endif
+
+ifeq ($(CONFIG_ENABLE_IOTIVITY_SECURED),y)
+CFLAGS += -D__WITH_DTLS__
+CFLAGS += -D__ST_THINGS_RTOS_LOCAL_SECURED__
+endif
+
+ifeq ($(CONFIG_ENABLE_IOTIVITY_CLOUD),y)
+CFLAGS += -DWITH_CLOUD
+CFLAGS += -D__WITH_TLS__
+CFLAGS += -D__SECURED__
+CFLAGS += -DTCP_ADAPTER
+CFLAGS += -D__ST_THINGS_RTOS_CLOUD__
+endif
+
+DEPPATH += --dep-path src/st_things
+VPATH += :src/st_things
--- /dev/null
+/* ****************************************************************
+ *
+ * Copyright 2017 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef __ST_THINGS_RTOS__
+#include <st_things/st_things.h>
+#else
+#include "st_things.h"
+#endif // __ST_THINGS_RTOS__
+#include "st_things_request_handler.h"
+#include "st_things_representation.h"
+#include "st_things_logger.h"
+
+#include "things_api.h"
+#include "things_types.h"
+#include "things_resource.h"
+#include "ocpayload.h"
+#include "octypes.h"
+
+static st_things_reset_confirm_cb g_handle_reset_confirm_cb = NULL;
+static st_things_reset_result_cb g_handle_reset_result_cb = NULL;
+
+static st_things_pin_generated_cb g_handle_pin_generated_cb = NULL;
+static st_things_pin_display_close_cb g_handle_pin_display_close_cb = NULL;
+
+static st_things_user_confirm_cb g_handle_user_confirm_cb = NULL;
+
+static st_things_status_change_cb g_handle_things_status_change_cb = NULL;
+
+typedef enum {
+ STACK_NOT_INITIALIZED = 0,
+ STACK_INITIALIZED,
+ STACK_STARTED
+} stack_status_e;
+
+static stack_status_e g_stack_status = STACK_NOT_INITIALIZED;
+
+ /**
+ * This callback will be invoked by DA Stack with the result of reset.
+ * Result will be passed to the application through its registered callback.
+ */
+void get_reset_result_cb(int result)
+{
+ ST_LOG_ENTRY(ST_INFO);
+ ST_LOG_V(ST_DEBUG, "Result of reset is %d", result);
+ bool res = (result == 1) ? true : false;
+ if (NULL != g_handle_reset_result_cb) {
+ g_handle_reset_result_cb(res);
+ }
+ ST_LOG_EXIT(ST_INFO);
+}
+
+ /**
+ * This callback will be registered with the DA Stack to get the request for user's confirmation for reset.
+ * Application's callback will be invoked to get the user's opinion.
+ */
+int get_reset_confirm_cb(things_reset_result_func_type *func_carrier, things_es_enrollee_reset_e reset_type)
+{
+ ST_LOG_ENTRY(ST_INFO);
+ if (NULL == g_handle_reset_confirm_cb) {
+ ST_LOG_EXIT(ST_INFO);
+ return 0;
+ }
+
+ if (RST_NEED_CONFIRM == reset_type) {
+ // Invoke application's callback to get user's confirmation and pass the result to DA Stack.
+ bool confirm = g_handle_reset_confirm_cb();
+ ST_LOG_V(ST_DEBUG, "User's confirmation for reset : %s", confirm ? "true" : "false");
+ if (confirm) {
+ things_return_user_opinion_for_reset(1);
+ } else {
+ things_return_user_opinion_for_reset(0);
+ }
+ } else if (RST_AUTO_RESET == reset_type) {
+ ST_LOG(ST_DEBUG, "Reset will start automatically");
+ things_return_user_opinion_for_reset(1);
+ } else {
+ ST_LOG_V(ST_ERROR, "reset_type(%d) is invalid", reset_type);
+ ST_LOG_EXIT(ST_INFO);
+ return 0;
+ }
+
+ // Set the callback through this function's value-result paramter with DA Stack to get the result of reset.
+ *func_carrier = get_reset_result_cb;
+
+ ST_LOG_EXIT(ST_INFO);
+ return 1;
+}
+
+ /**
+ * This callback will be registered with the DA Stack to recieve easy-setup events.
+ * The status will be passed to the application through the callback registered by the application.
+ */
+void get_things_status_cb(things_es_enrollee_state_e state)
+{
+ ST_LOG_ENTRY(ST_INFO);
+ ST_LOG_V(ST_DEBUG, "Received event for easy-setup state change (%d)", state);
+ bool handled = true;
+ st_things_status_e status = ST_THINGS_STATUS_INIT;
+ switch (state) {
+ case ES_STATE_INIT:
+ status = ST_THINGS_STATUS_INIT;
+ break;
+ case ES_STATE_CONNECTING_TO_ENROLLER:
+ status = ST_THINGS_STATUS_CONNECTING_TO_AP;
+ break;
+ case ES_STATE_CONNECTED_TO_ENROLLER:
+ status = ST_THINGS_STATUS_CONNECTED_TO_AP;
+ break;
+ case ES_STATE_FAILED_TO_CONNECT_TO_ENROLLER:
+ status = ST_THINGS_STATUS_CONNECTING_TO_AP_FAILED;
+ break;
+ case ES_STATE_PUBLISHING_RESOURCES_TO_CLOUD:
+ status = ST_THINGS_STATUS_REGISTERING_TO_CLOUD;
+ break;
+ case ES_STATE_FAILED_TO_REGISTER_TO_CLOUD:
+ status = ST_THINGS_STATUS_REGISTERING_FAILED_ON_SIGN_IN;
+ break;
+ case ES_STATE_FAILED_TO_PUBLISH_RESOURCES_TO_CLOUD:
+ status = ST_THINGS_STATUS_REGISTERING_FAILED_ON_PUB_RES;
+ break;
+ case ES_STATE_PUBLISHED_RESOURCES_TO_CLOUD:
+ status = ST_THINGS_STATUS_REGISTERED_TO_CLOUD;
+ break;
+ default:
+ ST_LOG(ST_DEBUG, "This state is ignored");
+ handled = false;
+ break;
+ }
+
+ if (handled && NULL != g_handle_things_status_change_cb) {
+ g_handle_things_status_change_cb(status);
+ }
+ ST_LOG_EXIT(ST_INFO);
+}
+
+ /**
+ * DA Stack invokes this callback for providing ownership transfer states.
+ */
+void ownership_transfer_state_cb(const char *addr, uint16_t port, const char *uuid, int event)
+{
+ ST_LOG_ENTRY(ST_INFO);
+ ST_LOG_V(ST_DEBUG, "Received event for ownership-transfer state change (%d)", event);
+ (void)addr;
+ (void)port;
+ (void)uuid;
+
+ if (NULL == g_handle_things_status_change_cb) {
+ ST_LOG_EXIT(ST_INFO);
+ return;
+ }
+
+ switch (event) {
+ case 1: // OTM Started
+ g_handle_things_status_change_cb(ST_THINGS_STATUS_ES_STARTED);
+ break;
+ case 2: // OTM Done
+ g_handle_things_status_change_cb(ST_THINGS_STATUS_ES_DONE);
+ break;
+ case 3: // OTM Error
+ g_handle_things_status_change_cb(ST_THINGS_STATUS_ES_FAILED_ON_OWNERSHIP_TRANSFER);
+ break;
+ }
+ ST_LOG_EXIT(ST_INFO);
+}
+
+ /**
+ * Callback for getting users confirmation for MUTUAL VERIFICATION BASED JUST WORK Ownership transfer
+ */
+int get_user_confirm_cb(void)
+{
+ ST_LOG_ENTRY(ST_INFO);
+ if (NULL == g_handle_user_confirm_cb) {
+ ST_LOG_EXIT(ST_INFO);
+ return 0;
+ }
+
+ bool confirm = g_handle_user_confirm_cb();
+ ST_LOG_V(ST_DEBUG, "User's confirmation for MUTUAL VERIFICATION BASED JUST WORK Ownership-transfer : %s", confirm ? "true" : "false");
+
+ ST_LOG_EXIT(ST_INFO);
+ return confirm ? 1 : 0;
+}
+
+ /**
+ * Callback for getting the pin for random pin based ownership transfer.
+ */
+void generated_pin_cb(char *pin_data, size_t pin_size)
+{
+ ST_LOG_ENTRY(ST_INFO);
+ if (NULL != g_handle_pin_generated_cb) {
+ g_handle_pin_generated_cb(pin_data, pin_size);
+ }
+ ST_LOG_EXIT(ST_INFO);
+}
+
+ /**
+ * Callback for getting the close pin display request after random pin based ownership transfer.
+ */
+void close_pin_display_cb(void)
+{
+ ST_LOG_ENTRY(ST_INFO);
+ if (NULL != g_handle_pin_display_close_cb) {
+ g_handle_pin_display_close_cb();
+ }
+ ST_LOG_EXIT(ST_INFO);
+}
+
+int st_things_initialize(const char *json_path, bool *easysetup_complete)
+{
+ ST_LOG_ENTRY(ST_INFO);
+
+ if (STACK_NOT_INITIALIZED != g_stack_status) {
+ int ret_val = ST_THINGS_ERROR_OPERATION_FAILED;
+ switch (g_stack_status) {
+ case STACK_INITIALIZED:
+ ST_LOG(ST_ERROR, "Stack initialized already.");
+ ret_val = ST_THINGS_ERROR_STACK_ALREADY_INITIALIZED;
+ break;
+ case STACK_STARTED:
+ ST_LOG(ST_ERROR, "Stack is currently running.");
+ ret_val = ST_THINGS_ERROR_STACK_RUNNING;
+ break;
+ default:
+ ST_LOG_V(ST_ERROR, "Invalid stack state: %d.", g_stack_status);
+ break;
+ }
+
+ ST_LOG_EXIT(ST_INFO);
+ return ret_val;
+ }
+
+ if (NULL == json_path) {
+ ST_LOG(ST_ERROR, "Json file path is NULL");
+ ST_LOG_EXIT(ST_INFO);
+ return ST_THINGS_ERROR_INVALID_PARAMETER;
+ }
+
+ ST_LOG_V(ST_DEBUG, "JSON file path: %s", json_path);
+
+ int result = 0;
+ if (1 != (result = things_initialize_stack(json_path, easysetup_complete))) {
+ ST_LOG_V(ST_ERROR, "things_initialize_stack failed (result:%d)", result);
+ ST_LOG_EXIT(ST_INFO);
+ return ST_THINGS_ERROR_OPERATION_FAILED;
+ }
+
+ g_stack_status = STACK_INITIALIZED;
+
+ ST_LOG_V(ST_DEBUG, "Is EasySetup completed : %s", (*easysetup_complete) ? "true" : "false");
+ ST_LOG_EXIT(ST_INFO);
+ return ST_THINGS_ERROR_NONE;
+}
+
+int st_things_deinitialize(void)
+{
+ ST_LOG_ENTRY(ST_INFO);
+
+ if (STACK_INITIALIZED != g_stack_status) {
+ int ret_val = ST_THINGS_ERROR_OPERATION_FAILED;
+ switch (g_stack_status) {
+ case STACK_NOT_INITIALIZED:
+ ST_LOG(ST_ERROR, "Stack is not initialized.");
+ ret_val = ST_THINGS_ERROR_STACK_NOT_INITIALIZED;
+ break;
+ case STACK_STARTED:
+ ST_LOG(ST_ERROR, "Stack is currently running. Stop the stack before deinitializing it.");
+ ret_val = ST_THINGS_ERROR_STACK_RUNNING;
+ break;
+ default:
+ ST_LOG_V(ST_ERROR, "Invalid stack state: %d.", g_stack_status);
+ break;
+ }
+
+ ST_LOG_EXIT(ST_INFO);
+ return ret_val;
+ }
+
+ int result = 0;
+ if (1 != (result = things_deinitialize_stack())) {
+ ST_LOG_V(ST_ERROR, "things_deinitialize_stack failed (result:%d)", result);
+ ST_LOG_EXIT(ST_INFO);
+ return ST_THINGS_ERROR_OPERATION_FAILED;
+ }
+
+ g_stack_status = STACK_NOT_INITIALIZED;
+
+ ST_LOG_EXIT(ST_INFO);
+ return ST_THINGS_ERROR_NONE;
+}
+
+int st_things_start(void)
+{
+ ST_LOG_INIT();
+ ST_LOG_ENTRY(ST_INFO);
+
+ if (STACK_INITIALIZED != g_stack_status) {
+ int ret_val = ST_THINGS_ERROR_OPERATION_FAILED;
+ switch (g_stack_status) {
+ case STACK_NOT_INITIALIZED:
+ ST_LOG(ST_ERROR, "Stack is not initialized.");
+ ret_val = ST_THINGS_ERROR_STACK_NOT_INITIALIZED;
+ break;
+ case STACK_STARTED:
+ ST_LOG(ST_DEBUG, "Stack started already.");
+ ret_val = ST_THINGS_ERROR_NONE;
+ break;
+ default:
+ ST_LOG_V(ST_ERROR, "Invalid stack state: %d.", g_stack_status);
+ break;
+ }
+
+ ST_LOG_EXIT(ST_INFO);
+ return ret_val;
+ }
+
+ int result = 0;
+
+ // Register callback for reset confirmation.
+ if (1 != (result = things_register_confirm_reset_start_func(get_reset_confirm_cb))) {
+ ST_LOG_V(ST_ERROR, "things_register_confirm_reset_start_func failed (result:%d)", result);
+ goto error;
+ }
+ // Register callback for easy-setup status.
+ if (1 != (result = things_register_easysetup_state_func(get_things_status_cb))) {
+ ST_LOG_V(ST_ERROR, "things_register_easysetup_state_func failed (result:%d)", result);
+ goto error;
+ }
+ // Register callback for receiving the Security Ownership Transfer state changes.
+ if (1 != (result = things_register_otm_event_handler(ownership_transfer_state_cb))) {
+ ST_LOG_V(ST_ERROR, "things_register_otm_event_handler failed (result:%d)", result);
+ goto error;
+ }
+ // Register callback for receiving request during ownership transfer for getting confirmation from user.
+ if (1 != (result = things_register_user_confirm_func(get_user_confirm_cb))) {
+ ST_LOG_V(ST_ERROR, "things_register_user_confirm_func failed (result:%d)", result);
+ goto error;
+ }
+ // Register callback for receiving the pin generated for ownership transfer.
+ if (1 != (result = things_register_pin_generated_func(generated_pin_cb))) {
+ ST_LOG_V(ST_ERROR, "things_register_pin_generated_func failed (result:%d)", result);
+ goto error;
+ }
+ // Register callback to receiving request for closing the PIN display.
+ if (1 != (result = things_register_pin_display_close_func(close_pin_display_cb))) {
+ ST_LOG_V(ST_ERROR, "things_register_pin_display_close_func failed (result:%d)", result);
+ goto error;
+ }
+ // Register callback to handle GET and POST requests.
+ if (1 != (result = things_register_handle_request_func(handle_get_request_cb, handle_set_request_cb))) {
+ ST_LOG_V(ST_ERROR, "things_register_handle_request_func failed (result:%d)", result);
+ goto error;
+ }
+ // Start DA Stack.
+ if (1 != (result = things_start_stack())) {
+ ST_LOG_V(ST_ERROR, "things_start_stack failed (result:%d)", result);
+ goto error;
+ }
+
+ g_stack_status = STACK_STARTED;
+
+ ST_LOG_EXIT(ST_INFO);
+ return ST_THINGS_ERROR_NONE;
+
+ error:
+ ST_LOG_EXIT(ST_INFO);
+ return ST_THINGS_ERROR_OPERATION_FAILED;
+}
+
+int st_things_stop(void)
+{
+ ST_LOG_ENTRY(ST_INFO);
+
+ if (STACK_STARTED != g_stack_status) {
+ int ret_val = ST_THINGS_ERROR_OPERATION_FAILED;
+ switch (g_stack_status) {
+ case STACK_NOT_INITIALIZED:
+ ST_LOG(ST_ERROR, "Stack is not initialized.");
+ ret_val = ST_THINGS_ERROR_STACK_NOT_INITIALIZED;
+ break;
+ case STACK_INITIALIZED:
+ ST_LOG(ST_ERROR, "Stack is not started.");
+ ret_val = ST_THINGS_ERROR_STACK_NOT_STARTED;
+ break;
+ default:
+ ST_LOG_V(ST_ERROR, "Invalid stack state: %d.", g_stack_status);
+ break;
+ }
+
+ ST_LOG_EXIT(ST_INFO);
+ return ret_val;
+ }
+
+ int result = 0;
+
+ // Terminate DA Stack.
+ if (1 != (result = things_stop())) {
+ ST_LOG_V(ST_ERROR, "things_stop failed (result:%d)", result);
+ ST_LOG_EXIT(ST_INFO);
+ return ST_THINGS_ERROR_OPERATION_FAILED;
+ }
+
+ g_stack_status = STACK_INITIALIZED;
+
+ ST_LOG_EXIT(ST_INFO);
+ ST_LOG_DEINIT();
+ return ST_THINGS_ERROR_NONE;
+}
+
+int st_things_register_request_cb(st_things_get_request_cb get_cb, st_things_set_request_cb set_cb)
+{
+ ST_LOG_ENTRY(ST_INFO);
+ if (NULL == get_cb || NULL == set_cb) {
+ ST_LOG_EXIT(ST_INFO);
+ return ST_THINGS_ERROR_INVALID_PARAMETER;
+ }
+
+ ST_LOG_EXIT(ST_INFO);
+ return register_request_handler_cb(get_cb, set_cb);
+}
+
+int st_things_register_reset_cb(st_things_reset_confirm_cb confirm_cb, st_things_reset_result_cb result_cb)
+{
+ ST_LOG_ENTRY(ST_INFO);
+ if (NULL == confirm_cb || NULL == result_cb) {
+ ST_LOG_EXIT(ST_INFO);
+ return ST_THINGS_ERROR_INVALID_PARAMETER;
+ }
+
+ g_handle_reset_confirm_cb = confirm_cb;
+ g_handle_reset_result_cb = result_cb;
+
+ ST_LOG_EXIT(ST_INFO);
+ return ST_THINGS_ERROR_NONE;
+}
+
+int st_things_reset(void)
+{
+ ST_LOG_ENTRY(ST_INFO);
+
+ if (STACK_STARTED != g_stack_status) {
+ int ret_val = ST_THINGS_ERROR_OPERATION_FAILED;
+ switch (g_stack_status) {
+ case STACK_NOT_INITIALIZED:
+ ST_LOG(ST_ERROR, "Stack is not initialized. Before reset, stack should be initialized and started.");
+ ret_val = ST_THINGS_ERROR_STACK_NOT_INITIALIZED;
+ break;
+ case STACK_INITIALIZED:
+ ST_LOG(ST_ERROR, "Stack is initialized but not started.");
+ ret_val = ST_THINGS_ERROR_STACK_NOT_STARTED;
+ break;
+ default:
+ ST_LOG_V(ST_ERROR, "Invalid stack state: %d.", g_stack_status);
+ break;
+ }
+
+ ST_LOG_EXIT(ST_INFO);
+ return ret_val;
+ }
+
+ int result = 0;
+ if (1 != (result = things_reset(NULL, RST_AUTO_RESET))) {
+ ST_LOG_V(ST_ERROR, "things_reset failed (result:%d)", result);
+ ST_LOG_EXIT(ST_INFO);
+ return ST_THINGS_ERROR_OPERATION_FAILED;
+ }
+
+ ST_LOG_EXIT(ST_INFO);
+ return ST_THINGS_ERROR_NONE;
+}
+
+int st_things_register_pin_handling_cb(st_things_pin_generated_cb generated_cb, st_things_pin_display_close_cb close_cb)
+{
+ ST_LOG_ENTRY(ST_INFO);
+ if (NULL == generated_cb || NULL == close_cb) {
+ ST_LOG_EXIT(ST_INFO);
+ return ST_THINGS_ERROR_INVALID_PARAMETER;
+ }
+
+ g_handle_pin_generated_cb = generated_cb;
+ g_handle_pin_display_close_cb = close_cb;
+
+ ST_LOG_EXIT(ST_INFO);
+ return ST_THINGS_ERROR_NONE;
+}
+
+int st_things_register_user_confirm_cb(st_things_user_confirm_cb confirm_cb)
+{
+ ST_LOG_ENTRY(ST_INFO);
+ if (NULL == confirm_cb) {
+ ST_LOG_EXIT(ST_INFO);
+ return ST_THINGS_ERROR_INVALID_PARAMETER;
+ }
+
+ g_handle_user_confirm_cb = confirm_cb;
+
+ ST_LOG_EXIT(ST_INFO);
+ return ST_THINGS_ERROR_NONE;
+}
+
+int st_things_register_things_status_change_cb(st_things_status_change_cb status_cb)
+{
+ ST_LOG_ENTRY(ST_INFO);
+ if (NULL == status_cb) {
+ ST_LOG_EXIT(ST_INFO);
+ return ST_THINGS_ERROR_INVALID_PARAMETER;
+ }
+
+ g_handle_things_status_change_cb = status_cb;
+
+ ST_LOG_EXIT(ST_INFO);
+ return ST_THINGS_ERROR_NONE;
+}
+
+int st_things_notify_observers(const char *resource_uri)
+{
+ ST_LOG_ENTRY(ST_INFO);
+
+ if (STACK_STARTED != g_stack_status) {
+ int ret_val = ST_THINGS_ERROR_OPERATION_FAILED;
+ switch (g_stack_status) {
+ case STACK_NOT_INITIALIZED:
+ ST_LOG(ST_ERROR, "Stack is not initialized. Before notifying observers, stack should be initialized and started.");
+ ret_val = ST_THINGS_ERROR_STACK_NOT_INITIALIZED;
+ break;
+ case STACK_INITIALIZED:
+ ST_LOG(ST_ERROR, "Stack is initialized but not started.");
+ ret_val = ST_THINGS_ERROR_STACK_NOT_STARTED;
+ break;
+ default:
+ ST_LOG_V(ST_ERROR, "Invalid stack state: %d.", g_stack_status);
+ break;
+ }
+
+ ST_LOG_EXIT(ST_INFO);
+ return ret_val;
+ }
+
+ if (NULL == resource_uri || 1 > strlen(resource_uri)) {
+ ST_LOG(ST_ERROR, "The resource URI is invalid");
+ ST_LOG_EXIT(ST_INFO);
+ return ST_THINGS_ERROR_INVALID_PARAMETER;
+ }
+
+ int result = 0;
+ if (1 != (result = things_notify_observers(resource_uri))) {
+ ST_LOG_V(ST_ERROR, "things_notify_observers failed (result:%d)", result);
+ ST_LOG_EXIT(ST_INFO);
+ return ST_THINGS_ERROR_OPERATION_FAILED;
+ }
+
+ ST_LOG_EXIT(ST_INFO);
+ return ST_THINGS_ERROR_NONE;
+}
+
+st_things_representation_s *st_things_create_representation_inst()
+{
+ ST_LOG_ENTRY(ST_INFO);
+ st_things_representation_s *rep = create_representation_inst();
+ ST_LOG_EXIT(ST_INFO);
+ return rep;
+}
+
+void st_things_destroy_representation_inst(st_things_representation_s *rep)
+{
+ ST_LOG_ENTRY(ST_INFO);
+ destroy_representation_inst(rep);
+ ST_LOG_EXIT(ST_INFO);
+}
--- /dev/null
+/* ****************************************************************
+ *
+ * Copyright 2017 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.
+ *
+ ******************************************************************/
+
+#ifndef _POSIX_C_SOURCE
+#define _POSIX_C_SOURCE 200809L
+#endif
+
+#include <unistd.h>
+#include <time.h>
+#include <sys/time.h>
+#include <stdlib.h>
+
+#include "st_things_logger.h"
+#include "string.h"
+
+#ifndef __TIZEN__
+static const uint16_t LINE_BUFFER_SIZE = 255;
+static const char *LEVEL[] __attribute__ ((unused)) = {
+"DEBUG", "INFO", "WARNING", "ERROR", "FATAL"};
+
+static char *p_version = NULL;
+
+void st_things_log_init()
+{
+ /* Initialize p_version variable */
+ p_version = NULL;
+}
+
+void st_things_log_shutdown()
+{
+ /* Free the memory allocated for p_version */
+ free(p_version);
+}
+
+void st_things_log_set_version(char *version)
+{
+ if (NULL == version) {
+ return;
+ }
+
+ if (NULL != p_version) {
+ free(p_version);
+ }
+
+ /* Allocate memory for p_version and set the version information */
+ p_version = (char *)malloc(strlen(version) + 1);
+ if (NULL == p_version) {
+ printf("Error while allocating memory for version");
+ return;
+ }
+ memset(p_version, 0, strlen(version) + 1);
+ strncpy(p_version, version, strlen(version));
+}
+
+/**
+ * Output a log string with the specified priority level.
+ * Only defined for Linux and Android
+ *
+ * @param level - ST_DEBUG, ST_INFO, ST_WARNING, ST_ERROR, ST_FATAL
+ * @param tag - Module name
+ * @param log_str - log string
+ */
+void st_things_log(st_things_log_level_e level, const char *tag, const char *func_name, const int16_t line_num, const char *log_str)
+{
+ if (!log_str || !tag) {
+ return;
+ }
+
+ struct timeval tv;
+ time_t now_time = 0;
+ struct tm *now_tm = NULL;
+ char tm_buf[64] = { 0 };
+
+ gettimeofday(&tv, NULL);
+ now_time = tv.tv_sec;
+ now_tm = localtime(&now_time);
+ strftime(tm_buf, sizeof tm_buf, "%m/%d %H:%M:%S", now_tm);
+
+ if (p_version) {
+ printf("[%s %s] %s %s %s %d %s\n", tm_buf, p_version, LEVEL[level], tag, func_name, line_num, log_str);
+ } else {
+ printf("[%s] %s %s %s %d %s\n", tm_buf, LEVEL[level], tag, func_name, line_num, log_str);
+ }
+}
+
+/**
+ * Output a variable argument list log string with the specified priority level.
+ * Only defined for Linux and Android
+ *
+ * @param level - ST_DEBUG, ST_INFO, ST_WARNING, ST_ERROR, ST_FATAL
+ * @param tag - Module name
+ * @param format - variadic log string
+ */
+void st_things_log_v(st_things_log_level_e level, const char *tag, const char *func_name, const int16_t line_num, const char *format, ...)
+{
+ if (!format || !tag) {
+ return;
+ }
+
+ /* Using Variable arguments to extract each argument and passing it st_things_log API */
+ char buffer[MAX_LOG_V_BUFFER_SIZE] = { 0 };
+ va_list args;
+ va_start(args, format);
+ vsnprintf(buffer, sizeof buffer - 1, format, args);
+ va_end(args);
+ st_things_log(level, tag, func_name, line_num, buffer);
+}
+#endif //#ifndef __TIZEN__
--- /dev/null
+/* ****************************************************************
+ *
+ * Copyright 2017 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.
+ *
+ ******************************************************************/
+
+#ifndef __ST_THINGS_LOGGER_H__
+#define __ST_THINGS_LOGGER_H__
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#ifdef __TIZEN__
+#include <dlog.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* Log Value Macro's */
+#define ST_THINGS_FUNC_ENTRY "IN"
+#define ST_THINGS_FUNC_EXIT "OUT"
+#define ST_THINGS_MEMORY_ERROR "Memory Error"
+#define ST_THINGS_INVALID_PARAM "Invalid Parameter"
+#define ST_THINGS_TAG "ST_THINGS_SDK"
+
+// Max buffer size used in variable argument log function
+#define MAX_LOG_V_BUFFER_SIZE (256)
+
+// Log levels
+#ifdef __TIZEN__
+ typedef enum {
+ ST_DEBUG = DLOG_DEBUG,
+ ST_INFO = DLOG_INFO,
+ ST_WARNING = DLOG_WARN,
+ ST_ERROR = DLOG_ERROR,
+ ST_FATAL = DLOG_FATAL
+ } st_things_log_level_e;
+#endif
+
+#ifndef __TIZEN__ /* Linux */
+ typedef enum {
+ ST_DEBUG,
+ ST_INFO,
+ ST_WARNING,
+ ST_ERROR,
+ ST_FATAL
+ } st_things_log_level_e;
+
+ /**
+ * Initialize the logger.
+ */
+ void st_things_log_init();
+
+ /**
+ * Called to Free dyamically allocated resources used with custom logging.
+ * Not necessary if default logging is used
+ */
+ void st_things_log_shutdown();
+
+ /**
+ * Set the Version.
+ */
+ void st_things_log_set_version(char *version);
+
+ /**
+ * Output a log string with the specified priority level.
+ * Only defined for Linux and Android
+ *
+ * @param level - ST_DEBUG, ST_INFO, ST_WARNING, ST_ERROR, ST_FATAL
+ * @param tag - Module name
+ * @param log_str - log string
+ */
+ void st_things_log(st_things_log_level_e level, const char *tag, const char *func_name, const int16_t line_num, const char *log_str);
+
+ /**
+ * Output a variable argument list log string with the specified priority level.
+ * @param level - ST_DEBUG, ST_INFO, ST_WARNING, ST_ERROR, ST_FATAL
+ * @param tag - Module name
+ * @param format - variadic log string
+ */
+ void st_things_log_v(st_things_log_level_e level, const char *tag, const char *func_name, const int16_t line_num, const char *format, ...);
+#endif //#ifndef __TIZEN__
+
+#ifdef FEATURE_LOGGING
+#ifdef __TIZEN__
+#define ST_LOG_INIT()
+#define ST_LOG_DEINIT()
+#define ST_LOG(level, log_str) dlog_print(level, ST_THINGS_TAG, "%s : %s(%d) > " log_str, __FILE__, __FUNCTION__, __LINE__)
+#define ST_LOG_V(level, fmt, ...) dlog_print(level, ST_THINGS_TAG, "%s : %s(%d) > " fmt, __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__)
+#define ST_LOG_ENTRY(level) dlog_print(level, ST_THINGS_TAG, "%s : %s(%d) > " ST_THINGS_FUNC_ENTRY, __FILE__, __FUNCTION__, __LINE__)
+#define ST_LOG_EXIT(level) dlog_print(level, ST_THINGS_TAG, "%s : %s(%d) > " ST_THINGS_FUNC_EXIT, __FILE__, __FUNCTION__, __LINE__)
+#else /* Linux */
+#define ST_LOG_INIT() st_things_log_init()
+#define ST_LOG_DEINIT() st_things_log_shutdown()
+#define ST_LOG(level, log_str) st_things_log((level), ST_THINGS_TAG, __FUNCTION__, __LINE__, (log_str))
+#define ST_LOG_V(level, fmt, ...) st_things_log_v((level), ST_THINGS_TAG, __FUNCTION__, __LINE__, fmt, __VA_ARGS__)
+#define ST_LOG_ENTRY(level) st_things_log((level), ST_THINGS_TAG, __FUNCTION__, __LINE__, (ST_THINGS_FUNC_ENTRY))
+#define ST_LOG_EXIT(level) st_things_log((level), ST_THINGS_TAG, __FUNCTION__, __LINE__, (ST_THINGS_FUNC_EXIT))
+#endif
+#else //DISABLE LOGGING
+#define ST_LOG_INIT()
+#define ST_LOG_DEINIT()
+#define ST_LOG(level, log_str)
+#define ST_LOG_V(level, fmt, ...)
+#define ST_LOG_ENTRY(level)
+#define ST_LOG_EXIT(level)
+#endif // FEATURE_LOGGING
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __ST_THINGS_LOGGER_H__ */
--- /dev/null
+/* ****************************************************************
+ *
+ * Copyright 2017 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 "st_things_representation.h"
+#include "st_things_util.h"
+#include "st_things_logger.h"
+#include "ocpayload.h"
+
+bool get_str_value(struct _st_things_representation *rep, const char *key, char **value)
+{
+ RET_FALSE_IF_PARAM_IS_NULL(rep);
+ RET_FALSE_IF_PARAM_IS_NULL(rep->payload);
+ RET_FALSE_IF_PARAM_IS_NULL(key);
+ RET_FALSE_IF_PARAM_IS_NULL(value);
+
+ return OCRepPayloadGetPropString((OCRepPayload *) rep->payload, key, value);
+}
+
+bool get_bool_value(struct _st_things_representation *rep, const char *key, bool *value)
+{
+ RET_FALSE_IF_PARAM_IS_NULL(rep);
+ RET_FALSE_IF_PARAM_IS_NULL(rep->payload);
+ RET_FALSE_IF_PARAM_IS_NULL(key);
+ RET_FALSE_IF_PARAM_IS_NULL(value);
+
+ return OCRepPayloadGetPropBool((OCRepPayload *) rep->payload, key, value);
+}
+
+bool get_int_value(struct _st_things_representation *rep, const char *key, int64_t *value)
+{
+ RET_FALSE_IF_PARAM_IS_NULL(rep);
+ RET_FALSE_IF_PARAM_IS_NULL(rep->payload);
+ RET_FALSE_IF_PARAM_IS_NULL(key);
+ RET_FALSE_IF_PARAM_IS_NULL(value);
+
+ return OCRepPayloadGetPropInt((OCRepPayload *)rep->payload, key, value);
+}
+
+bool get_double_value(struct _st_things_representation *rep, const char *key, double *value)
+{
+ RET_FALSE_IF_PARAM_IS_NULL(rep);
+ RET_FALSE_IF_PARAM_IS_NULL(rep->payload);
+ RET_FALSE_IF_PARAM_IS_NULL(key);
+ RET_FALSE_IF_PARAM_IS_NULL(value);
+
+ return OCRepPayloadGetPropDouble((OCRepPayload *) rep->payload, key, value);
+}
+
+bool get_byte_value(struct _st_things_representation *rep, const char *key, uint8_t **value, size_t *size)
+{
+ RET_FALSE_IF_PARAM_IS_NULL(rep);
+ RET_FALSE_IF_PARAM_IS_NULL(rep->payload);
+ RET_FALSE_IF_PARAM_IS_NULL(key);
+ RET_FALSE_IF_PARAM_IS_NULL(value);
+ RET_FALSE_IF_PARAM_IS_NULL(size);
+
+ OCByteString byte_value = { NULL, 0 };
+ if (!OCRepPayloadGetPropByteString((OCRepPayload *)rep->payload, key, &byte_value)) {
+ return false;
+ }
+
+ (*size) = byte_value.len;
+ (*value) = byte_value.bytes;
+
+ return true;
+}
+
+bool get_object_value(struct _st_things_representation *rep, const char *key, struct _st_things_representation **value)
+{
+ RET_FALSE_IF_PARAM_IS_NULL(rep);
+ RET_FALSE_IF_PARAM_IS_NULL(rep->payload);
+ RET_FALSE_IF_PARAM_IS_NULL(key);
+ RET_FALSE_IF_PARAM_IS_NULL(value);
+
+ OCRepPayload *payload = NULL;
+ bool result = OCRepPayloadGetPropObject(rep->payload, key, &payload);
+ if (result) {
+ *value = create_representation_inst_internal(payload);
+ if (NULL == *value) {
+ ST_LOG(ST_ERROR, "Failed to create representation for value.");
+ OCRepPayloadDestroy(payload);
+ return false;
+ }
+ }
+ return result;
+}
+
+bool set_str_value(struct _st_things_representation *rep, const char *key, const char *value)
+{
+ RET_FALSE_IF_PARAM_IS_NULL(rep);
+ RET_FALSE_IF_PARAM_IS_NULL(rep->payload);
+ RET_FALSE_IF_PARAM_IS_NULL(key);
+ RET_FALSE_IF_PARAM_IS_NULL(value);
+
+ return OCRepPayloadSetPropString(rep->payload, key, value);
+}
+
+bool set_bool_value(struct _st_things_representation *rep, const char *key, bool value)
+{
+ RET_FALSE_IF_PARAM_IS_NULL(rep);
+ RET_FALSE_IF_PARAM_IS_NULL(rep->payload);
+ RET_FALSE_IF_PARAM_IS_NULL(key);
+
+ return OCRepPayloadSetPropBool(rep->payload, key, value);
+}
+
+bool set_int_value(struct _st_things_representation *rep, const char *key, int64_t value)
+{
+ RET_FALSE_IF_PARAM_IS_NULL(rep);
+ RET_FALSE_IF_PARAM_IS_NULL(rep->payload);
+ RET_FALSE_IF_PARAM_IS_NULL(key);
+
+ return OCRepPayloadSetPropInt(rep->payload, key, value);
+}
+
+bool set_double_value(struct _st_things_representation *rep, const char *key, double value)
+{
+ RET_FALSE_IF_PARAM_IS_NULL(rep);
+ RET_FALSE_IF_PARAM_IS_NULL(rep->payload);
+ RET_FALSE_IF_PARAM_IS_NULL(key);
+
+ return OCRepPayloadSetPropDouble(rep->payload, key, value);
+}
+
+bool set_byte_value(struct _st_things_representation *rep, const char *key, const uint8_t *value, size_t size)
+{
+ RET_FALSE_IF_PARAM_IS_NULL(rep);
+ RET_FALSE_IF_PARAM_IS_NULL(rep->payload);
+ RET_FALSE_IF_PARAM_IS_NULL(key);
+ RET_FALSE_IF_PARAM_IS_NULL(value);
+ RET_FALSE_IF_PARAM_EXPR_IS_TRUE(size < 1);
+
+ OCByteString bVal = { (uint8_t *) /*To resolve a build warning */ value, size };
+ return OCRepPayloadSetPropByteString(rep->payload, key, bVal);
+}
+
+bool set_object_value(struct _st_things_representation *rep, const char *key, const struct _st_things_representation *value)
+{
+ RET_FALSE_IF_PARAM_IS_NULL(rep);
+ RET_FALSE_IF_PARAM_IS_NULL(rep->payload);
+ RET_FALSE_IF_PARAM_IS_NULL(key);
+ RET_FALSE_IF_PARAM_IS_NULL(value);
+ RET_FALSE_IF_PARAM_IS_NULL(value->payload);
+
+ return OCRepPayloadSetPropObject(rep->payload, key, value->payload);
+}
+
+bool get_str_array_value(struct _st_things_representation *rep, const char *key, char ***array, size_t *length)
+{
+ RET_FALSE_IF_PARAM_IS_NULL(rep);
+ RET_FALSE_IF_PARAM_IS_NULL(rep->payload);
+ RET_FALSE_IF_PARAM_IS_NULL(key);
+ RET_FALSE_IF_PARAM_IS_NULL(array);
+ RET_FALSE_IF_PARAM_IS_NULL(length);
+
+ size_t dimensions[MAX_REP_ARRAY_DEPTH] = { 0 };
+ bool ret = OCRepPayloadGetStringArray(rep->payload, key, array, dimensions);
+ if (true == ret) {
+ *length = calcDimTotal(dimensions);
+ }
+
+ return ret;
+}
+
+bool get_int_array_value(struct _st_things_representation *rep, const char *key, int64_t **array, size_t *length)
+{
+ RET_FALSE_IF_PARAM_IS_NULL(rep);
+ RET_FALSE_IF_PARAM_IS_NULL(rep->payload);
+ RET_FALSE_IF_PARAM_IS_NULL(key);
+ RET_FALSE_IF_PARAM_IS_NULL(array);
+ RET_FALSE_IF_PARAM_IS_NULL(length);
+
+ size_t dimensions[MAX_REP_ARRAY_DEPTH] = { 0 };
+ bool ret = OCRepPayloadGetIntArray(rep->payload, key, array, dimensions);
+ if (true == ret) {
+ *length = calcDimTotal(dimensions);
+ }
+
+ return ret;
+}
+
+bool get_double_array_value(struct _st_things_representation *rep, const char *key, double **array, size_t *length)
+{
+ RET_FALSE_IF_PARAM_IS_NULL(rep);
+ RET_FALSE_IF_PARAM_IS_NULL(rep->payload);
+ RET_FALSE_IF_PARAM_IS_NULL(key);
+ RET_FALSE_IF_PARAM_IS_NULL(array);
+ RET_FALSE_IF_PARAM_IS_NULL(length);
+
+ size_t dimensions[MAX_REP_ARRAY_DEPTH] = { 0 };
+ bool ret = OCRepPayloadGetDoubleArray(rep->payload, key, array, dimensions);
+ if (true == ret) {
+ *length = calcDimTotal(dimensions);
+ }
+
+ return ret;
+}
+
+bool get_object_array_value(struct _st_things_representation *rep, const char *key, struct _st_things_representation ***array, size_t *length)
+{
+ RET_FALSE_IF_PARAM_IS_NULL(rep);
+ RET_FALSE_IF_PARAM_IS_NULL(rep->payload);
+ RET_FALSE_IF_PARAM_IS_NULL(key);
+ RET_FALSE_IF_PARAM_IS_NULL(array);
+ RET_FALSE_IF_PARAM_IS_NULL(length);
+
+ size_t dimensions[MAX_REP_ARRAY_DEPTH] = { 0 };
+ OCRepPayload **children = NULL;
+ bool ret = OCRepPayloadGetPropObjectArray(rep->payload, key, &children, dimensions);
+ if (!ret) {
+ return false;
+ }
+
+ *length = calcDimTotal(dimensions);
+ *array = (struct _st_things_representation **)util_calloc((*length), sizeof(struct _st_things_representation *));
+ if (NULL == *array) {
+ ST_LOG(ST_ERROR, "Failed to allocate memory for object array value.");
+ for (size_t index = 0; index < *length; index++) {
+ OCPayloadDestroy((OCPayload *) children[index]);
+ }
+ util_free(children);
+ return false;
+ }
+
+ for (size_t index = 0; index < *length; index++) {
+ if (NULL == children[index]) {
+ ST_LOG_V(ST_ERROR, "Payload at index(%d) is NULL.", index);
+ } else {
+ (*array)[index] = create_representation_inst_internal(children[index]);
+ if (NULL == (*array)[index]) {
+ ST_LOG(ST_ERROR, "Failed to create a representation for object array value.");
+ }
+ }
+
+ if (NULL == (*array)[index]) {
+ for (size_t sub_index = 0; sub_index < index; sub_index++) {
+ destroy_representation_inst_internal((*array)[sub_index], true);
+ }
+ util_free(*array);
+ *array = NULL;
+ *length = 0;
+
+ for (size_t sub_index = index; sub_index < *length; sub_index++) {
+ OCPayloadDestroy((OCPayload *) children[sub_index]);
+ }
+ util_free(children);
+ return false;
+ }
+ }
+
+ util_free(children);
+ return true;
+}
+
+bool set_str_array_value(struct _st_things_representation *rep, const char *key, const char **array, size_t length)
+{
+ RET_FALSE_IF_PARAM_IS_NULL(rep);
+ RET_FALSE_IF_PARAM_IS_NULL(rep->payload);
+ RET_FALSE_IF_PARAM_IS_NULL(key);
+ RET_FALSE_IF_PARAM_IS_NULL(array);
+ RET_FALSE_IF_PARAM_EXPR_IS_TRUE(length < 1);
+
+ size_t dimensions[MAX_REP_ARRAY_DEPTH] = { length, 0, 0 };
+ return OCRepPayloadSetStringArray(rep->payload, key, array, dimensions);
+}
+
+bool set_int_array_value(struct _st_things_representation *rep, const char *key, const int64_t *array, size_t length)
+{
+ RET_FALSE_IF_PARAM_IS_NULL(rep);
+ RET_FALSE_IF_PARAM_IS_NULL(rep->payload);
+ RET_FALSE_IF_PARAM_IS_NULL(key);
+ RET_FALSE_IF_PARAM_IS_NULL(array);
+ RET_FALSE_IF_PARAM_EXPR_IS_TRUE(length < 1);
+
+ size_t dimensions[MAX_REP_ARRAY_DEPTH] = { length, 0, 0 };
+ return OCRepPayloadSetIntArray(rep->payload, key, array, dimensions);
+}
+
+bool set_double_array_value(struct _st_things_representation *rep, const char *key, const double *array, size_t length)
+{
+ RET_FALSE_IF_PARAM_IS_NULL(rep);
+ RET_FALSE_IF_PARAM_IS_NULL(rep->payload);
+ RET_FALSE_IF_PARAM_IS_NULL(key);
+ RET_FALSE_IF_PARAM_IS_NULL(array);
+ RET_FALSE_IF_PARAM_EXPR_IS_TRUE(length < 1);
+
+ size_t dimensions[MAX_REP_ARRAY_DEPTH] = { length, 0, 0 };
+ return OCRepPayloadSetDoubleArray(rep->payload, key, array, dimensions);
+}
+
+bool set_object_array_value(struct _st_things_representation *rep, const char *key, const struct _st_things_representation **array, size_t length)
+{
+ RET_FALSE_IF_PARAM_IS_NULL(rep);
+ RET_FALSE_IF_PARAM_IS_NULL(rep->payload);
+ RET_FALSE_IF_PARAM_IS_NULL(key);
+ RET_FALSE_IF_PARAM_IS_NULL(array);
+ RET_FALSE_IF_PARAM_EXPR_IS_TRUE(length < 1);
+
+ OCRepPayload **value_payload = NULL;
+ value_payload = (OCRepPayload **) util_malloc(length * sizeof(OCRepPayload *));
+ if (NULL == value_payload) {
+ ST_LOG(ST_ERROR, "Failed to allocate memory for object array value.");
+ return false;
+ }
+
+ for (size_t i = 0; i < length; i++) {
+ if (NULL == array[i]) {
+ ST_LOG_V(ST_ERROR, "array[%d] is NULL.", i);
+ util_free(value_payload);
+ return false;
+ }
+ if (NULL == array[i]->payload) {
+ ST_LOG_V(ST_ERROR, "array[%d]->payload is NULL.", i);
+ util_free(value_payload);
+ return false;
+ }
+ value_payload[i] = array[i]->payload;
+ }
+
+ size_t dimensions[MAX_REP_ARRAY_DEPTH] = { length, 0, 0 };
+ bool res = OCRepPayloadSetPropObjectArray(rep->payload, key, (const OCRepPayload **)value_payload, dimensions);
+ util_free(value_payload);
+
+ return res;
+}
+
+st_things_representation_s *create_representation_inst_internal(OCRepPayload *payload)
+{
+ st_things_representation_s *rep = (st_things_representation_s *) util_malloc(sizeof(st_things_representation_s));
+ RET_VAL_IF_NULL(rep, "Failed to allocate memory for representation.", NULL);
+
+ rep->get_str_value = &get_str_value;
+ rep->get_bool_value = &get_bool_value;
+ rep->get_int_value = &get_int_value;
+ rep->get_double_value = &get_double_value;
+ rep->get_byte_value = &get_byte_value;
+ rep->get_object_value = &get_object_value;
+
+ rep->set_str_value = &set_str_value;
+ rep->set_bool_value = &set_bool_value;
+ rep->set_int_value = &set_int_value;
+ rep->set_double_value = &set_double_value;
+ rep->set_byte_value = &set_byte_value;
+ rep->set_object_value = &set_object_value;
+
+ rep->get_str_array_value = &get_str_array_value;
+ rep->get_int_array_value = &get_int_array_value;
+ rep->get_double_array_value = &get_double_array_value;
+ rep->get_object_array_value = &get_object_array_value;
+
+ rep->set_str_array_value = &set_str_array_value;
+ rep->set_int_array_value = &set_int_array_value;
+ rep->set_double_array_value = &set_double_array_value;
+ rep->set_object_array_value = &set_object_array_value;
+
+ if (NULL != payload) {
+ ST_LOG(ST_DEBUG, "Setting the given payload in the representation.");
+ rep->payload = payload;
+ } else {
+ ST_LOG(ST_DEBUG, "Creating a new payload and setting it in the representation.");
+ rep->payload = OCRepPayloadCreate();
+ if (NULL == rep->payload) {
+ ST_LOG(ST_ERROR, "Failed to create payload for representation.");
+ destroy_representation_inst_internal(rep, false);
+ return NULL;
+ }
+ }
+
+ return rep;
+}
+
+st_things_representation_s *create_representation_inst(void)
+{
+ return create_representation_inst_internal(NULL);
+}
+
+void destroy_representation_inst_internal(st_things_representation_s *rep, bool destroy_payload)
+{
+ RET_IF_PARAM_IS_NULL(rep);
+
+ ST_LOG_V(ST_DEBUG, "Destroy payload: %s.", destroy_payload ? "Yes" : "No");
+
+ // Payload will be de-allocated for the following cases.
+ // 1. For request representations(created at this API layer).
+ // 2. For all representations created by the application.
+ // DA Stack will de-allocate the payload for other cases.
+ // 1. For response representations.
+ if (destroy_payload) {
+ OCPayloadDestroy((OCPayload *) (rep->payload));
+ }
+
+ util_free(rep);
+}
+
+void destroy_representation_inst(st_things_representation_s *rep)
+{
+ destroy_representation_inst_internal(rep, true);
+}
--- /dev/null
+/* ****************************************************************
+ *
+ * Copyright 2017 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.
+ *
+ ******************************************************************/
+
+#ifndef __ST_THINGS_REPRESENTATION_H__
+#define __ST_THINGS_REPRESENTATION_H__
+
+#ifdef __ST_THINGS_RTOS__
+#include <st_things/st_things_types.h>
+#else
+#include "st_things_types.h"
+#endif // __ST_THINGS_RTOS__
+#include "octypes.h"
+
+st_things_representation_s* create_representation_inst(void);
+
+st_things_representation_s* create_representation_inst_internal(OCRepPayload *payload);
+
+void destroy_representation_inst(st_things_representation_s *rep);
+
+void destroy_representation_inst_internal(st_things_representation_s *rep, bool destroy_payload);
+
+#endif // __ST_THINGS_REPRESENTATION_H__
--- /dev/null
+/* ****************************************************************
+ *
+ * Copyright 2017 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 "st_things_request_handler.h"
+#include "st_things_request_handler_collection.h"
+#include "st_things_representation.h"
+#include "st_things_util.h"
+#include "st_things_logger.h"
+
+#include "things_api.h"
+#include "octypes.h"
+#include "ocpayload.h"
+
+#define BOOL_ID 0
+#define INT_ID 1
+#define DOUBLE_ID 2
+#define STRING_ID 3
+#define OBJECT_ID 4
+#define BYTE_ID 5
+#define INT_ARRAY_ID 6
+#define DOUBLE_ARRAY_ID 7
+#define STRING_ARRAY_ID 8
+#define OBJECT_ARRAY_ID 9
+
+#define IS_READABLE(var) (1 & var)
+#define IS_WRITABLE(var) (2 & var)
+
+#define PROPERTY_KEY_DELIMITER ';'
+#define KEY_VALUE_SEPARATOR '='
+
+static st_things_get_request_cb g_handle_get_req_cb = NULL;
+static st_things_set_request_cb g_handle_set_req_cb = NULL;
+
+bool get_query_value_internal(const char *query, const char *key, char **value, bool *found)
+{
+ RET_FALSE_IF_EXPR_IS_TRUE((NULL == query || strlen(query) < 1), "Invalid query.");
+ RET_FALSE_IF_EXPR_IS_TRUE((NULL == key || strlen(key) < 1), "Invalid key.");
+ RET_FALSE_IF_PARAM_IS_NULL(value);
+
+ *value = NULL;
+ if (NULL != found) {
+ *found = false;
+ }
+
+ int query_len = strlen(query);
+ int key_len = strlen(key);
+ char *p_buff = NULL, *p_origin = NULL;
+ char *p_ptr = NULL;
+
+ p_origin = p_buff = (char *)util_malloc(query_len + 1);
+ if (NULL == p_origin) {
+ ST_LOG(ST_ERROR, "Failed to allocate memory to get a specific value from query.");
+ return false;
+ }
+
+ memset(p_buff, 0, query_len + 1);
+ memcpy(p_buff, query, query_len);
+
+ p_ptr = strtok(p_buff, QUERY_DELIMITER);
+ if (NULL == p_ptr) {
+ ST_LOG(ST_ERROR, "Failed to tokenize the query.");
+ util_free(p_origin);
+ return false;
+ }
+
+ bool res = false;
+ while (p_ptr != NULL) {
+ if (strncmp(p_ptr, key, key_len) == 0) {
+ ST_LOG_V(ST_DEBUG, "Key(%s) exists in query parameter(%s).", key, query);
+ if (NULL != found) {
+ *found = true;
+ }
+
+ *value = util_clone_string(p_ptr + key_len + 1);
+ if (NULL == *value) {
+ ST_LOG(ST_ERROR, "Failed to clone the query value.");
+ util_free(p_origin);
+ } else {
+ res = true;
+ }
+ break;
+ }
+
+ p_ptr = strtok(NULL, QUERY_DELIMITER);
+ }
+
+ if (NULL == p_ptr) {
+ ST_LOG_V(ST_DEBUG, "Key(%s) doesn't exist in query(%s).", key, query);
+ }
+
+ util_free(p_origin);
+
+ return res;
+}
+
+bool get_query_value_for_get_req(struct _st_things_get_request_message *req_msg, const char *key, char **value)
+{
+ RET_FALSE_IF_PARAM_IS_NULL(req_msg);
+ return get_query_value_internal(req_msg->query, key, value, NULL);
+}
+
+bool get_query_value_for_post_req(struct _st_things_set_request_message *req_msg, const char *key, char **value)
+{
+ RET_FALSE_IF_PARAM_IS_NULL(req_msg);
+ return get_query_value_internal(req_msg->query, key, value, NULL);
+}
+
+bool is_property_key_exist(struct _st_things_get_request_message *req_msg, const char *key)
+{
+ RET_FALSE_IF_PARAM_IS_NULL(req_msg);
+ RET_FALSE_IF_PARAM_IS_NULL(req_msg->property_key);
+ RET_FALSE_IF_EXPR_IS_TRUE(strlen(req_msg->property_key) < 1, "Property key in request message is empty.");
+ RET_FALSE_IF_PARAM_IS_NULL(key);
+ RET_FALSE_IF_EXPR_IS_TRUE(strlen(key) < 1, "Key is empty.");
+
+ int key_len = strlen(key);
+ bool exist = false;
+ char *key_ptr = req_msg->property_key;
+ while (NULL != key_ptr && !exist) {
+ key_ptr = strstr(key_ptr, key);
+ if (NULL == key_ptr) {
+ break;
+ }
+ // The following logic ensures that the key is a complete key and not a substring of another key.
+ // Check whether a delimeter immediately follows the key.
+ if (PROPERTY_KEY_DELIMITER != key_ptr[key_len]) {
+ key_ptr += key_len;
+ continue;
+ }
+ // If key is not at the begining, then check whether there is a delimiter immediately before the key.
+ if (key_ptr != req_msg->property_key && PROPERTY_KEY_DELIMITER != key_ptr[-1]) {
+ key_ptr += key_len;
+ continue;
+ }
+
+ exist = true;
+ }
+
+ ST_LOG_V(ST_DEBUG, "Key(%s) exist?: %s.", key, exist ? "Yes" : "No");
+ return exist;
+}
+
+static bool get_resource_types(things_resource_s *rsrc, char ***res_types, int *count)
+{
+ RET_FALSE_IF_PARAM_IS_NULL(rsrc);
+ RET_FALSE_IF_PARAM_IS_NULL(res_types);
+ RET_FALSE_IF_PARAM_IS_NULL(count);
+
+ int rt_count = rsrc->things_get_num_of_res_types(rsrc);
+ ST_LOG_V(ST_DEBUG, "Resource(%s) has %d resource type(s).", rsrc->uri, rt_count);
+ RET_FALSE_IF_EXPR_IS_TRUE(rt_count < 1, "No resource types in resource.");
+
+ char **types = (char **)util_calloc(rt_count, sizeof(char *));
+ RET_FALSE_IF_NULL(types, "Failed to allocate memory for resource types.");
+
+ bool result = true;
+ const char *res_type;
+ for (int i = 0; i < rt_count; i++) {
+ res_type = rsrc->things_get_res_type(rsrc, i);
+ if (NULL == res_type || strlen(res_type) < 1) {
+ ST_LOG_V(ST_ERROR, "Resource type at index(%d) is invalid.", i);
+ util_free_str_array(types, i);
+ result = false;
+ break;
+ }
+
+ types[i] = util_clone_string(res_type);
+ if (NULL == types[i]) {
+ ST_LOG_V(ST_ERROR, "Failed to clone resource type(%s).", res_type);
+ util_free_str_array(types, i);
+ result = false;
+ break;
+ }
+ }
+
+ if (result) {
+ *count = rt_count;
+ *res_types = types;
+ }
+
+ return result;
+}
+
+static bool get_interface_types(things_resource_s *rsrc, char ***if_types, int *count)
+{
+ RET_FALSE_IF_PARAM_IS_NULL(rsrc);
+ RET_FALSE_IF_PARAM_IS_NULL(if_types);
+ RET_FALSE_IF_PARAM_IS_NULL(count);
+
+ int if_count = rsrc->things_get_num_of_inf_types(rsrc);
+ ST_LOG_V(ST_DEBUG, "Resource(%s) has %d interface type(s).", rsrc->uri, if_count);
+ RET_FALSE_IF_EXPR_IS_TRUE(if_count < 1, "No interface types in resource.");
+
+ char **types = (char **)util_calloc(if_count, sizeof(char *));
+ RET_VAL_IF_NULL(types, "Failed to allocate memory for inteface types.", false);
+
+ bool result = true;
+ const char *if_type = NULL;
+ for (int i = 0; i < if_count; i++) {
+ if_type = rsrc->things_get_inf_type(rsrc, i);
+ if (NULL == if_type || strlen(if_type) < 1) {
+ ST_LOG_V(ST_ERROR, "Interface type at index(%d) is invalid.", i);
+ util_free_str_array(types, i);
+ result = false;
+ break;
+ }
+
+ types[i] = util_clone_string(if_type);
+ if (NULL == types[i]) {
+ ST_LOG_V(ST_ERROR, "Failed to clone inteface type(%s).", if_type);
+ util_free_str_array(types, i);
+ result = false;
+ break;
+ }
+ }
+
+ if (result) {
+ *count = if_count;
+ *if_types = types;
+ }
+
+ return result;
+}
+
+ /*
+ * Adds the common properties of resource such as 'rt', 'if'.
+ * 'links' property will be added in the response payload for collection resources.
+ * If it fails for any reason, the resp_payload which is partially updated by this function will not be reset.
+ * The caller of this method will have to release the payload and return an error response to the client.
+ */
+bool add_common_props(things_resource_s *rsrc, bool collection, OCRepPayload *resp_payload)
+{
+ RET_FALSE_IF_PARAM_IS_NULL(rsrc);
+ RET_FALSE_IF_PARAM_IS_NULL(resp_payload);
+
+ // Set resource types.
+ int rt_count = 0;
+ char **res_types = NULL;
+ if (!get_resource_types(rsrc, &res_types, &rt_count)) {
+ ST_LOG_V(ST_ERROR, "Failed to get the resource types of the given resource(%s).", rsrc->uri);
+ return false;
+ }
+
+ for (int i = 0; i < rt_count; i++) {
+ if (!OCRepPayloadAddResourceTypeAsOwner(resp_payload, res_types[i])) {
+ ST_LOG(ST_ERROR, "Failed to add the resource type in the response payload.");
+ // Release memory allocated for resource types.
+ util_free_str_array(res_types, rt_count);
+ return false;
+ }
+ }
+
+ // Set interface types.
+ int if_count = 0;
+ char **if_types = NULL;
+ if (!get_interface_types(rsrc, &if_types, &if_count)) {
+ ST_LOG_V(ST_ERROR, "Failed to get the interface types of the given resource(%s).", rsrc->uri);
+ return false;
+ }
+
+ for (int i = 0; i < if_count; i++) {
+ if (!OCRepPayloadAddInterfaceAsOwner(resp_payload, if_types[i])) {
+ ST_LOG(ST_ERROR, "Failed to add the interface type in the response payload.");
+ // Release memory allocated for interface types.
+ util_free_str_array(if_types, if_count);
+ return false;
+ }
+ }
+
+ // Set "links"(only for collection).
+ if (collection) {
+ size_t count = 0;
+ OCRepPayload **links = NULL;
+ if (!form_collection_links(rsrc, &links, &count)) {
+ ST_LOG_V(ST_ERROR, "Failed to form links for the given collection resource(%s).", rsrc->uri);
+ return false;
+ }
+
+ ST_LOG(ST_DEBUG, "Formed links for collection.");
+ size_t dimensions[MAX_REP_ARRAY_DEPTH] = { count, 0, 0 };
+ bool result = OCRepPayloadSetPropObjectArrayAsOwner(resp_payload, OC_RSRVD_LINKS, links, dimensions);
+ if (!result) {
+ ST_LOG(ST_ERROR, "Failed to add the links in the response payload.");
+ for (size_t i = 0; i < count && NULL != links[i]; i++) {
+ OCRepPayloadDestroy(links[i]);
+ }
+ util_free(links);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// To get the properties of a resource based on either resource type or resource uri.
+static bool get_supported_properties(const char *res_type, const char *res_uri, int *count, things_attribute_info_s ***properties, bool *destroy_props)
+{
+ RET_FALSE_IF_PARAM_IS_NULL(count);
+ RET_FALSE_IF_PARAM_IS_NULL(properties);
+ RET_FALSE_IF_PARAM_IS_NULL(destroy_props);
+
+ *destroy_props = false;
+
+ // Get the properties based on resource type.
+ if (NULL != res_type && strlen(res_type) > 0) {
+ int res = things_get_attributes_by_resource_type(res_type, count, properties);
+ ST_LOG_V(ST_DEBUG, "Get attributes by resource type(%s): %s.", res_type, (1 == res) ? "Success" : "Failed");
+ return res ? true : false;
+ }
+ // Get the properties based on resource uri.
+ if (NULL != res_uri && strlen(res_uri) > 0) {
+ int type_count = 0;
+ char **res_types = NULL;
+ // 1. Get the resource types.
+ if (!things_get_resource_type(res_uri, &type_count, &res_types)) {
+ ST_LOG_V(ST_ERROR, "Failed to get the resource types based on resource uri(%s).", res_uri);
+ return false;
+ }
+
+ if (type_count < 1 || NULL == res_types) {
+ ST_LOG_V(ST_ERROR, "No resource types for the given resource(%s).", res_uri);
+ return false;
+ }
+
+ ST_LOG_V(ST_DEBUG, "Resource(%s) has %d resource type(s).", res_uri, type_count);
+
+ // 2. Get the properties for each resource type.
+ int *prop_count = NULL;
+ things_attribute_info_s ***props = NULL;
+ props = (things_attribute_info_s ***) util_calloc(type_count, sizeof(things_attribute_info_s **));
+ if (NULL == props) {
+ ST_LOG(ST_ERROR, "Failed to allocate memory for resource properties.");
+ return false;
+ }
+ prop_count = (int *)util_calloc(type_count, sizeof(int));
+ if (NULL == props) {
+ ST_LOG(ST_ERROR, "Failed to allocate memory for resource properties.");
+ util_free(props);
+ return false;
+ }
+
+ for (int index = 0; index < type_count; index++) {
+ if (!things_get_attributes_by_resource_type(res_types[index], &prop_count[index], &props[index])) {
+ ST_LOG_V(ST_ERROR, "Failed to get the properties of resource type (%s).", res_types[index]);
+ util_free(prop_count);
+ util_free(props);
+ *count = 0;
+ *properties = NULL;
+ return false;
+ }
+ ST_LOG_V(ST_DEBUG, "Number of properties of resource type(%s): %d.", res_types[index], prop_count[index]);
+ *count += prop_count[index];
+ }
+
+ ST_LOG_V(ST_DEBUG, "Total number of properties: %d.", *count);
+
+ *properties = (things_attribute_info_s **) util_calloc(*count, sizeof(things_attribute_info_s *));
+ if (NULL == *properties) {
+ ST_LOG(ST_ERROR, "Failed to allocate memory for resource properties.");
+ util_free(prop_count);
+ util_free(props);
+ *count = 0;
+ return false;
+ }
+
+ int cur_index = 0;
+ for (int index = 0; index < type_count; index++) {
+ if (NULL == props[index]) {
+ ST_LOG_V(ST_ERROR, "Resource type(%s) doesn't have any properties.", res_types[index]);
+ util_free(prop_count);
+ util_free(props);
+ *count = 0;
+ return false;
+ }
+
+ for (int sub_index = 0; sub_index < prop_count[index]; sub_index++) {
+ things_attribute_info_s *prop = *(props[index] + sub_index);
+ if (NULL == prop) {
+ ST_LOG(ST_ERROR, "NULL Property.");
+ util_free(prop_count);
+ util_free(props);
+ *count = 0;
+ return false;
+ }
+ // If this prop is already added, then ignore it and decrement the total count by 1.
+ bool exist = false;
+ for (int i = 0; i < cur_index; i++) {
+ if (0 == strncmp(((*properties)[i])->key, prop->key, strlen(prop->key))) {
+ ST_LOG_V(ST_DEBUG, "Property(%s) is already added in the request message.", prop->key);
+ exist = true;
+ break;
+ }
+ }
+ if (exist) {
+ (*count)--;
+ } else {
+ (*properties)[cur_index++] = prop;
+ }
+ }
+ }
+
+ *destroy_props = true;
+ util_free(prop_count);
+ util_free(props);
+ } else {
+ ST_LOG(ST_ERROR, "Resource type and URI are invalid.");
+ return false;
+ }
+
+ return true;
+}
+
+static void remove_query_parameter(char *query, char *key)
+{
+ RET_IF_EXPR_IS_TRUE((NULL == query || strlen(query) < 1), "Invalid parameter: query.");
+ RET_IF_EXPR_IS_TRUE((NULL == key || strlen(key) < 1), "Invalid parameter: key.");
+
+ int key_len = strlen(key);
+ char *pos1 = strstr(query, key);
+ if (NULL == pos1 || (KEY_VALUE_SEPARATOR != pos1[key_len])) { // Key should exist and its next char should be '='.
+ ST_LOG(ST_ERROR, "Key doesn't exist in query.");
+ return;
+ }
+
+ char *pos2 = strstr(pos1, QUERY_DELIMITER);
+ if (NULL != pos2) {
+ pos2++; // Increment the pointer to make it point the first character in the next key
+ while ((*pos1++ = *pos2++)) ;
+ } else{ // Given key is the last in the query.
+ if (pos1 != query) {
+ pos1--; // Decrement the pointer to remove the leading query delimiter
+ }
+
+ *pos1 = '\0';
+ }
+}
+
+static void add_property_key_in_get_req_msg(st_things_get_request_message_s *req_msg, char *prop_key)
+{
+ RET_IF_PARAM_IS_NULL(req_msg);
+ RET_IF_PARAM_IS_NULL(req_msg->property_key);
+ RET_IF_PARAM_IS_NULL(prop_key);
+
+ strncat(req_msg->property_key, prop_key, strlen(prop_key));
+ int prop_len = strlen(req_msg->property_key);
+ req_msg->property_key[prop_len] = PROPERTY_KEY_DELIMITER;
+ req_msg->property_key[prop_len + 1] = '\0';
+}
+
+static bool add_property_in_post_req_msg(st_things_set_request_message_s *req_msg, OCRepPayload *req_payload, things_attribute_info_s *prop)
+{
+ RET_FALSE_IF_PARAM_IS_NULL(req_msg);
+ RET_FALSE_IF_PARAM_IS_NULL(req_msg->rep);
+ RET_FALSE_IF_PARAM_IS_NULL(req_msg->rep->payload);
+ RET_FALSE_IF_PARAM_IS_NULL(req_payload);
+ RET_FALSE_IF_PARAM_IS_NULL(prop);
+
+ OCRepPayload *resp_payload = req_msg->rep->payload;
+
+ ST_LOG_V(ST_DEBUG, "Property Key is %s", prop->key);
+ ST_LOG_V(ST_DEBUG, "Property type is %d", prop->type);
+
+ // Based on the property type, call appropriate methods to copy
+ // the property from request payload to request representation.
+ bool result = false;
+ switch (prop->type) {
+ case BOOL_ID:
+ {
+ bool value = false;
+ if (OCRepPayloadGetPropBool(req_payload, prop->key, &value)) {
+ result = OCRepPayloadSetPropBool(resp_payload, prop->key, value);
+ if (!result) {
+ ST_LOG_V(ST_ERROR, "Failed to set the boolean value of '%s' in request message.", prop->key);
+ }
+ } else {
+ ST_LOG_V(ST_ERROR, "Failed to get the boolean value of '%s' for request message.", prop->key);
+ }
+ }
+ break;
+ case INT_ID:
+ {
+ int64_t value = 0;
+ if (OCRepPayloadGetPropInt(req_payload, prop->key, &value)) {
+ result = OCRepPayloadSetPropInt(resp_payload, prop->key, value);
+ if (!result) {
+ ST_LOG_V(ST_ERROR, "Failed to set the integer value of '%s' in request message", prop->key);
+ }
+ } else {
+ ST_LOG_V(ST_ERROR, "Failed to get the integer value of '%s' for request message", prop->key);
+ }
+ }
+ break;
+ case DOUBLE_ID:
+ {
+ double value = 0.0;
+ if (OCRepPayloadGetPropDouble(req_payload, prop->key, &value)) {
+ result = OCRepPayloadSetPropDouble(resp_payload, prop->key, value);
+ if (!result) {
+ ST_LOG_V(ST_ERROR, "Failed to set the double value of '%s' in request message", prop->key);
+ }
+ } else {
+ ST_LOG_V(ST_ERROR, "Failed to get the double value of '%s' for request message", prop->key);
+ }
+ }
+ break;
+ case STRING_ID:
+ {
+ char *value = NULL;
+ if (OCRepPayloadGetPropString(req_payload, prop->key, &value)) {
+ result = OCRepPayloadSetPropStringAsOwner(resp_payload, prop->key, value);
+ if (!result) {
+ ST_LOG_V(ST_ERROR, "Failed to set the string value of '%s' in request message", prop->key);
+ util_free(value);
+ }
+ } else {
+ ST_LOG_V(ST_ERROR, "Failed to get the string value of '%s' for request message", prop->key);
+ }
+ }
+ break;
+ case OBJECT_ID:
+ {
+ OCRepPayload *value = NULL;
+ if (OCRepPayloadGetPropObject(req_payload, prop->key, &value)) {
+ result = OCRepPayloadSetPropObjectAsOwner(resp_payload, prop->key, value);
+ if (!result) {
+ ST_LOG_V(ST_ERROR, "Failed to set the object value of '%s' in request message", prop->key);
+ OCRepPayloadDestroy(value);
+ }
+ } else {
+ ST_LOG_V(ST_ERROR, "Failed to get the object value of '%s' for request message", prop->key);
+ }
+ }
+ break;
+ case BYTE_ID:
+ {
+ OCByteString *byte_value = (OCByteString *) util_calloc(1, sizeof(OCByteString));
+ if (NULL == byte_value) {
+ ST_LOG_V(ST_ERROR, "Failed to allocate memory for byte string value of '%s' in request message", prop->key);
+ break;
+ }
+
+ if (OCRepPayloadGetPropByteString(req_payload, prop->key, byte_value)) {
+ result = OCRepPayloadSetPropByteStringAsOwner(resp_payload, prop->key, byte_value);
+ if (!result) {
+ ST_LOG_V(ST_ERROR, "Failed to set the byte string value of '%s' in request message", prop->key);
+ util_free(byte_value->bytes);
+ }
+ } else {
+ ST_LOG_V(ST_ERROR, "Failed to get the byte string value of '%s' for request message", prop->key);
+ }
+
+ if (!result) {
+ util_free(byte_value);
+ }
+ }
+ break;
+ case INT_ARRAY_ID:
+ {
+ int64_t *value = NULL;
+ size_t dimensions[MAX_REP_ARRAY_DEPTH] = { 0 };
+ if (OCRepPayloadGetIntArray(req_payload, prop->key, &value, dimensions)) {
+ result = OCRepPayloadSetIntArrayAsOwner(resp_payload, prop->key, value, dimensions);
+ if (!result) {
+ ST_LOG_V(ST_ERROR, "Failed to set the integer array value of '%s' in request message", prop->key);
+ util_free(value);
+ }
+ } else {
+ ST_LOG_V(ST_ERROR, "Failed to get the integer array value of '%s' for request message", prop->key);
+ }
+ }
+ break;
+ case DOUBLE_ARRAY_ID:
+ {
+ double *value = NULL;
+ size_t dimensions[MAX_REP_ARRAY_DEPTH] = { 0 };
+ if (OCRepPayloadGetDoubleArray(req_payload, prop->key, &value, dimensions)) {
+ result = OCRepPayloadSetDoubleArrayAsOwner(resp_payload, prop->key, value, dimensions);
+ if (!result) {
+ ST_LOG_V(ST_ERROR, "Failed to set the double array value of '%s' in request message", prop->key);
+ util_free(value);
+ }
+ } else {
+ ST_LOG_V(ST_ERROR, "Failed to get the double array value of '%s' for request message", prop->key);
+ }
+ }
+ break;
+ case STRING_ARRAY_ID:
+ {
+ char **value = NULL;
+ size_t dimensions[MAX_REP_ARRAY_DEPTH] = { 0 };
+ if (OCRepPayloadGetStringArray(req_payload, prop->key, &value, dimensions)) {
+ result = OCRepPayloadSetStringArrayAsOwner(resp_payload, prop->key, value, dimensions);
+ if (!result) {
+ ST_LOG_V(ST_ERROR, "Failed to set the string array value of '%s' in request message", prop->key);
+ size_t len = calcDimTotal(dimensions);
+ util_free_str_array(value, len);
+ }
+ } else {
+ ST_LOG_V(ST_ERROR, "Failed to get the string array value of '%s' for request message", prop->key);
+ }
+ }
+ break;
+ case OBJECT_ARRAY_ID:
+ {
+ OCRepPayload **value = NULL;
+ size_t dimensions[MAX_REP_ARRAY_DEPTH] = { 0 };
+ if (OCRepPayloadGetPropObjectArray(req_payload, prop->key, &value, dimensions)) {
+ result = OCRepPayloadSetPropObjectArrayAsOwner(resp_payload, prop->key, value, dimensions);
+ if (!result) {
+ ST_LOG_V(ST_ERROR, "Failed to set the object array value of '%s' in request message", prop->key);
+ size_t len = calcDimTotal(dimensions);
+ for (size_t index = 0; index < len; index++) {
+ OCRepPayloadDestroy(value[index]);
+ }
+ util_free(value);
+ }
+ } else {
+ ST_LOG_V(ST_ERROR, "Failed to get the object array value of '%s' for request message", prop->key);
+ }
+ }
+ break;
+ default:
+ ST_LOG_V(ST_ERROR, "Invalid property type (%d).", prop->type);
+ break;
+ }
+
+ return result;
+}
+
+static void destroy_req_msg_inst_for_get(st_things_get_request_message_s *req_msg)
+{
+ RET_IF_PARAM_IS_NULL(req_msg);
+
+ util_free(req_msg->resource_uri);
+ util_free(req_msg->query);
+ util_free(req_msg->property_key);
+
+ req_msg->query = NULL;
+ req_msg->resource_uri = NULL;
+ req_msg->property_key = NULL;
+ req_msg->get_query_value = NULL;
+ req_msg->has_property_key = NULL;
+
+ util_free(req_msg);
+}
+
+static void destroy_req_msg_inst_for_post(st_things_set_request_message_s *req_msg, bool destroy_payload)
+{
+ RET_IF_PARAM_IS_NULL(req_msg);
+
+ util_free(req_msg->resource_uri);
+ util_free(req_msg->query);
+
+ if (NULL != req_msg->rep) {
+ destroy_representation_inst_internal(req_msg->rep, destroy_payload);
+ }
+
+ req_msg->resource_uri = NULL;
+ req_msg->query = NULL;
+ req_msg->rep = NULL;
+ req_msg->get_query_value = NULL;
+
+ util_free(req_msg);
+}
+
+static st_things_get_request_message_s *create_req_msg_inst_for_get(const char *res_uri, const char *query)
+{
+ st_things_get_request_message_s *req_msg = (st_things_get_request_message_s *) util_malloc(sizeof(st_things_get_request_message_s));
+ RET_VAL_IF_NULL(req_msg, "Failed to allocate memory for GET request message.", NULL);
+
+ req_msg->resource_uri = util_clone_string(res_uri);
+ RET_VAL_IF_NULL(req_msg->resource_uri, "Failed to clone the resource uri.", NULL);
+
+ if (NULL != query && strlen(query) > 1) {
+ req_msg->query = util_clone_string(query);
+ } else {
+ req_msg->query = NULL;
+ }
+ req_msg->property_key = NULL;
+ req_msg->get_query_value = &get_query_value_for_get_req;
+ req_msg->has_property_key = &is_property_key_exist;
+ return req_msg;
+}
+
+static st_things_set_request_message_s *create_req_msg_inst_for_post(const char *res_uri, const char *query, OCRepPayload *req_payload)
+{
+ st_things_set_request_message_s *req_msg = (st_things_set_request_message_s *) util_malloc(sizeof(st_things_set_request_message_s));
+ RET_VAL_IF_NULL(req_msg, "Failed to allocate memory for SET request message.", NULL);
+
+ req_msg->resource_uri = util_clone_string(res_uri);
+ RET_VAL_IF_NULL(req_msg->resource_uri, "Failed to clone the resource uri.", NULL);
+
+ if (NULL != query && strlen(query) > 1) {
+ req_msg->query = util_clone_string(query);
+ } else {
+ req_msg->query = NULL;
+ }
+
+ req_msg->rep = create_representation_inst_internal(req_payload);
+ if (NULL == req_msg->rep) {
+ ST_LOG(ST_ERROR, "Failed to create representation for SET request message.");
+ destroy_req_msg_inst_for_post(req_msg, false);
+ return NULL;
+ }
+
+ req_msg->get_query_value = &get_query_value_for_post_req;
+ return req_msg;
+}
+
+ /*
+ * Helper method to get the response from application for GET requests.
+ * The 'resp_payload' parameter will be used to get the response.
+ * Common properties of the resource such as rt, if and links will not be set by this method.
+ */
+bool handle_get_req_helper(const char *res_uri, const char *query, OCRepPayload *resp_payload)
+{
+ RET_FALSE_IF_PARAM_IS_NULL(resp_payload);
+ RET_FALSE_IF_NULL(g_handle_get_req_cb, "Request callback for GET is NULL.");
+
+ // Setup the request message.
+ st_things_get_request_message_s *req_msg = create_req_msg_inst_for_get(res_uri, query);
+ RET_FALSE_IF_NULL(req_msg, "Failed to create request message for GET.");
+
+ /* Based on the resource type of the request (specified in the query parameters like rt=oic.r.switch.binary) and
+ interface type in the query parameter, add proper set of property keys in the request message.
+ Application's response representation should include
+ only those properties which are present in the request message. */
+ char *res_type = NULL;
+ int count = 0;
+ bool destroy_props = false;
+ struct things_attribute_info_s **properties = NULL;
+
+ // Get resource type from query parameter
+ if (NULL != query && strlen(query) > 0) {
+ bool found = false;
+ bool result = get_query_value_internal(query, OC_RSRVD_RESOURCE_TYPE, &res_type, &found);
+ if (found && !result) { // If query is present but API returns false.
+ ST_LOG_V(ST_ERROR, "Failed to get the resource type from query parameter(%s).", query);
+ destroy_req_msg_inst_for_get(req_msg);
+ return false;
+ }
+ }
+ // Get supported set of properties based on resource type query parameter.
+ // If resource type is not available, then get the properties based on resource uri.
+ bool res = get_supported_properties(res_type, res_uri, &count, &properties, &destroy_props);
+ if (!res) {
+ ST_LOG(ST_ERROR, "Failed to get the resource properties based on its type or uri.");
+ destroy_req_msg_inst_for_get(req_msg);
+ util_free(res_type);
+ return false;
+ }
+ // Calculate the length of all property keys
+ int total_length_of_prop_keys = 0;
+ for (int index = 0; index < count; index++) {
+ if (NULL != properties[index]) {
+ total_length_of_prop_keys += strlen(properties[index]->key);
+ }
+ }
+ total_length_of_prop_keys += count; // For delimiter
+ total_length_of_prop_keys += 1; // For null character
+
+ // Allocate memory for holding property keys with delimiters
+ req_msg->property_key = (char *)util_calloc(total_length_of_prop_keys, sizeof(char));
+ if (!req_msg->property_key) {
+ ST_LOG(ST_ERROR, "Failed to allocate memory for property key in GET request message.");
+ if (destroy_props) {
+ util_free(properties);
+ }
+ destroy_req_msg_inst_for_get(req_msg);
+ util_free(res_type);
+ return false;
+ }
+ // Get interface type from query parameter.
+ char *if_type = NULL;
+ if (NULL != query && strlen(query) > 0) {
+ bool found = false;
+ bool result = get_query_value_internal(query, OC_RSRVD_INTERFACE, &if_type, &found);
+ if (found && !result) { // If query is present but API returns false.
+ ST_LOG_V(ST_ERROR, "Failed to get the interface type from query parameter(%s).", query);
+ if (destroy_props) {
+ util_free(properties);
+ }
+ destroy_req_msg_inst_for_get(req_msg);
+ util_free(res_type);
+ return false;
+ }
+ }
+
+ bool handled = false;
+ if (NULL != if_type && strlen(if_type) > 0) {
+ ST_LOG_V(ST_DEBUG, "Interface type is (%s).", if_type);
+ if (0 == strncmp(if_type, OC_RSRVD_INTERFACE_READ, strlen(OC_RSRVD_INTERFACE_READ))) {
+ // Add all the attributes which are readable.
+ for (int index = 0; index < count; index++) {
+ if (NULL != properties[index] && IS_READABLE(properties[index]->rw)) {
+ add_property_key_in_get_req_msg(req_msg, properties[index]->key);
+ }
+ }
+ handled = true;
+ } else if (0 == strncmp(if_type, ST_THINGS_RSRVD_INTERFACE_READWRITE, strlen(ST_THINGS_RSRVD_INTERFACE_READWRITE))) {
+ // Add all the attributes which are readable and writable.
+ for (int index = 0; index < count; index++) {
+ if (NULL != properties[index] && IS_READABLE(properties[index]->rw) && IS_WRITABLE(properties[index]->rw)) {
+ add_property_key_in_get_req_msg(req_msg, properties[index]->key);
+ }
+ }
+ handled = true;
+ }
+ }
+
+ if (!handled) { // For all other cases, add all the property keys.
+ for (int index = 0; index < count; index++) {
+ if (NULL != properties[index]) {
+ add_property_key_in_get_req_msg(req_msg, properties[index]->key);
+ }
+ }
+ }
+ // Remove 'rt' and 'if' from query parameters
+ if (NULL != query && strlen(query) > 0) {
+ remove_query_parameter(req_msg->query, OC_RSRVD_RESOURCE_TYPE);
+ remove_query_parameter(req_msg->query, OC_RSRVD_INTERFACE);
+ }
+ // Setup the response representation for application. This representation will be handed over to the application.
+ st_things_representation_s *things_resp_rep = create_representation_inst_internal(resp_payload);
+ if (NULL != things_resp_rep) {
+ res = g_handle_get_req_cb(req_msg, things_resp_rep);
+ ST_LOG_V(ST_DEBUG, "The result of application's callback : %s.", res ? "true" : "false");
+ destroy_representation_inst_internal(things_resp_rep, false);
+ } else {
+ ST_LOG(ST_ERROR, "Failed to create response representation.");
+ res = false;
+ }
+
+ destroy_req_msg_inst_for_get(req_msg);
+ if (destroy_props) {
+ util_free(properties);
+ }
+ util_free(res_type);
+ util_free(if_type);
+
+ return res;
+}
+
+static int handle_get_req_on_single_rsrc(things_resource_s *single_rsrc)
+{
+ RET_VAL_IF_PARAM_IS_NULL(single_rsrc, 0);
+
+ // Setup the response representation. This representation will be handed over to the underlying stack.
+ things_representation_s *resp_rep = things_create_representation_inst(NULL);
+ RET_VAL_IF_NULL(resp_rep, "Failed to create response representation.", 0);
+
+ bool result = OCRepPayloadSetUri(resp_rep->payload, single_rsrc->uri);
+ if (!result) {
+ ST_LOG_V(ST_ERROR, "Failed to set the resource uri(%s) in response payload.", single_rsrc->uri);
+ things_release_representation_inst(resp_rep);
+ return 0;
+ }
+
+ ST_LOG_V(ST_DEBUG, "Resource uri(%s) is set in the response payload.", single_rsrc->uri);
+
+ // Set the common properties in the payload (Only for baseline interface).
+ char *if_type = NULL;
+ if (NULL != single_rsrc->query && strlen(single_rsrc->query) > 0) {
+ bool found = false;
+ bool result = get_query_value_internal(single_rsrc->query, OC_RSRVD_INTERFACE, &if_type, &found);
+ if (found && !result) { // If query is present but API returns false.
+ ST_LOG_V(ST_ERROR, "Failed to get the interface type from query parameter(%s).", single_rsrc->query);
+ things_release_representation_inst(resp_rep);
+ return 0;
+ }
+ }
+
+ if (NULL == if_type || strlen(if_type) < 1 || !strncmp(if_type, OC_RSRVD_INTERFACE_DEFAULT, strlen(OC_RSRVD_INTERFACE_DEFAULT))) {
+ if (!add_common_props(single_rsrc, false, resp_rep->payload)) {
+ ST_LOG(ST_ERROR, "Failed to add the common properties in response payload.");
+ things_release_representation_inst(resp_rep);
+ util_free(if_type);
+ return 0;
+ }
+ ST_LOG(ST_DEBUG, "Added common properties in response payload.");
+ }
+ // Get the resource's properties from the application.
+ result = handle_get_req_helper(single_rsrc->uri, single_rsrc->query, resp_rep->payload);
+ if (!result) {
+ things_release_representation_inst(resp_rep);
+ util_free(if_type);
+ return 0;
+ }
+ // Set the response representation in the resource.
+ single_rsrc->things_set_representation(single_rsrc, resp_rep);
+
+ util_free(if_type);
+ return 1;
+}
+
+ /*
+ * Helper method to get the response from application for POST requests.
+ * The 'resp_payload' parameter will be used to get the response.
+ * Common properties of the resource such as rt, if and links will not be set by this method.
+ */
+bool handle_post_req_helper(const char *res_uri, const char *query, OCRepPayload *req_payload, OCRepPayload *resp_payload)
+{
+ RET_FALSE_IF_PARAM_IS_NULL(req_payload);
+ RET_FALSE_IF_PARAM_IS_NULL(resp_payload);
+ RET_FALSE_IF_NULL(g_handle_set_req_cb, "Request callback for SET is NULL.");
+
+ // Setup the response representation for application. This representation will be handed over to the application.
+ st_things_representation_s *things_resp_rep = create_representation_inst_internal(resp_payload);
+ RET_FALSE_IF_NULL(things_resp_rep, "Failed to create response representation.");
+
+ // Setup the request message.
+ st_things_set_request_message_s *req_msg = create_req_msg_inst_for_post(res_uri, query, NULL);
+ if (NULL == req_msg) {
+ ST_LOG(ST_ERROR, "Failed to create the request message for SET.");
+ destroy_representation_inst_internal(things_resp_rep, false);
+ return false;
+ }
+
+ /* Based on the resource type of the request (specified in the query parameters like rt=oic.r.switch.binary) and
+ interface type in the query parameter, add proper set of properties in the request representation.
+ Application's response representation should include
+ only the properties present in the request representation. */
+
+ char *res_type = NULL;
+ int count = 0;
+ bool destroy_props = false;
+ struct things_attribute_info_s **properties = NULL;
+
+ // Get resource type from query parameter
+ if (NULL != query && strlen(query) > 0) {
+ bool found = false;
+ bool result = get_query_value_internal(query, OC_RSRVD_RESOURCE_TYPE, &res_type, &found);
+ if (found && !result) { // If query is present but API returns false.
+ ST_LOG_V(ST_ERROR, "Failed to get the resource type from query parameter(%s).", query);
+ destroy_representation_inst_internal(things_resp_rep, false);
+ destroy_req_msg_inst_for_post(req_msg, true);
+ return false;
+ }
+ }
+ // Get necessary set of properties.
+ bool res = get_supported_properties(res_type, res_uri, &count, &properties, &destroy_props);
+ if (!res) {
+ ST_LOG(ST_ERROR, "Failed to get the resource properties based on its type or uri.");
+ destroy_representation_inst_internal(things_resp_rep, false);
+ destroy_req_msg_inst_for_post(req_msg, true);
+ util_free(res_type);
+ return false;
+ }
+
+ ST_LOG_V(ST_DEBUG, "Total number of supported properties: %d.", count);
+
+ res = true;
+ // Check whether the request has all mandatory properties.
+ for (int index = 0; index < count; index++) {
+ if (NULL == properties[index]) {
+ ST_LOG_V(ST_ERROR, "Property at index(%d) is NULL.", index);
+ res = false;
+ break;
+ }
+
+ if (properties[index]->mandatory) {
+ if (OCRepPayloadIsNull(req_payload, properties[index]->key)) {
+ ST_LOG_V(ST_ERROR, "Mandatory property (%s) is not present in the request.", properties[index]->key);
+ res = false;
+ break;
+ }
+ }
+ }
+
+ if (!res) {
+ if (destroy_props) {
+ util_free(properties);
+ }
+ destroy_representation_inst_internal(things_resp_rep, false);
+ destroy_req_msg_inst_for_post(req_msg, true);
+ util_free(res_type);
+ return false;
+ }
+
+ for (int index = 0; index < count; index++) {
+ if (NULL != properties[index] && IS_WRITABLE(properties[index]->rw)) {
+ res = add_property_in_post_req_msg(req_msg, req_payload, properties[index]);
+ if (!res) {
+ break;
+ }
+ }
+ }
+
+ if (res) {
+ // Remove 'rt' and 'if' from query parameters.
+ remove_query_parameter(req_msg->query, OC_RSRVD_RESOURCE_TYPE);
+ remove_query_parameter(req_msg->query, OC_RSRVD_INTERFACE);
+
+ res = g_handle_set_req_cb(req_msg, things_resp_rep);
+ ST_LOG_V(ST_DEBUG, "The result of application's callback : %s", res ? "true" : "false");
+ } else {
+ ST_LOG(ST_ERROR, "Failed to add properties in request message.");
+ }
+
+ if (destroy_props) {
+ util_free(properties);
+ }
+ destroy_req_msg_inst_for_post(req_msg, true);
+ destroy_representation_inst_internal(things_resp_rep, false);
+ util_free(res_type);
+ return true;
+}
+
+static int handle_post_req_on_single_rsrc(things_resource_s *single_rsrc)
+{
+ RET_VAL_IF_PARAM_IS_NULL(single_rsrc, 0);
+
+ // Retrieve the request representation. This representation will hold all the input properties of post request.
+ // Payload in this representation will be used to form the request message which will be given to the application.
+ struct things_representation_s *req_rep = NULL;
+ bool rep_exist = single_rsrc->things_get_representation(single_rsrc, &req_rep);
+ if (!rep_exist || NULL == req_rep || NULL == req_rep->payload) {
+ ST_LOG(ST_ERROR, "Empty payload in POST request.");
+ return 0; // TODO: When a post request comes with empty payload, how do we handle?
+ }
+ // Setup the response representation. This representation will be handed over to the underlying stack.
+ // The payload which is passed as a parameter will be updated with the common properties.
+ things_representation_s *resp_rep = things_create_representation_inst(NULL);
+ RET_VAL_IF_NULL(resp_rep, "Failed to create response representation.", 0);
+
+ if (!OCRepPayloadSetUri(resp_rep->payload, single_rsrc->uri)) {
+ ST_LOG_V(ST_ERROR, "Failed to set the resource uri(%s) in response payload.", single_rsrc->uri);
+ things_release_representation_inst(resp_rep);
+ return 0;
+ }
+
+ ST_LOG_V(ST_DEBUG, "Resource uri(%s) is set in the response payload.", single_rsrc->uri);
+
+ // Get interface type from query parameter
+ char *if_type = NULL;
+ if (NULL != single_rsrc->query && strlen(single_rsrc->query) > 0) {
+ bool found = false;
+ bool result = get_query_value_internal(single_rsrc->query, OC_RSRVD_INTERFACE, &if_type, &found);
+ if (found && !result) { // If query is present but API returns false.
+ ST_LOG_V(ST_ERROR, "Failed to get the interface type from query parameter(%s).", single_rsrc->query);
+ things_release_representation_inst(resp_rep);
+ return 0;
+ }
+ }
+ // Set the common properties in the payload (Only for baseline interface).
+ // The payload which is passed as a parameter will be updated with the common properties.
+ if (NULL == if_type || !strncmp(if_type, OC_RSRVD_INTERFACE_DEFAULT, strlen(OC_RSRVD_INTERFACE_DEFAULT))) {
+ if (!add_common_props(single_rsrc, false, resp_rep->payload)) {
+ ST_LOG(ST_ERROR, "Failed to add the common properties in response payload.");
+ things_release_representation_inst(resp_rep);
+ util_free(if_type);
+ return 0;
+ }
+ ST_LOG(ST_DEBUG, "Added common properties in response payload.");
+ }
+ // Give the request properties to application and get the response back.
+ bool res = handle_post_req_helper(single_rsrc->uri, single_rsrc->query, req_rep->payload, resp_rep->payload);
+ if (res) {
+ // Set the response representation in the resource.
+ single_rsrc->things_set_representation(single_rsrc, resp_rep);
+ } else {
+ things_release_representation_inst(resp_rep);
+ }
+ util_free(if_type);
+ return res ? 1 : 0;
+}
+
+int handle_get_request_cb(struct things_resource_s *resource)
+{
+ ST_LOG(ST_DEBUG, "Received a GET request callback");
+
+ RET_VAL_IF_PARAM_IS_NULL(resource, 0);
+ RET_VAL_IF_NULL(g_handle_get_req_cb, "Request callback for GET is NULL.", 0);
+ RET_VAL_IF_EXPR_IS_TRUE((NULL == resource->uri || strlen(resource->uri) < 1), "Resource URI is invalid", 0);
+
+ int result = 0;
+ bool collection = things_is_collection_resource(resource->uri);
+
+ ST_LOG_V(ST_DEBUG, "Resource URI : %s (%s resource)", resource->uri, collection ? "collection" : "single");
+ ST_LOG_V(ST_DEBUG, "Query Parameter: %s", resource->query);
+
+ if (collection) {
+ result = handle_get_req_on_collection_rsrc(resource);
+ } else {
+ result = handle_get_req_on_single_rsrc(resource);
+ }
+
+ if (result) {
+ ST_LOG_V(ST_DEBUG, "Handled GET request for %s resource successfully.", collection ? "collection" : "single");
+ } else {
+ ST_LOG_V(ST_DEBUG, "Failed to handle the GET request for %s resource.", collection ? "collection" : "single");
+ }
+
+ return result;
+}
+
+int handle_set_request_cb(struct things_resource_s *resource)
+{
+ ST_LOG(ST_DEBUG, "Received a SET request callback");
+
+ RET_VAL_IF_PARAM_IS_NULL(resource, 0);
+ RET_VAL_IF_NULL(g_handle_set_req_cb, "Request callback for SET is NULL", 0);
+ RET_VAL_IF_EXPR_IS_TRUE((NULL == resource->uri || strlen(resource->uri) < 1), "Resource URI is invalid", 0);
+
+ int result = 0;
+ bool collection = things_is_collection_resource(resource->uri);
+
+ ST_LOG_V(ST_DEBUG, "Resource URI : %s (%s resource)", resource->uri, collection ? "collection" : "single");
+ ST_LOG_V(ST_DEBUG, "Query Parameter: %s", resource->query);
+
+ if (collection) {
+ result = handle_post_req_on_collection_rsrc(resource);
+ } else {
+ result = handle_post_req_on_single_rsrc(resource);
+ }
+
+ if (result) {
+ ST_LOG_V(ST_DEBUG, "Handled SET request for %s resource successfully.", collection ? "collection" : "single");
+ } else {
+ ST_LOG_V(ST_DEBUG, "Failed to handle the SET request for %s resource.", collection ? "collection" : "single");
+ }
+
+ return result;
+}
+
+int register_request_handler_cb(st_things_get_request_cb get_cb, st_things_set_request_cb set_cb)
+{
+ if (NULL == get_cb) {
+ ST_LOG(ST_ERROR, "Request callback for GET is NULL.");
+ return ST_THINGS_ERROR_INVALID_PARAMETER;
+ }
+
+ if (NULL == set_cb) {
+ ST_LOG(ST_ERROR, "Request callback for SET is NULL.");
+ return ST_THINGS_ERROR_INVALID_PARAMETER;
+ }
+
+ g_handle_get_req_cb = get_cb;
+ g_handle_set_req_cb = set_cb;
+
+ return ST_THINGS_ERROR_NONE;
+}
--- /dev/null
+/* ****************************************************************
+ *
+ * Copyright 2017 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.
+ *
+ ******************************************************************/
+
+#ifndef __ST_THINGS_REQUEST_HANDLER_H__
+#define __ST_THINGS_REQUEST_HANDLER_H__
+
+#ifdef __ST_THINGS_RTOS__
+#include <st_things/st_things.h>
+#else
+#include "st_things.h"
+#endif // __ST_THINGS_RTOS__
+#include "things_resource.h"
+#include "octypes.h"
+
+#define ST_THINGS_RSRVD_INTERFACE_READWRITE "oic.if.rw"
+#define ST_THINGS_RSRVD_INTERFACE_SENSOR "oic.if.s"
+#define ST_THINGS_RSRVD_INTERFACE_ACTUATOR "oic.if.a"
+
+bool get_query_value_internal(const char *query, const char *key, char **value, bool *found);
+
+bool add_common_props(things_resource_s *rsrc, bool collection, OCRepPayload *resp_payload);
+
+bool handle_get_req_helper(const char *res_uri, const char *query, OCRepPayload *resp_payload);
+
+bool handle_post_req_helper(const char *res_uri, const char *query, OCRepPayload *req_payload, OCRepPayload *resp_payload);
+
+int handle_get_request_cb(struct things_resource_s *resource);
+
+int handle_set_request_cb(struct things_resource_s *resource);
+
+int register_request_handler_cb(st_things_get_request_cb get_cb, st_things_set_request_cb set_cb);
+
+#endif // __ST_THINGS_REQUEST_HANDLER_H__
--- /dev/null
+/* ****************************************************************
+ *
+ * Copyright 2017 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 "st_things_request_handler_collection.h"
+#include "st_things_request_handler.h"
+#include "st_things_logger.h"
+#include "st_things_util.h"
+
+#include "things_api.h"
+#include "ocpayload.h"
+
+static bool get_resource_types2(things_resource_info_s * rsrc, char ***res_types, int *count)
+{
+ RET_FALSE_IF_PARAM_IS_NULL(rsrc);
+ RET_FALSE_IF_PARAM_IS_NULL(res_types);
+ RET_FALSE_IF_PARAM_IS_NULL(count);
+
+ int rt_count = rsrc->rt_cnt;
+ ST_LOG_V(ST_DEBUG, "Resource(%s) has %d resource type(s).", rsrc->uri, rt_count);
+ RET_FALSE_IF_EXPR_IS_TRUE(rt_count < 1, "No resource types in resource.");
+
+ char **types = (char **)util_calloc(rt_count, sizeof(char *));
+ RET_VAL_IF_NULL(types, "Failed to allocate memory for resource types.", false);
+
+ bool result = true;
+ const char *res_type = NULL;
+ for (int i = 0; i < rt_count; i++) {
+ res_type = rsrc->resource_types[i];
+ if (NULL == res_type || strlen(res_type) < 1) {
+ ST_LOG_V(ST_ERROR, "Resource type at index(%d) is invalid.", i);
+ util_free_str_array(types, i);
+ result = false;
+ break;
+ }
+
+ types[i] = util_clone_string(res_type);
+ if (NULL == types[i]) {
+ ST_LOG_V(ST_ERROR, "Failed to clone resource type(%s).", res_type);
+ util_free_str_array(types, i);
+ result = false;
+ break;
+ }
+ }
+
+ if (result) {
+ *count = rt_count;
+ *res_types = types;
+ }
+
+ return result;
+}
+
+static bool get_interface_types2(things_resource_info_s *rsrc, char ***if_types, int *count)
+{
+ RET_FALSE_IF_PARAM_IS_NULL(rsrc);
+ RET_FALSE_IF_PARAM_IS_NULL(if_types);
+ RET_FALSE_IF_PARAM_IS_NULL(count);
+
+ int if_count = rsrc->if_cnt;
+ ST_LOG_V(ST_DEBUG, "Resource(%s) has %d interface type(s).", rsrc->uri, if_count);
+ RET_FALSE_IF_EXPR_IS_TRUE(if_count < 1, "No interface types in resource.");
+
+ char **types = (char **)util_calloc(if_count, sizeof(char *));
+ RET_VAL_IF_NULL(types, "Failed to allocate memory for inteface types.", false);
+
+ bool result = true;
+ const char *if_type = NULL;
+ for (int i = 0; i < if_count; i++) {
+ if_type = rsrc->interface_types[i];
+ if (NULL == if_type || strlen(if_type) < 1) {
+ ST_LOG_V(ST_ERROR, "Interface type at index(%d) is invalid.", i);
+ util_free_str_array(types, i);
+ result = false;
+ break;
+ }
+
+ types[i] = util_clone_string(if_type);
+ if (NULL == types[i]) {
+ ST_LOG_V(ST_ERROR, "Failed to clone inteface type(%s).", if_type);
+ util_free_str_array(types, i);
+ result = false;
+ break;
+ }
+ }
+
+ if (result) {
+ *count = if_count;
+ *if_types = types;
+ }
+
+ return result;
+}
+
+ /*
+ * Sample format of "links" representation:-
+ * [
+ * {
+ * "href": , // Resource URI
+ * "rt": [],
+ * "if": []
+ * },
+ * {
+ * "href": , // Resource URI
+ * "rt": [],
+ * "if": []
+ * }
+ * ]
+ */
+bool form_collection_links(things_resource_s *collection_rsrc, OCRepPayload ***links, size_t *count)
+{
+ RET_FALSE_IF_PARAM_IS_NULL(collection_rsrc);
+ RET_FALSE_IF_PARAM_IS_NULL(links);
+ RET_FALSE_IF_PARAM_IS_NULL(count);
+
+ int num_of_children = 0;
+ things_resource_info_s **children = NULL;
+ if (!things_get_child_resources(collection_rsrc->uri, &num_of_children, &children)) {
+ ST_LOG_V(ST_ERROR, "Failed to get child resources of collection resource(%s).", collection_rsrc->uri);
+ return false;
+ }
+
+ if (0 == num_of_children || NULL == children) {
+ ST_LOG_V(ST_ERROR, "Collection resource(%s) has no children.", collection_rsrc->uri);
+ return false;
+ }
+
+ ST_LOG_V(ST_DEBUG, "Collection resource(%s) has %d children.", collection_rsrc->uri, num_of_children);
+
+ // Allocate memory for the "links" in the response payload.
+ OCRepPayload **link_arr = (OCRepPayload **) util_calloc(num_of_children, sizeof(OCRepPayload *));
+ if (NULL == link_arr) {
+ ST_LOG(ST_ERROR, "Failed to allocate memory for links in collection.");
+ return false;
+ }
+
+ bool result = true;
+ int rt_count = 0;
+ int if_count = 0;
+ char **res_types = NULL;
+ char **if_types = NULL;
+ size_t dimensions[MAX_REP_ARRAY_DEPTH] = { 0, 0, 0 };
+ for (int index = 0; index < num_of_children; index++) {
+ if (NULL == children[index]->uri || strlen(children[index]->uri)) {
+ ST_LOG_V(ST_ERROR, "Resource URI of child resource at index(%d) is invalid.", index);
+ result = false;
+ break;
+ }
+
+ link_arr[index] = OCRepPayloadCreate();
+ if (NULL == link_arr[index]) {
+ ST_LOG(ST_ERROR, "Failed to allocate memory for links in collection.");
+ result = false;
+ break;
+ }
+ // Set the resource URI.
+ if (!OCRepPayloadSetPropString(link_arr[index], OC_RSRVD_HREF, children[index]->uri)) {
+ ST_LOG_V(ST_ERROR, "Failed to set the URI of child(%s) for links in collection(%s).", children[index]->uri, collection_rsrc->uri);
+ result = false;
+ break;
+ }
+
+ ST_LOG_V(ST_DEBUG, "Child resource uri(%s) is set in the response payload.", children[index]->uri);
+
+ // Set the resource types.
+ if (!get_resource_types2(children[index], &res_types, &rt_count)) {
+ ST_LOG_V(ST_ERROR, "Failed to get the resource types of a child(%s) for links in collection.", children[index]->uri);
+ result = false;
+ break;
+ }
+ dimensions[0] = rt_count;
+ result = OCRepPayloadSetStringArrayAsOwner(link_arr[index], OC_RSRVD_RESOURCE_TYPE, res_types, dimensions);
+ if (!result) {
+ ST_LOG_V(ST_ERROR, "Failed to set the resource types of child(%s) for links in collection.", children[index]->uri);
+ result = false;
+ break;
+ }
+ res_types = NULL;
+
+ ST_LOG_V(ST_DEBUG, "Resource types of child resource(%s) are set in the response payload.", children[index]->uri);
+
+ // Set the interface types.
+ if (!get_interface_types2(children[index], &if_types, &if_count)) {
+ ST_LOG_V(ST_ERROR, "Failed to get the interface types of child(%s) for links in collection.", children[index]->uri);
+ result = false;
+ break;
+ }
+ dimensions[0] = if_count;
+ result = OCRepPayloadSetStringArrayAsOwner(link_arr[index], OC_RSRVD_INTERFACE, if_types, dimensions);
+ if (!result) {
+ ST_LOG_V(ST_ERROR, "Failed to set the interface types of child(%s) for links in collection.", children[index]->uri);
+ result = false;
+ break;
+ }
+ if_types = NULL;
+
+ ST_LOG_V(ST_DEBUG, "Interface types of child resource(%s) are set in the response payload.", children[index]->uri);
+ }
+
+ if (result) {
+ *count = num_of_children;
+ *links = link_arr;
+ } else {
+ // Release memory allocated for resource types.
+ if (res_types != NULL) {
+ util_free_str_array(res_types, rt_count);
+ }
+ // Release memory allocated for interface types.
+ if (if_types != NULL) {
+ util_free_str_array(if_types, if_count);
+ }
+
+ for (int i = 0; i < num_of_children && NULL != link_arr[i]; i++) {
+ OCRepPayloadDestroy(link_arr[i]);
+ }
+ util_free(link_arr);
+
+ *count = 0;
+ *links = NULL;
+ }
+
+ return result;
+}
+
+ /*
+ * Response for links list can directly be sent without dependency on application
+ * because the response will include only the common properties of all the child resources.
+ *
+ * Sample response representation:-
+ *
+ * {
+ * // Child resources' common properties
+ * "links":
+ * [
+ * {
+ * "href": , // Resource URI
+ * "rt": [],
+ * "if": []
+ * },
+ * {
+ * "href": , // Resource URI
+ * "rt": [],
+ * "if": []
+ * }
+ * ]
+ * }
+ */
+static bool handle_get_req_on_collection_linkslist(things_resource_s *collection_rsrc)
+{
+ RET_FALSE_IF_PARAM_IS_NULL(collection_rsrc);
+
+ // Setup the response representation. This representation will be handed over to the underlying stack.
+ things_representation_s *resp_rep = things_create_representation_inst(NULL);
+ RET_FALSE_IF_NULL(resp_rep, "Failed to create response representation.");
+
+ OCRepPayload *payload = resp_rep->payload;
+ if (NULL == payload) {
+ ST_LOG(ST_ERROR, "Payload in response representation is NULL.");
+ things_release_representation_inst(resp_rep);
+ return false;
+ }
+ // Get the "links".
+ size_t count = 0;
+ OCRepPayload **links = NULL;
+ bool result = false;
+ if (form_collection_links(collection_rsrc, &links, &count)) {
+ size_t dimensions[MAX_REP_ARRAY_DEPTH] = { count, 0, 0 };
+ result = OCRepPayloadSetPropObjectArrayAsOwner(payload, OC_RSRVD_LINKS, links, dimensions);
+ if (!result) {
+ ST_LOG(ST_ERROR, "Failed to add the links in the response payload.");
+ for (size_t i = 0; i < count && NULL != links[i]; i++) {
+ OCRepPayloadDestroy(links[i]);
+ }
+ util_free(links);
+ }
+ } else {
+ ST_LOG(ST_ERROR, "Failed to form links for collection.");
+ }
+
+ if (result) {
+ collection_rsrc->things_set_representation(collection_rsrc, resp_rep);
+ } else {
+ things_release_representation_inst(resp_rep);
+ }
+
+ return result;
+}
+
+ /*
+ * Sample response representation:-
+ *
+ * {
+ * "href": ,
+ *
+ * // Collection resource's common properties
+ * "rt":[],
+ * "if":[],
+ * "links":
+ * [
+ * {
+ * "href": , // Resource URI
+ * "rt": [],
+ * "if": []
+ * },
+ * {
+ * "href": , // Resource URI
+ * "rt": [],
+ * "if": []
+ * }
+ * ]
+ *
+ * // Collection resource's properties
+ * "ps":,
+ * "lec":,
+ * }
+ */
+static bool handle_get_req_on_collection_baseline(things_resource_s *collection_rsrc)
+{
+ RET_FALSE_IF_PARAM_IS_NULL(collection_rsrc);
+
+ // Setup the response representation. This representation will be handed over to the underlying stack.
+ things_representation_s *resp_rep = things_create_representation_inst(NULL);
+ RET_FALSE_IF_NULL(resp_rep, "Failed to create response representation.");
+
+ OCRepPayload *resp_payload = resp_rep->payload;
+ if (NULL == resp_payload) {
+ ST_LOG(ST_ERROR, "Payload in response representation is NULL.");
+ things_release_representation_inst(resp_rep);
+ return false;
+ }
+ // Set collection resource's URI.
+ if (!OCRepPayloadSetUri(resp_payload, collection_rsrc->uri)) {
+ ST_LOG_V(ST_ERROR, "Failed to set the resource uri(%s) in response payload.", collection_rsrc->uri);
+ things_release_representation_inst(resp_rep);
+ return false;
+ }
+
+ ST_LOG_V(ST_DEBUG, "Resource URI(%s) is set in the response payload.", collection_rsrc->uri);
+
+ // Set collection resource's common properties (rt, if & links).
+ bool result = add_common_props(collection_rsrc, true, resp_payload);
+ if (!result) {
+ ST_LOG(ST_ERROR, "Failed to add the common properties in response representation.");
+ things_release_representation_inst(resp_rep);
+ return false;
+ }
+
+ ST_LOG(ST_DEBUG, "Common properties are added in the response payload.");
+
+ // Get the properties of the collection resource from application.
+ result = handle_get_req_helper(collection_rsrc->uri, collection_rsrc->query, resp_payload);
+ if (!result) {
+ ST_LOG(ST_ERROR, "Failed to get the resource properties from application.");
+ things_release_representation_inst(resp_rep);
+ return false;
+ }
+
+ collection_rsrc->things_set_representation(collection_rsrc, resp_rep);
+
+ return true;
+}
+
+ /*
+ * Linked list of payload(OCRepPayload) of each and every resources.
+ * First object in the payload is collection resource.
+ *
+ * Sample response representation:-
+ *
+ * {
+ * "href": ,
+ * "rep":
+ * {
+ * // Collection resource's common properties
+ * "rt":[],
+ * "if":[],
+ * "links":[],
+ *
+ * // Collection resource's properties
+ * "ps":,
+ * "lec":,
+ * }
+ * },
+ * {
+ * "href": ,
+ * "rep":
+ * {
+ * // Child resource's common properties
+ * "rt":[],
+ * "if":[],
+ *
+ * // Child resource's properties
+ * "prop1":,
+ * "prop2":,
+ * }
+ * }
+ */
+static bool handle_get_req_on_collection_batch(things_resource_s *collection_rsrc)
+{
+ RET_FALSE_IF_PARAM_IS_NULL(collection_rsrc);
+
+ // Setup the response representation. This representation will be handed over to the underlying stack.
+ things_representation_s *resp_rep = things_create_representation_inst(NULL);
+ RET_FALSE_IF_NULL(resp_rep, "Failed to create response representation.");
+
+ OCRepPayload *payload_head = resp_rep->payload;
+ if (NULL == payload_head) {
+ ST_LOG(ST_ERROR, "Payload in response representation is NULL.");
+ things_release_representation_inst(resp_rep);
+ return false;
+ }
+ // Handle collection resource.
+ // Set collection resource's URI.
+ if (!OCRepPayloadSetUri(payload_head, collection_rsrc->uri)) {
+ ST_LOG_V(ST_ERROR, "Failed to set the resource uri(%s) in response payload.", collection_rsrc->uri);
+ things_release_representation_inst(resp_rep);
+ return false;
+ }
+
+ ST_LOG_V(ST_DEBUG, "Resource URI(%s) is set in the response payload.", collection_rsrc->uri);
+
+ OCRepPayload *rep_payload = OCRepPayloadCreate();
+ if (NULL == rep_payload) {
+ ST_LOG(ST_ERROR, "Failed to create response payload for 'rep'.");
+ things_release_representation_inst(resp_rep);
+ return false;
+ }
+ // Set collection resource's common properties (rt, if & links).
+ bool result = add_common_props(collection_rsrc, true, rep_payload);
+ if (!result) {
+ ST_LOG(ST_ERROR, "Failed to add collection's common properties in response payload.");
+ OCRepPayloadDestroy(rep_payload);
+ things_release_representation_inst(resp_rep);
+ return false;
+ }
+
+ ST_LOG(ST_DEBUG, "Collection's common properties are added in the response payload.");
+
+ // Get the properties of the collection resource from application.
+ result = handle_get_req_helper(collection_rsrc->uri, collection_rsrc->query, rep_payload);
+ if (!result) {
+ ST_LOG_V(ST_DEBUG, "Failed to get the collection resource(%s) properties from application.", collection_rsrc->uri);
+ ST_LOG(ST_DEBUG, "Corresponding payload in response will be empty.");
+ }
+
+ result = OCRepPayloadSetPropObjectAsOwner(payload_head, OC_RSRVD_REPRESENTATION, rep_payload);
+ if (!result) {
+ ST_LOG(ST_ERROR, "Failed to set 'rep' for collection in response payload.");
+ OCRepPayloadDestroy(rep_payload);
+ things_release_representation_inst(resp_rep);
+ return false;
+ }
+
+ rep_payload = NULL;
+
+ // Handle child resources.
+ int num_of_children = 0;
+ things_resource_info_s **children = NULL;
+ if (!things_get_child_resources(collection_rsrc->uri, &num_of_children, &children)) {
+ ST_LOG(ST_ERROR, "Failed to get child resources.");
+ things_release_representation_inst(resp_rep);
+ return false;
+ }
+
+ if (0 == num_of_children || NULL == children) {
+ ST_LOG(ST_ERROR, "No child resource(s).");
+ things_release_representation_inst(resp_rep);
+ return false;
+ }
+
+ ST_LOG_V(ST_DEBUG, "Collection resource(%s) has %d child resource(s).", collection_rsrc->uri, num_of_children);
+
+ result = true;
+ int rt_count = 0;
+ int if_count = 0;
+ char **res_types = NULL;
+ char **if_types = NULL;
+ size_t dimensions[MAX_REP_ARRAY_DEPTH] = { 0, 0, 0 };
+ OCRepPayload *payload = payload_head;
+ OCRepPayload *child_payload = NULL;
+ for (int index = 0; index < num_of_children; index++) {
+ if (NULL == children[index]) {
+ ST_LOG_V(ST_ERROR, "Child at index(%d) is NULL.", index);
+ result = false;
+ break;
+ }
+
+ child_payload = OCRepPayloadCreate();
+ if (NULL == child_payload) {
+ ST_LOG(ST_ERROR, "Failed to create payload for child.");
+ result = false;
+ break;
+ }
+ // Set child resource's URI.
+ if (!OCRepPayloadSetUri(child_payload, children[index]->uri)) {
+ ST_LOG_V(ST_ERROR, "Failed to set the child resource uri(%s) in response representation.", children[index]->uri);
+ result = false;
+ break;
+ }
+ // Set child resource's representation (common properties and resource properties).
+ rep_payload = OCRepPayloadCreate();
+ if (NULL == rep_payload) {
+ ST_LOG(ST_ERROR, "Failed to create payload for child.");
+ result = false;
+ break;
+ }
+ // Set the resource types.
+ if (!get_resource_types2(children[index], &res_types, &rt_count)) {
+ ST_LOG(ST_ERROR, "Failed to get the resource types of child.");
+ result = false;
+ break;
+ }
+ dimensions[0] = rt_count;
+ if (!OCRepPayloadSetStringArrayAsOwner(rep_payload, OC_RSRVD_RESOURCE_TYPE, res_types, dimensions)) {
+ ST_LOG(ST_ERROR, "Failed to set the resource types of child in response representation.");
+ result = false;
+ break;
+ }
+ res_types = NULL;
+
+ // Set the interface types.
+ if (!get_interface_types2(children[index], &if_types, &if_count)) {
+ ST_LOG(ST_ERROR, "Failed to get the interface types of child.");
+ result = false;
+ break;
+ }
+ dimensions[0] = if_count;
+ if (!OCRepPayloadSetStringArrayAsOwner(rep_payload, OC_RSRVD_INTERFACE, if_types, dimensions)) {
+ ST_LOG(ST_ERROR, "Failed to set the inteface types of child in response representation.");
+ result = false;
+ break;
+ }
+ if_types = NULL;
+
+ // First interface supported by the resource is the default inteface.
+ // Form a query with the first interface.
+ char **child_if_types = children[index]->interface_types;
+ if (NULL == child_if_types) {
+ ST_LOG(ST_ERROR, "Child resource doesn't have any interface.");
+ result = false;
+ break;
+ }
+ char *if_type = child_if_types[0];
+ if (NULL == if_type) {
+ ST_LOG(ST_ERROR, "First interface of child resource is NULL.");
+ result = false;
+ break;
+ }
+
+ char *prefix = "if=";
+ char *query = (char *)util_malloc(strlen(if_type) + strlen(prefix) + 1);
+ if (NULL == query) {
+ ST_LOG(ST_ERROR, "Failed to create query for child.");
+ result = false;
+ break;
+ }
+
+ strncat(query, prefix, strlen(prefix));
+ strncat(query, if_type, strlen(if_type));
+
+ // Get the properties of the child resource from application.
+ result = handle_get_req_helper(children[index]->uri, query, rep_payload);
+ if (!result) {
+ ST_LOG_V(ST_DEBUG, "Failed to get the child resource(%s) properties from application.", children[index]->uri);
+ ST_LOG(ST_DEBUG, "Corresponding payload in response will be empty.");
+ }
+
+ if (!OCRepPayloadSetPropObjectAsOwner(child_payload, OC_RSRVD_REPRESENTATION, rep_payload)) {
+ ST_LOG(ST_ERROR, "Failed to set the child representation in response representation.");
+ util_free(query);
+ result = false;
+ break;
+ }
+
+ rep_payload = NULL;
+
+ util_free(query);
+
+ payload->next = child_payload;
+ payload = child_payload;
+ }
+
+ if (!result) {
+ if (NULL != res_types) {
+ util_free_str_array(res_types, rt_count);
+ }
+
+ if (NULL != if_types) {
+ util_free_str_array(if_types, if_count);
+ }
+
+ OCRepPayloadDestroy(child_payload);
+ OCRepPayloadDestroy(rep_payload);
+ things_release_representation_inst(resp_rep);
+ return false;
+ }
+
+ collection_rsrc->things_set_representation(collection_rsrc, resp_rep);
+
+ return true;
+}
+
+ /*
+ * Handles GET request for colletion resources on "read-only", "read-write", "actuator" and "sensor" interfaces.
+ * Common properties will not be added.
+ */
+static bool handle_get_req_on_collection_common(things_resource_s *collection_rsrc)
+{
+ RET_FALSE_IF_PARAM_IS_NULL(collection_rsrc);
+
+ // Setup the response representation. This representation will be handed over to the underlying stack.
+ things_representation_s *resp_rep = things_create_representation_inst(NULL);
+ RET_FALSE_IF_NULL(resp_rep, "Failed to create response representation.");
+
+ OCRepPayload *resp_payload = resp_rep->payload;
+ if (NULL == resp_payload) {
+ ST_LOG(ST_ERROR, "Payload is response representation is NULL.");
+ things_release_representation_inst(resp_rep);
+ return false;
+ }
+
+ if (!OCRepPayloadSetUri(resp_payload, collection_rsrc->uri)) {
+ ST_LOG_V(ST_ERROR, "Failed to set the resource uri(%s) in response payload.", collection_rsrc->uri);
+ things_release_representation_inst(resp_rep);
+ return false;
+ }
+
+ ST_LOG_V(ST_DEBUG, "Resource URI(%s) is set in the response payload.", collection_rsrc->uri);
+
+ // Get the resource's properties from the application.
+ bool result = handle_get_req_helper(collection_rsrc->uri, collection_rsrc->query, resp_payload);
+ if (!result) {
+ ST_LOG(ST_ERROR, "Failed to get the resource properties from application.");
+ things_release_representation_inst(resp_rep);
+ return false;
+ }
+ // Set the response representation in the resource.
+ collection_rsrc->things_set_representation(collection_rsrc, resp_rep);
+ return true;
+}
+
+int handle_get_req_on_collection_rsrc(things_resource_s *collection_rsrc)
+{
+ RET_VAL_IF_PARAM_IS_NULL(collection_rsrc, 0);
+
+ // Get interface type from query parameter
+ char *if_type = NULL;
+ if (NULL != collection_rsrc->query && strlen(collection_rsrc->query) > 0) {
+ bool found = false;
+ bool result = get_query_value_internal(collection_rsrc->query, OC_RSRVD_INTERFACE, &if_type, &found);
+ if (found && !result) { // If query is present but API returns false.
+ ST_LOG_V(ST_ERROR, "Failed to get the interface type from query parameter(%s).", collection_rsrc->query);
+ return 0;
+ }
+ }
+ // If interface is not available in the query parameter, then "oic.if.ll" will be taken as the default interface.
+ // Reasons:-
+ // 1. Default collection request handler in iotivity stack(occollection.c)
+ // takes "links list" as the default interface to serve collection resource requests.
+ // 2. Underlying stack adds "oic.if.ll" to all collection resources.
+ if (NULL == if_type) {
+ if_type = util_clone_string(OC_RSRVD_INTERFACE_LL);
+ RET_VAL_IF_NULL(if_type, "Failed to clone interface type.", 0);
+ }
+
+ ST_LOG_V(ST_DEBUG, "This GET request will be handled on %s inteface.", if_type);
+
+ bool result = false;
+ if (0 == strncmp(if_type, OC_RSRVD_INTERFACE_DEFAULT, strlen(OC_RSRVD_INTERFACE_DEFAULT))) {
+ result = handle_get_req_on_collection_baseline(collection_rsrc);
+ } else if (0 == strncmp(if_type, OC_RSRVD_INTERFACE_LL, strlen(OC_RSRVD_INTERFACE_LL))) {
+ result = handle_get_req_on_collection_linkslist(collection_rsrc);
+ } else if (0 == strncmp(if_type, OC_RSRVD_INTERFACE_BATCH, strlen(OC_RSRVD_INTERFACE_BATCH))) {
+ result = handle_get_req_on_collection_batch(collection_rsrc);
+ } else {
+ result = handle_get_req_on_collection_common(collection_rsrc);
+ }
+
+ util_free(if_type);
+
+ return result ? 1 : 0;
+}
+
+ /*
+ * POST request and response schema is same as the GET response schema.
+ */
+static bool handle_post_req_on_collection_baseline(things_resource_s *collection_rsrc)
+{
+ RET_FALSE_IF_PARAM_IS_NULL(collection_rsrc);
+
+ // Retrieve the request representation. This representation will hold all the input properties of post request.
+ // Payload in this representation will be used to form the request message which will be given to the application.
+ struct things_representation_s *req_rep = NULL;
+ bool rep_exist = collection_rsrc->things_get_representation(collection_rsrc, &req_rep);
+ if (!rep_exist || NULL == req_rep || NULL == req_rep->payload) {
+ ST_LOG(ST_ERROR, "Empty payload in POST request.");
+ return false; // TODO: When a post request comes with empty payload, how do we handle?
+ }
+ // Setup the response representation. This representation will be handed over to the underlying stack.
+ things_representation_s *resp_rep = things_create_representation_inst(NULL);
+ RET_FALSE_IF_NULL(resp_rep, "Failed to create response representation.");
+
+ OCRepPayload *resp_payload = resp_rep->payload;
+ if (NULL == resp_payload) {
+ ST_LOG(ST_ERROR, "Payload in response representation is NULL.");
+ things_release_representation_inst(resp_rep);
+ return false;
+ }
+ // Set collection resource's URI.
+ if (!OCRepPayloadSetUri(resp_payload, collection_rsrc->uri)) {
+ ST_LOG_V(ST_ERROR, "Failed to set the resource uri(%s) in response payload.", collection_rsrc->uri);
+ things_release_representation_inst(resp_rep);
+ return false;
+ }
+
+ ST_LOG_V(ST_DEBUG, "Resource URI(%s) is set in the response payload.", collection_rsrc->uri);
+
+ // Set collection resource's common properties (rt, if, & links).
+ bool result = add_common_props(collection_rsrc, true, resp_payload);
+ if (!result) {
+ ST_LOG(ST_ERROR, "Failed to add the common properties in response payload.");
+ things_release_representation_inst(resp_rep);
+ return false;
+ }
+
+ ST_LOG(ST_DEBUG, "Common properties are added in the response payload.");
+
+ // Give the properties of the collection resource to application and get the response.
+ result = handle_post_req_helper(collection_rsrc->uri, collection_rsrc->query, req_rep->payload, resp_payload);
+ if (!result) {
+ ST_LOG(ST_ERROR, "Failed to set the resource properties.");
+ things_release_representation_inst(resp_rep);
+ return false;
+ }
+
+ collection_rsrc->things_set_representation(collection_rsrc, resp_rep);
+
+ return true;
+}
+
+ /*
+ * POST request and response schema is same as the GET response schema.
+ */
+static bool handle_post_req_on_collection_batch(things_resource_s *collection_rsrc)
+{
+ RET_FALSE_IF_PARAM_IS_NULL(collection_rsrc);
+
+ // Retrieve the request representation. This representation will hold all the input properties of post request.
+ // Payload in this representation will be used to form the request message which will be given to the application.
+ struct things_representation_s *req_rep = NULL;
+ bool rep_exist = collection_rsrc->things_get_representation(collection_rsrc, &req_rep);
+ if (!rep_exist || NULL == req_rep || NULL == req_rep->payload) {
+ ST_LOG(ST_ERROR, "Empty payload in POST request.");
+ return false; // TODO: When a post request comes with empty payload, how do we handle?
+ }
+ // Setup the response representation. This representation will be handed over to the underlying stack.
+ things_representation_s *resp_rep = things_create_representation_inst(NULL);
+ RET_FALSE_IF_NULL(resp_rep, "Failed to create response representation.");
+
+ OCRepPayload *payload_head = resp_rep->payload;
+ if (NULL == payload_head) {
+ ST_LOG(ST_ERROR, "Payload in response representation is NULL.");
+ things_release_representation_inst(resp_rep);
+ return false;
+ }
+ // Handle collection resource.
+ // Set collection resource's URI.
+ if (!OCRepPayloadSetUri(payload_head, collection_rsrc->uri)) {
+ ST_LOG_V(ST_ERROR, "Failed to set the resource uri(%s) in response payload.", collection_rsrc->uri);
+ things_release_representation_inst(resp_rep);
+ return false;
+ }
+
+ ST_LOG_V(ST_DEBUG, "Resource URI(%s) is set in the response payload.", collection_rsrc->uri);
+
+ OCRepPayload *rep_payload = OCRepPayloadCreate();
+ if (NULL == rep_payload) {
+ ST_LOG(ST_ERROR, "Failed to create payload for response representation.");
+ things_release_representation_inst(resp_rep);
+ return false;
+ }
+ // Set collection resource's common properties (rt, if, & links).
+ bool result = add_common_props(collection_rsrc, true, rep_payload);
+ if (!result) {
+ ST_LOG(ST_ERROR, "Failed to add collection's common properties in response payload.");
+ OCRepPayloadDestroy(rep_payload);
+ things_release_representation_inst(resp_rep);
+ return false;
+ }
+
+ ST_LOG(ST_DEBUG, "Collection's common properties are added in the response payload.");
+
+ // Get the properties of the collection resource from application.
+ result = handle_post_req_helper(collection_rsrc->uri, collection_rsrc->query, req_rep->payload, rep_payload);
+ if (!result) {
+ ST_LOG_V(ST_DEBUG, "Failed to get the collection resource(%s) properties from application.", collection_rsrc->uri);
+ ST_LOG(ST_DEBUG, "Corresponding payload in response will be empty.");
+ }
+
+ result = OCRepPayloadSetPropObjectAsOwner(payload_head, OC_RSRVD_REPRESENTATION, rep_payload);
+ if (!result) {
+ ST_LOG(ST_ERROR, "Failed to set the representation for collection in response payload.");
+ OCRepPayloadDestroy(rep_payload);
+ things_release_representation_inst(resp_rep);
+ return false;
+ }
+
+ rep_payload = NULL;
+
+ // Handle child resources.
+ result = true;
+ int num_of_children = 0;
+ things_resource_info_s **children = NULL;
+ if (!things_get_child_resources(collection_rsrc->uri, &num_of_children, &children)) {
+ ST_LOG(ST_ERROR, "Failed to get child resources.");
+ things_release_representation_inst(resp_rep);
+ return false;
+ }
+
+ if (0 == num_of_children || NULL == children) {
+ ST_LOG(ST_ERROR, "No child resource(s).");
+ things_release_representation_inst(resp_rep);
+ return false;
+ }
+
+ ST_LOG_V(ST_DEBUG, "Collection resource(%s) has %d child resource(s).", collection_rsrc->uri, num_of_children);
+
+ int rt_count = 0;
+ int if_count = 0;
+ char **res_types = NULL;
+ char **if_types = NULL;
+ size_t dimensions[MAX_REP_ARRAY_DEPTH] = { 0, 0, 0 };
+ OCRepPayload *child_head = NULL;
+ OCRepPayload *prev_payload = NULL; // Represents the previous payload in the linked list.
+ OCRepPayload *payload = NULL; // Represents the current payload in loop.
+ for (int index = 0; index < num_of_children; index++) {
+ if (NULL == children[index]) {
+ ST_LOG_V(ST_ERROR, "Child at index(%d) is NULL.", index);
+ result = false;
+ break;
+ }
+
+ payload = OCRepPayloadCreate();
+ if (NULL == payload) {
+ ST_LOG(ST_ERROR, "Failed to create payload for child.");
+ result = false;
+ break;
+ }
+ // Set child resource's URI.
+ if (!OCRepPayloadSetUri(payload, children[index]->uri)) {
+ ST_LOG_V(ST_ERROR, "Failed to set the child resource uri(%s) in response representation.", children[index]->uri);
+ result = false;
+ break;
+ }
+ // Set child resource's representation (common properties and resource properties).
+ rep_payload = OCRepPayloadCreate();
+ if (NULL == rep_payload) {
+ ST_LOG(ST_ERROR, "Failed to create payload for child.");
+ result = false;
+ break;
+ }
+ // Set the resource types.
+ if (!get_resource_types2(children[index], &res_types, &rt_count)) {
+ ST_LOG(ST_ERROR, "Failed to get the resource types of child.");
+ result = false;
+ break;
+ }
+ dimensions[0] = rt_count;
+ if (!OCRepPayloadSetStringArrayAsOwner(rep_payload, OC_RSRVD_RESOURCE_TYPE, res_types, dimensions)) {
+ ST_LOG(ST_ERROR, "Failed to set the resource types of child in response representation.");
+ result = false;
+ break;
+ }
+ res_types = NULL;
+
+ // Set the interface types.
+ if (!get_interface_types2(children[index], &if_types, &if_count)) {
+ ST_LOG(ST_ERROR, "Failed to get the interface types of child.");
+ result = false;
+ break;
+ }
+ dimensions[0] = if_count;
+ if (!OCRepPayloadSetStringArrayAsOwner(rep_payload, OC_RSRVD_INTERFACE, if_types, dimensions)) {
+ ST_LOG(ST_ERROR, "Failed to set the inteface types of child in response representation.");
+ result = false;
+ break;
+ }
+ if_types = NULL;
+
+ // First interface supported by the resource is the default inteface.
+ // Form a query with the first interface.
+ char **child_if_types = children[index]->interface_types;
+ if (NULL == child_if_types) {
+ ST_LOG(ST_ERROR, "Child resource doesn't have any interface.");
+ result = false;
+ break;
+ }
+ char *if_type = child_if_types[0];
+ if (NULL == if_type) {
+ ST_LOG(ST_ERROR, "First interface of child resource is NULL.");
+ result = false;
+ break;
+ }
+
+ char *prefix = "if=";
+ char *query = (char *)util_malloc(strlen(if_type) + strlen(prefix) + 1);
+ if (NULL == query) {
+ ST_LOG(ST_ERROR, "Failed to create query for child.");
+ result = false;
+ break;
+ }
+
+ strncat(query, prefix, strlen(prefix));
+ strncat(query, if_type, strlen(if_type));
+
+ // Get the properties of the child resource from application.
+ result = handle_post_req_helper(children[index]->uri, query, req_rep->payload, rep_payload);
+ if (!result) {
+ ST_LOG_V(ST_DEBUG, "Failed to get the child resource(%s) properties from application.", children[index]->uri);
+ ST_LOG(ST_DEBUG, "Corresponding payload in response will be empty.");
+ }
+
+ if (!OCRepPayloadSetPropObjectAsOwner(payload, OC_RSRVD_REPRESENTATION, rep_payload)) {
+ ST_LOG(ST_ERROR, "Failed to set the child representation in response representation.");
+ result = false;
+ break;
+ }
+
+ rep_payload = NULL;
+
+ if (NULL != prev_payload) {
+ prev_payload->next = payload;
+ } else {
+ child_head = payload;
+ }
+ prev_payload = payload;
+ payload = NULL;
+
+ util_free(query);
+ }
+
+ if (!result) {
+ if (NULL != res_types) {
+ util_free_str_array(res_types, rt_count);
+ }
+
+ if (NULL != if_types) {
+ util_free_str_array(if_types, if_count);
+ }
+
+ OCRepPayloadDestroy(rep_payload);
+ OCRepPayloadDestroy(payload);
+ OCRepPayloadDestroy(child_head);
+ things_release_representation_inst(resp_rep);
+ return false;
+ }
+
+ payload_head->next = child_head;
+ collection_rsrc->things_set_representation(collection_rsrc, resp_rep);
+ return true;
+}
+
+ /*
+ * Handles POST request for colletion resources on "read-write" and "actuator" interfaces.
+ * Request and response neither include the common properties of collection resource
+ * nor the child resources' properties which means both request and response includes only
+ * the collection resource's properties.
+ */
+static bool handle_post_req_on_collection_common(things_resource_s *collection_rsrc)
+{
+ RET_FALSE_IF_PARAM_IS_NULL(collection_rsrc);
+
+ // Retrieve the request representation. This representation will hold all the input properties of post request.
+ // Payload in this representation will be used to form the request message which will be given to the application.
+ struct things_representation_s *req_rep = NULL;
+ bool rep_exist = collection_rsrc->things_get_representation(collection_rsrc, &req_rep);
+ if (!rep_exist || NULL == req_rep || NULL == req_rep->payload) {
+ ST_LOG(ST_ERROR, "Empty payload in POST request.");
+ return false; // TODO: When a post request comes with empty payload, how do we handle?
+ }
+ // Setup the response representation. This representation will be handed over to the underlying stack.
+ things_representation_s *resp_rep = things_create_representation_inst(NULL);
+ RET_FALSE_IF_NULL(resp_rep, "Failed to create response representation.");
+
+ OCRepPayload *resp_payload = resp_rep->payload;
+ if (NULL == resp_payload) {
+ ST_LOG(ST_ERROR, "Payload is response representation is NULL.");
+ things_release_representation_inst(resp_rep);
+ return false;
+ }
+
+ if (!OCRepPayloadSetUri(resp_payload, collection_rsrc->uri)) {
+ ST_LOG_V(ST_ERROR, "Failed to set the resource uri(%s) in response payload.", collection_rsrc->uri);
+ things_release_representation_inst(resp_rep);
+ return false;
+ }
+
+ ST_LOG_V(ST_DEBUG, "Resource URI(%s) is set in the response payload.", collection_rsrc->uri);
+
+ // Give the properties of the collection resource to application and get the response.
+ bool result = handle_post_req_helper(collection_rsrc->uri, collection_rsrc->query,
+ req_rep->payload, resp_payload);
+ if (!result) {
+ ST_LOG(ST_ERROR, "Failed to set the resource properties.");
+ things_release_representation_inst(resp_rep);
+ return false;
+ }
+ // Set the response representation in the resource.
+ collection_rsrc->things_set_representation(collection_rsrc, resp_rep);
+
+ return true;
+}
+
+int handle_post_req_on_collection_rsrc(things_resource_s *collection_rsrc)
+{
+ RET_VAL_IF_PARAM_IS_NULL(collection_rsrc, 0);
+
+ // Get interface type from query parameter.
+ char *if_type = NULL;
+ if (NULL != collection_rsrc->query && strlen(collection_rsrc->query) > 0) {
+ bool found = false;
+ bool result = get_query_value_internal(collection_rsrc->query, OC_RSRVD_INTERFACE, &if_type, &found);
+ if (found && !result) { // If query is present but API returns false.
+ ST_LOG_V(ST_ERROR, "Failed to get the interface type from query parameter(%s).", collection_rsrc->query);
+ return 0;
+ }
+ }
+ // If interface is not available in the query parameter, then "oic.if.baseline" will be taken as the default interface.
+ if (NULL == if_type) {
+ if_type = util_clone_string(OC_RSRVD_INTERFACE_DEFAULT);
+ RET_VAL_IF_NULL(if_type, "Failed to clone interface type.", 0);
+ }
+
+ ST_LOG_V(ST_DEBUG, "This SET request will be handled on %s inteface.", if_type);
+
+ bool result = false;
+ if (0 == strncmp(if_type, OC_RSRVD_INTERFACE_DEFAULT, strlen(OC_RSRVD_INTERFACE_DEFAULT))) {
+ result = handle_post_req_on_collection_baseline(collection_rsrc);
+ } else if (0 == strncmp(if_type, OC_RSRVD_INTERFACE_BATCH, strlen(OC_RSRVD_INTERFACE_BATCH))) {
+ result = handle_post_req_on_collection_batch(collection_rsrc);
+ } else if (0 == strncmp(if_type, ST_THINGS_RSRVD_INTERFACE_READWRITE, strlen(ST_THINGS_RSRVD_INTERFACE_READWRITE))) {
+ result = handle_post_req_on_collection_common(collection_rsrc);
+ } else if (0 == strncmp(if_type, ST_THINGS_RSRVD_INTERFACE_ACTUATOR, strlen(ST_THINGS_RSRVD_INTERFACE_ACTUATOR))) {
+ result = handle_post_req_on_collection_common(collection_rsrc);
+ } else {
+ result = false;
+ }
+
+ util_free(if_type);
+
+ return result ? 1 : 0;
+}
--- /dev/null
+/* ****************************************************************
+ *
+ * Copyright 2017 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.
+ *
+ ******************************************************************/
+
+#ifndef __ST_THINGS_REQUEST_HANDLER_COLLECTION_H__
+#define __ST_THINGS_REQUEST_HANDLER_COLLECTION_H__
+
+#include "things_resource.h"
+#include "octypes.h"
+
+bool form_collection_links(things_resource_s* collection_rsrc, OCRepPayload*** links, size_t* count);
+
+int handle_get_req_on_collection_rsrc(things_resource_s* collection_rsrc);
+
+int handle_post_req_on_collection_rsrc(things_resource_s* collection_rsrc);
+
+#endif // __ST_THINGS_REQUEST_HANDLER_COLLECTION_H__
--- /dev/null
+/* ****************************************************************
+ *
+ * Copyright 2017 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 "st_things_util.h"
+
+void *util_malloc(size_t size)
+{
+ RET_NULL_IF_PARAM_EXPR_IS_TRUE(size < 1);
+
+ return malloc(size);
+}
+
+void *util_calloc(size_t num, size_t size)
+{
+ RET_NULL_IF_PARAM_EXPR_IS_TRUE(num < 1);
+ RET_NULL_IF_PARAM_EXPR_IS_TRUE(size < 1);
+
+ return calloc(num, size);
+}
+
+void util_free(void *ptr)
+{
+ free(ptr);
+}
+
+char *util_clone_string(const char *str)
+{
+ RET_NULL_IF_PARAM_IS_NULL(str);
+
+ int len = strlen(str);
+ char *dest_str = (char *)util_malloc(sizeof(char) *len + 1);
+ if (NULL != dest_str) {
+ strncpy(dest_str, str, len + 1);
+ } else {
+ ST_LOG(ST_ERROR, "Memory allocation failed.");
+ }
+
+ return dest_str;
+}
+
+void util_free_str_array(char **ptr, size_t size)
+{
+ RET_IF_PARAM_IS_NULL(ptr);
+ RET_IF_PARAM_EXPR_IS_TRUE(size < 1);
+
+ for (size_t index = 0; index < size; index++) {
+ free(ptr[index]);
+ }
+ free(ptr);
+}
--- /dev/null
+/* ****************************************************************
+ *
+ * Copyright 2017 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.
+ *
+ ******************************************************************/
+
+#ifndef __ST_THINGS_UTIL_H__
+#define __ST_THINGS_UTIL_H__
+
+#include <string.h>
+#include <stdlib.h>
+#include "st_things_logger.h"
+
+#define RET_IF_PARAM_IS_NULL(var) \
+ do { \
+ if (NULL == (var)) { \
+ ST_LOG(ST_ERROR, "Invalid Parameter: " #var " is NULL."); \
+ return; \
+ } \
+ } while (0)
+
+#define RET_NULL_IF_PARAM_IS_NULL(var) \
+ do { \
+ if (NULL == (var)) { \
+ ST_LOG(ST_ERROR, "Invalid Parameter: " #var " is NULL."); \
+ return NULL; \
+ } \
+ } while (0)
+
+#define RET_FALSE_IF_PARAM_IS_NULL(var) \
+ do { \
+ if (NULL == (var)) { \
+ ST_LOG(ST_ERROR, "Invalid Parameter: " #var " is NULL."); \
+ return false; \
+ } \
+ } while (0)
+
+#define RET_VAL_IF_PARAM_IS_NULL(var, ret_val) \
+ do { \
+ if (NULL == (var)) { \
+ ST_LOG(ST_ERROR, "Invalid Parameter: " #var " is NULL."); \
+ return (ret_val); \
+ } \
+ } while (0)
+
+#define RET_VAL_IF_NULL(var, msg, ret_val) \
+ do { \
+ if (NULL == (var)) { \
+ ST_LOG(ST_ERROR, msg); \
+ return (ret_val); \
+ } \
+ } while (0)
+
+#define RET_FALSE_IF_NULL(var, msg) \
+ do { \
+ if (NULL == (var)) { \
+ ST_LOG(ST_ERROR, msg); \
+ return false; \
+ } \
+ } while (0)
+
+#define RET_IF_PARAM_EXPR_IS_TRUE(expr) \
+ do { \
+ if ((expr)) { \
+ ST_LOG(ST_ERROR, "Invalid Parameter: " #expr); \
+ return; \
+ } \
+ } while (0)
+
+#define RET_NULL_IF_PARAM_EXPR_IS_TRUE(expr) \
+ do { \
+ if ((expr)) { \
+ ST_LOG(ST_ERROR, "Invalid Parameter: " #expr); \
+ return NULL; \
+ } \
+ } while (0)
+
+#define RET_FALSE_IF_PARAM_EXPR_IS_TRUE(expr) \
+ do { \
+ if ((expr)) { \
+ ST_LOG(ST_ERROR, "Invalid Parameter: " #expr); \
+ return false; \
+ } \
+ } while (0)
+
+#define RET_IF_EXPR_IS_TRUE(expr, msg) \
+ do { \
+ if ((expr)) { \
+ ST_LOG(ST_ERROR, msg); \
+ return; \
+ } \
+ } while (0)
+
+#define RET_FALSE_IF_EXPR_IS_TRUE(expr, msg) \
+ do { \
+ if ((expr)) { \
+ ST_LOG(ST_ERROR, msg); \
+ return false; \
+ } \
+ } while (0)
+
+#define RET_VAL_IF_EXPR_IS_TRUE(expr, msg, ret_val) \
+ do { \
+ if ((expr)) { \
+ ST_LOG(ST_ERROR, msg); \
+ return (ret_val); \
+ } \
+ } while (0)
+
+void *util_malloc(size_t size);
+
+void *util_calloc(size_t num, size_t size);
+
+void util_free(void *ptr);
+
+char *util_clone_string(const char *str);
+
+/**
+* Destroys the array items and the array.
+*/
+void util_free_str_array(char **ptr, size_t size);
+
+#endif // __ST_THINGS_UTIL_H__
--- /dev/null
+*.o
+*.os
+*.pyc
+*.a
+*.so
--- /dev/null
+###########################################################################
+#
+# Copyright 2017 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.
+#
+###########################################################################
+
+CSRCS += port_tinyara.c
+
+DEPPATH += --dep-path src/st_things/things_stack
+VPATH += :src/st_things/things_stack
\ No newline at end of file
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 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.
+ *
+ ****************************************************************************/
+
+#ifndef IOTIVITY_CONFIG_H__
+#define IOTIVITY_CONFIG_H__
+
+#include <tinyara/config.h>
+
+#define HAVE_ARPA_INET_H 1
+
+#define HAVE_FCNTL_H 1
+
+#define HAVE_GRP_H 1
+
+#define HAVE_NETDB_H 1
+
+#define HAVE_NETINET_IN_H 1
+
+#define HAVE_PTHREAD_H 1
+
+#define HAVE_PWD_H 1
+
+#define HAVE_STDLIB_H 1
+
+#define HAVE_STRING_H 1
+
+#define HAVE_STRINGS_H 1
+
+#define HAVE_SYS_SOCKET_H 1
+
+#define HAVE_SYS_STAT_H 1
+
+#define HAVE_SYS_TIME_H 1
+
+#define HAVE_SYS_TYPES_H 1
+
+#define HAVE_SYS_UNISTD_H 1
+
+#define HAVE_SYSLOG_H 1
+
+#define HAVE_TIME_H 1
+
+#define HAVE_UNISTD_H 1
+
+#define HAVE_UUID_UUID_H 1
+
+#include "platform_features.h"
+
+#endif // IOTIVITY_CONFIG_H__
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 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.
+ *
+ ****************************************************************************/
+
+#ifndef _THINGS_API_H_
+#define _THINGS_API_H_
+
+#include <stdint.h>
+#include "things_types.h"
+#include "things_resource.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#define TYPE_INT_64 "int64"
+#define TYPE_BOOL "boolean"
+#define TYPE_DOUBLE "double"
+#define TYPE_STRING "string"
+#define TYPE_BYTE "byte"
+
+#define MAX_IPADDR (16)
+#define OIC_UUID_STRING_SIZE (37)
+
+const char *things_get_sw_version();
+const char *things_get_device_id_string();
+int things_set_device_name(int dev_num, char *name);
+
+int things_initialize_stack(const char *json_path, bool *easysetup_completed);
+int things_deinitialize_stack();
+int things_start_stack();
+
+typedef void (*things_reset_result_func_type)(int result);
+
+typedef int (*things_reset_confirm_func_type)(things_reset_result_func_type *func_carrier, things_es_enrollee_reset_e reset_type);
+
+int things_register_confirm_reset_start_func(things_reset_confirm_func_type func);
+
+int things_return_user_opinion_for_reset(int b_reset_start);
+
+int things_reset(void *remote_owner, things_es_enrollee_reset_e reset_type);
+
+int things_stop(void);
+
+typedef int (*things_handle_request_func_type)(struct things_resource_s *p_resource);
+int things_register_handle_request_func(things_handle_request_func_type get_func, things_handle_request_func_type set_func);
+
+typedef int (*things_update_dev_prov_data_func_type)(es_dev_conf_prov_data_s *p_dev_prov_data);
+
+int things_register_update_dev_prov_data_func(things_update_dev_prov_data_func_type func);
+
+typedef int (*things_stop_soft_ap_func_type)(int value);
+
+int things_register_stop_soft_ap_func(things_stop_soft_ap_func_type func);
+
+int things_notify_observers(const char *uri);
+
+int things_send_push_message(const char *push_uri, void *payload);
+
+int things_wifi_changed_call_func(int state, char *ap_name, char *ip_addr);
+
+typedef void (*things_pin_generated_func_type)(char *pin_data, size_t pin_size);
+
+int things_register_pin_generated_func(things_pin_generated_func_type func);
+
+typedef void (*things_pin_display_close_func_type)(void);
+
+int things_register_pin_display_close_func(things_pin_display_close_func_type func);
+
+typedef int (*things_get_user_confirm_func_type)(void);
+
+int things_register_user_confirm_func(things_get_user_confirm_func_type func);
+
+int things_get_easysetup_state(void);
+
+typedef void (*things_get_easysetup_state_func_type)(things_es_enrollee_state_e state);
+
+int things_register_easysetup_state_func(things_get_easysetup_state_func_type func);
+
+typedef void (*things_cloud_con_result_func_type)(int result, char *domain, char *access_token);
+
+typedef void (*things_abort_easysetup_func_type)(things_es_enrollee_abort_e level);
+
+typedef void (*things_sec_otm_state_func_type)(const char *addr, uint16_t port, const char *uuid, int event);
+
+int things_register_otm_event_handler(things_sec_otm_state_func_type otm_event_callback);
+
+int things_save_acl(const char *uuid, const char *resource_uri, const char *resource_type, const char *interface_name, uint16_t permission);
+
+int things_set_mot_status(bool enable);
+
+int things_get_resource_type(const char *resource_uri, int *count, char ***resource_types);
+
+int things_get_attributes_by_resource_type(const char *res_type, int *count, things_attribute_info_s ***attributes);
+
+bool things_is_collection_resource(const char *res_uri);
+
+int things_get_child_resources(const char *col_res_uri, int *count, things_resource_info_s ***child_resources);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+#endif // _THINGS_API_H_
--- /dev/null
+/* ****************************************************************
+ *
+ * Copyright 2017 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.
+ *
+ ******************************************************************/
+
+#ifndef _THINGS_RESOURCE_H_
+#define _THINGS_RESOURCE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <octypes.h>
+
+//-----------------------------------------------------------------------------
+// Defines
+//-----------------------------------------------------------------------------
+#define QUERY_DELIMITER ";" // or "#"
+
+//-----------------------------------------------------------------------------
+// Typedefs
+//-----------------------------------------------------------------------------
+/* Structure for Array Attribute */
+typedef struct things_representation_s {
+ void *payload; // 8 bytes
+ void **children_payload; // 8 bytes
+ int64_t num_children; // 8 bytes
+ struct things_representation_s **children; // 8 * num_children bytes
+
+ /**
+ * @brief API for setting value with a key
+ * @param key : Attribute Key which will represent the value
+ * @param value : Attribute value
+ */
+ void (*things_set_value)(struct things_representation_s *rep, char *key, char *);
+ void (*things_set_bool_value)(struct things_representation_s *rep, char *key, bool);
+ void (*things_set_int_value)(struct things_representation_s *rep, char *key, int64_t);
+ void (*things_set_double_value)(struct things_representation_s *rep, char *key, double);
+ void (*things_set_byte_value)(struct things_representation_s *rep, char *key, uint8_t *value, size_t size);
+ bool(*things_set_object_value)(struct things_representation_s *mother, char *key, struct things_representation_s *child);
+ /**
+ * @brief API for setting/getting object array type of attribute.
+ * @param key : Attribute Key which will represent the array type of value
+ * @param length : Length of value(representation) array
+ * @param reps : Array type (representation) values
+ */
+ bool(*things_set_arrayvalue)(struct things_representation_s *, char *key, int length, struct things_representation_s **reps);
+
+ bool(*things_get_arrayvalue)(struct things_representation_s *, char *key, int *length, struct things_representation_s ***reps);
+
+ /**
+ * @brief API for setting/getting string array type of attribute.
+ * @param key : Attribute Key which will represent the array type of value
+ * @param length : Length of value(string) array
+ * @param array : Array type string values
+ */
+ void (*things_set_string_arrayvalue)(struct things_representation_s *mother, char *key, int length, char **array);
+
+ bool(*things_get_string_arrayvalue)(struct things_representation_s *mother, char *key, int *length, char ***array);
+
+ /**
+ * @brief API for setting/getting double array type of attribute.
+ * @param key : Attribute Key which will represent the array type of value
+ * @param length : Length of value(double) array
+ * @param array : Array type double values
+ */
+ void (*things_set_double_arrayvalue)(struct things_representation_s *mother, char *key, int length, double *array);
+
+ bool(*things_get_double_arrayvalue)(struct things_representation_s *mother, char *key, int *length, double **array);
+
+ /**
+ * @brief API for inserting int array type of attribute.
+ * @param key : Attribute Key which will represent the array type of value
+ * @param length : Length of value(int) array
+ * @param array : Array type int values
+ */
+ void (*things_set_int_arrayvalue)(struct things_representation_s *mother, char *key, int length, int64_t *array);
+
+ bool(*things_get_int_arrayvalue)(struct things_representation_s *mother, char *key, int *length, int64_t **array);
+ /**
+ * @brief API for getting value with a key
+ * @param key : Attribute Key which represents the value
+ * @param value : Reference of the variable to where value will be copied
+ * @return : true(value exist), false(value not exist)
+ */
+ bool(*things_get_value)(struct things_representation_s *rep, char *key, char **);
+ bool(*things_get_bool_value)(struct things_representation_s *rep, char *key, bool *);
+ bool(*things_get_int_value)(struct things_representation_s *rep, char *key, int64_t *);
+ bool(*things_get_double_value)(struct things_representation_s *rep, char *key, double *);
+ bool(*things_get_byte_value)(struct things_representation_s *rep, char *key, uint8_t **value, size_t *size);
+ bool(*things_get_object_value)(struct things_representation_s *mother, char *key, struct things_representation_s *child);
+
+} things_representation_s;
+
+/* Structure for Things resource */
+typedef struct things_resource_s {
+ char *query; // 4 bytes
+ char *uri; // 4 Bytes
+ char *res_type; // 4 Bytes
+ char *interface_type; // 4 Bytes
+
+ OCRequestHandle request_handle;
+ OCResourceHandle resource_handle; // 4 Bytes, OCResourceHandle handle;
+ int req_type; // 4 Bytes
+ double error; // 8 Bytes
+
+ struct things_resource_s *next; // 4 Bytes
+ struct things_representation_s *rep; // 4 Bytes
+
+ size_t size; // 4 bytes
+ char *cmd_id; // 4 Bytes
+
+ void *dev_addr; // sizeof(OCDevAddr) ????
+
+ void (*things_set_dev_addr)(struct things_resource_s *, void *OCDevAddr);
+ void *(*things_get_dev_addr)(struct things_resource_s *);
+
+ /**
+ * @brief API for setting URI.
+ * @param things_resource_s * : Instance of target resource
+ * @param const char * : URI string value
+ */
+ void (*things_set_uri)(struct things_resource_s *, const char *uri);
+ /**
+ * @brief API for setting error when returning request handling result
+ * @param things_resource_s * : Instance of target resource
+ * @param double : error code
+ */
+ void (*things_set_error)(struct things_resource_s *, double errorCode);
+
+ /**
+ * @brief API for getting query value
+ * @param things_resource_s * : Instance of target resource
+ * @param char* key : key value to look up in the query(ex: query -> key=value?key=value?...)
+ * @param char* value : value of the key in the query
+ * @return : true(query exist), false(query not exist)
+ */
+ bool(*things_get_query)(struct things_resource_s *, char *key, char **value);
+
+ /**
+ * @brief API for getting URI
+ * @param things_resource_s * : Instance of target resource
+ * @param char** uri : reference of the char* variable to where uri will be copied
+ */
+ void (*things_get_uri)(struct things_resource_s *, char **uri);
+
+ /**
+ * @brief API for getting # of supporting resource types
+ * @param things_resource_s * : Instance of target resource
+ * @return : Number of supporting resource types
+ */
+ int (*things_get_num_of_res_types)(struct things_resource_s *);
+ int (*things_get_num_of_inf_types)(struct things_resource_s *);
+ /**
+ * @brief API for getting # of supporting resource type with index
+ * @param things_resource_s * : Instance of target resource
+ * @param things_resource_s * : Index of supported resource type list
+ * @return : Supporting resource type
+ */
+ const char *(*things_get_res_type)(struct things_resource_s *, int index);
+ const char *(*things_get_inf_type)(struct things_resource_s *, int index);
+ /**
+ * @brief API for getting childrens of target resource
+ * @param things_resource_s * : Instance of target resource
+ * @return : Instance of children resource
+ * (Children resource are managed with Linked List)
+ */
+ struct things_resource_s *(*things_get_children)(struct things_resource_s *);
+
+ /**
+ * @brief API for setting representation of the target resource
+ * @param things_resource_s * : Instance of target resource
+ * @param things_representation_s * : Instance of the representation to set
+ */
+ void (*things_set_representation)(struct things_resource_s *, struct things_representation_s *rep);
+
+ /**
+ * @brief API for getting representation of the target resource
+ * @param things_resource_s * : Instance of target resource
+ * @param things_representation_s * : Instance of the representation to set
+ * @return : true(Representation exist), false(Representation not exist)
+ */
+ bool(*things_get_representation)(struct things_resource_s *, struct things_representation_s **rep);
+
+ /**
+ * @brief API for getting payload (Internal use only, NOT API)
+ * @param things_resource_s * : Instance of target resource
+ * @return : Instance OCRepPayload data structure defined by IoTivity stack
+ */
+ void *(*things_get_rep_payload)(struct things_resource_s *);
+
+ /**
+ * @brief API for creating instance of payload (Internal use only, NOT API)
+ * @param things_resource_s * : Instance of target resource
+ * @return : New instance OCRepPayload data structure defined by IoTivity stack
+ */
+ void *(*things_create_payload)(struct things_resource_s *, char *);
+
+ /**
+ * @brief API for checking whether given interface type is supporting one or not
+ * @param things_resource_s * : Instance of target resource
+ * @param iftype : Interface type to check
+ * @return : true (supporting interface type),false(not supporting)
+ */
+ bool(*things_is_supporting_interface_type)(struct things_resource_s *, char *ifType);
+
+ /**
+ * @brief API for checking whether given resource type is supporting one or not
+ * @param things_resource_s * : Instance of target resource
+ * @param iftype : Resource type to check
+ * @return : true (supporting resource type),false(not supporting)
+ */
+ bool(*things_is_supporting_resource_type)(struct things_resource_s *, char *res_type);
+
+ /**
+ * @brief API for setting frameid
+ * @brief Frameid will be used to match the response delivered from st_things SW with received request
+ * @param things_resource_s * : Instance of target resource
+ * @param cmd_id : Frame ID
+ */
+ void (*things_set_command_id)(struct things_resource_s *res, char *cmd_id);
+
+ /**
+ * @brief API for getting children resource instances
+ * @param things_resource_s * : Instance of target resource
+ * @return : Instance of children resource(s)
+ */
+ struct things_resource_s *(*things_get_next)(struct things_resource_s *);
+
+ /**
+ * @brief API for adding children resource instances
+ * @param things_resource_s * : Instance of target resource
+ * @param things_resource_s * : Instance of children resource
+ */
+ void (*things_add_child)(struct things_resource_s *, struct things_resource_s *);
+
+} things_resource_s;
+
+/**
+* @brief API for creating instance of payload
+* @param rep_payload : Instance of target resource
+* @return things_representation_s * : Instance of resource repsentation
+*/
+things_representation_s *things_create_representation_inst(void *rep_payload);
+
+/**
+* @brief API for creating instance of resource
+* @param void* : Instance of request handle
+* @param void* : Instance of resource handle
+* @param void* : Query in the request message
+* @param void* : Instance of payload in the request
+* @return things_resource_s * : Instance of resource repsentation
+*/
+things_resource_s *things_create_resource_inst(OCRequestHandle, OCResourceHandle, void *, void *);
+
+/**
+* @brief API for cloning instance of given resource
+* @param things_resource_s * : Instance of resource to clone
+* @return things_resource_s * : Instance of cloned resource
+*/
+things_resource_s *things_clone_resource_inst(things_resource_s *);
+void things_clone_resource_inst2(things_resource_s *pori, things_resource_s **pclone);
+
+/**
+* @brief API for releasing memory allocated for the instance of given representation
+* @param things_representation_s * : Instance of representation to release
+*/
+void things_release_representation_inst(things_representation_s *);
+
+/**
+* @brief API for releasing memory allocated for the instance of given resource
+* @param things_representation_s * : Instance of resource to release
+*/
+void things_release_resource_inst(things_resource_s *);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+#endif // _THINGS_RESOURCE_H_
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 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.
+ *
+ ****************************************************************************/
+
+#ifndef _THINGS_TYPES_H_
+#define _THINGS_TYPES_H_
+
+#define THINGS_STRING_MAX_DNSNAME 256
+#define THINGS_STRING_MAX_LENGTH 100
+
+#define MAX_SSIDLEN 33
+#define MAX_CREDLEN 64
+#define IP_PORT 22
+
+typedef enum {
+ WiFi_11A = 0,
+ WiFi_11B,
+ WiFi_11G,
+ WiFi_11N,
+ WiFi_11AC,
+ WiFi_EOF = 999,
+} wifi_mode_e;
+
+typedef enum {
+ WiFi_24G = 0,
+ WiFi_5G,
+ WiFi_BOTH,
+ WiFi_FREQ_EOF
+} wifi_freq_e;
+
+typedef enum {
+ NONE_AUTH = 0,
+ WEP,
+ WPA_PSK,
+ WPA2_PSK
+} wifi_auth_type_e;
+
+typedef enum {
+ NONE_ENC = 0,
+ WEP_64,
+ WEP_128,
+ TKIP,
+ AES,
+ TKIP_AES
+} wifi_enc_type_e;
+
+typedef struct {
+ char ssid[MAX_SSIDLEN]; /**< ssid of the Enroller**/
+ char pwd[MAX_CREDLEN]; /**< pwd of the Enroller**/
+ wifi_auth_type_e authtype; /**< auth type of the Enroller**/
+ wifi_enc_type_e enctype; /**< encryption type of the Enroller**/
+ int discovery_channel; // samsung specific property
+} es_wifi_prov_data_s;
+
+typedef struct {
+ char language[THINGS_STRING_MAX_LENGTH];
+ char country[THINGS_STRING_MAX_LENGTH];
+ char datetime[THINGS_STRING_MAX_LENGTH];
+} es_dev_conf_prov_data_s;
+
+typedef struct {
+ char auth_code[THINGS_STRING_MAX_LENGTH];
+ char auth_provider[THINGS_STRING_MAX_LENGTH];
+ char ip[IP_PORT];
+ char port[IP_PORT];
+ char host_name[THINGS_STRING_MAX_DNSNAME];
+ char ci_server[THINGS_STRING_MAX_LENGTH];
+ char server_id[THINGS_STRING_MAX_LENGTH];
+ char client_id[THINGS_STRING_MAX_LENGTH];
+ char accesstoken[THINGS_STRING_MAX_LENGTH];
+ int actoken_type;
+ char refreshtoken[THINGS_STRING_MAX_LENGTH];
+ char uid[THINGS_STRING_MAX_LENGTH];
+} es_cloud_prov_data_s;
+
+typedef struct things_cloud_info_s {
+ char *domain; // mandatory ( You can choose one in both "domain" and "ip". )
+ char *ip;
+ char *port; // optional
+ char *auth_provider; // mandatory
+ char *access_token; // mandatory
+ char *access_token_type; // optional
+ char *refresh_token; // mandatory
+ char *user_id; // mandatory
+ char *client_id; // mandatory
+} things_cloud_info_s;
+
+#define MAX_DEVICEID_LEN 8
+#define MAX_RESOURCE_LEN 128
+#define MAX_URI_LEN 128
+#define MAX_QUERY_LEN 100
+#define MAX_ATTRIBUTE_LEN 64
+#define MAX_VALUETYPE_LEN 32
+#define MAX_ATTRVALUE_LEN 512
+#define MAX_KEY_LENGTH 50
+#define MAX_SPEC_LENGTH 7
+#define MAX_RID_LENGTH 10
+#define MAX_IT_CNT 5
+#define MAX_RT_CNT 10
+
+typedef struct things_info_s {
+ char device_id[MAX_DEVICEID_LEN];
+ char resource[MAX_RESOURCE_LEN];
+ char query[MAX_QUERY_LEN];
+ char attribute[MAX_ATTRIBUTE_LEN];
+ char type[MAX_VALUETYPE_LEN];
+ char value[MAX_ATTRVALUE_LEN];
+ char id[MAX_DEVICEID_LEN];
+
+ void *request_handle;
+ void *resource_handle;
+} things_info_s;
+
+typedef struct things_attribute_info_s {
+ char key[MAX_KEY_LENGTH];
+ char spec[MAX_SPEC_LENGTH];
+ int type;
+ bool mandatory;
+ int rw;
+} things_attribute_info_s;
+
+typedef struct things_resource_info_s {
+ char rid[MAX_RID_LENGTH];
+ char uri[MAX_URI_LEN];
+ char *interface_types[MAX_IT_CNT];
+ char *resource_types[MAX_RT_CNT];
+
+ int if_cnt;
+ int rt_cnt;
+ bool observable;
+ int policy;
+} things_resource_info_s;
+
+typedef enum {
+ RST_NEED_CONFIRM = 0,
+
+ RST_AUTO_RESET = 1,
+
+ RST_ENUM_EOF
+} things_es_enrollee_reset_e;
+
+typedef enum {
+ /**
+ * Default Abort State.
+ */
+ ABORT_INIT = 0,
+
+ /**
+ * Abort Status indicating cancel Reset Confirm.
+ */
+ ABORT_BEFORE_RESET_CONFIRM = 1,
+
+ /**
+ * Abort Status indicating cancel Security Confirm.
+ */
+ ABORT_BEFORE_SEC_CONFIRM = 2,
+
+ /**
+ * Abort Status indicating being security-process to delete Owned Security Data.
+ */
+ ABORT_BEFORE_DATA_PROVISIONING = 3
+} things_es_enrollee_abort_e;
+
+/**
+ * @brief Indicate enrollee and provisioning status. Provisioning status is shown in "provisioning
+ * status" property in provisioning resource.
+ */
+typedef enum {
+ /**
+ * Default state of the device
+ */
+ ES_STATE_INIT = 0,
+
+ /**
+ * Status indicating being connecting to target network
+ */
+ ES_STATE_CONNECTING_TO_ENROLLER,
+
+ /**
+ * Status indicating successful connection to target network
+ */
+ ES_STATE_CONNECTED_TO_ENROLLER,
+
+ /**
+ * Status indicating connection failure to target network
+ */
+ ES_STATE_FAILED_TO_CONNECT_TO_ENROLLER,
+
+ /**
+ * Status indicating being registering to cloud
+ */
+ ES_STATE_REGISTERING_TO_CLOUD,
+
+ /**
+ * Status indicating successful registration to cloud
+ */
+ ES_STATE_REGISTERED_TO_CLOUD,
+
+ /**
+ * Status indicating registration failure to cloud
+ */
+ ES_STATE_FAILED_TO_REGISTER_TO_CLOUD,
+
+ /**
+ * Status indicating being publishing resources to cloud
+ */
+ ES_STATE_PUBLISHING_RESOURCES_TO_CLOUD,
+
+ /**
+ * Status indicating successful resource publish to cloud
+ */
+ ES_STATE_PUBLISHED_RESOURCES_TO_CLOUD,
+
+ /**
+ * Status indicating resource publish failure to cloud
+ */
+ ES_STATE_FAILED_TO_PUBLISH_RESOURCES_TO_CLOUD,
+
+ /**
+ * Status indicating Logout from cloud
+ */
+ ES_STATE_LOGOUT_FROM_CLOUD,
+
+ /**
+ * End of Easy setup status
+ */
+ ES_STATE_EOF = 255
+} things_es_enrollee_state_e, things_prov_status_e, things_cloud_status_e;
+
+#endif /* _THINGS_TYPES_H_ */
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 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 <tinyara/config.h>
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <ifaddrs.h>
+#include <net/if.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <net/lwip/netif.h>
+#include <ocstack.h>
+#include "uuid/uuid.h"
+
+#if CONFIG_NSOCKET_DESCRIPTORS > 0
+extern struct netif *g_netdevices;
+#endif
+
+void uuid_generate_random(uuid_t out)
+{
+ int i = 0;
+
+ srand(time(NULL)); /* TODO: Need to check time(NULL) */
+ for (i = 0; i < sizeof(uuid_t); i++) { /* 16 means UUID size */
+ out[i] = rand() % 0xff;
+ }
+
+ out[6] = (out[6] & 0x0F) | 0x40;
+ out[8] = (out[8] & 0x3F) | 0x80;
+}
+
+void uuid_generate(uuid_t out)
+{
+ uuid_generate_random(out);
+}
+
+void uuid_unparse_lower(const uuid_t uu, char *out)
+{
+ snprintf(out, 37 /* UUID_STRING_SIZE */ ,
+ "%02x%02x%02x%02x-" "%02x%02x-" "%02x%02x-" "%02x%02x-" "%02x%02x%02x%02x%02x%02x", uu[0], uu[1], uu[2], uu[3], uu[4], uu[5], uu[6], uu[7], uu[8], uu[9], uu[10], uu[11], uu[12], uu[13], uu[14], uu[15]);
+}
+
+int getifaddrs(struct ifaddrs **ifap)
+{
+ static struct ifaddrs ifa;
+ static struct sockaddr_in addr, netmask;
+ uint8_t flags;
+
+ memset(&ifa, 0, sizeof(ifa));
+ memset(&addr, 0, sizeof(addr));
+ memset(&netmask, 0, sizeof(netmask));
+
+ struct netif *curr = g_netdevices;
+
+ netlib_get_ipv4addr(curr->d_ifname, &addr.sin_addr);
+ netlib_get_dripv4addr(curr->d_ifname, &netmask.sin_addr);
+ netlib_getifstatus(curr->d_ifname, &flags);
+
+ ifa.ifa_next = NULL;
+ ifa.ifa_name = curr->d_ifname;
+ ifa.ifa_flags = flags | IFF_RUNNING;
+ addr.sin_family = netmask.sin_family = AF_INET;
+ ifa.ifa_addr = (struct sockaddr *)&addr;
+ ifa.ifa_netmask = (struct sockaddr *)&netmask;
+
+ *ifap = &ifa;
+
+ return 0;
+}
+
+unsigned int if_nametoindex(const char *ifname)
+{
+ return 0; // TODO: Now supports only 1 device
+}
+
+const char *gai_strerror(int errcode)
+{
+ static const char *n_str = "null";
+ return n_str;
+}
--- /dev/null
+###########################################################################
+#
+# Copyright 2017 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.
+#
+###########################################################################
+
+CSRCS += cloud_connector.c cloud_evtpend.c cloud_manager.c
+
+DEPPATH += --dep-path src/st_things/things_stack/src/common/cloud
+VPATH += :src/st_things/things_stack/src/common/cloud
\ No newline at end of file
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 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.
+ *
+ ****************************************************************************/
+
+#define _BSD_SOURCE
+#define _POSIX_C_SOURCE 200809L
+#include <string.h>
+#include <stdlib.h>
+
+#include <netdb.h>
+#ifdef __USE_MISC
+#include <arpa/inet.h>
+#include <errno.h>
+#endif
+
+#include "octypes.h"
+#include "ocstack.h"
+#include "ocpayload.h"
+#include "rd_client.h"
+
+#include "things_malloc.h"
+#include "things_logger.h"
+#include "es_common.h"
+#include "cloud_connector.h"
+#include "things_wait_handler.h"
+#include "things_data_manager.h"
+#include <wifi_manager/wifi_manager.h>
+
+#define TAG "[cloud_cntor]"
+
+#define HOSTENT_INTERNAL_HEADER_SIZE 100
+
+/** Account Device-Profile publish URI.*/
+#define OC_RSRVD_ACCOUNT_DEVPROFILE_URI "/oic/account/profile/device"
+
+static OCRepPayload *make_dev_profile_payload(const st_device_s *dev_info);
+
+int CICheckDomain(const char *DomainName, char **pIP)
+{
+
+ char ipbuffer[20];
+ memset(ipbuffer, 0, 20);
+ char bytes[4];
+
+ int ip4_address = 0;
+
+ wifi_manager_result_e res = wifi_net_hostname_to_ip4(DomainName, &ip4_address);
+ if (res == 0) {
+ bytes[0] = ip4_address & 0XFF;
+ bytes[1] = (ip4_address >> 8) & 0XFF;
+ bytes[2] = (ip4_address >> 16) & 0XFF;
+ bytes[3] = (ip4_address >> 24) & 0XFF;
+ //54.85.39.78
+ //78.85.39.54
+
+ snprintf(ipbuffer, sizeof(ipbuffer), "%d.%d.%d.%d", bytes[0], bytes[1], bytes[2], bytes[3]);
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "DNS resolved IP for[%s] is =%s", DomainName, ipbuffer);
+
+ if (pIP != NULL) {
+ *pIP = strdup(ipbuffer);
+ }
+ } else {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, " Failed to get the IP, hard coding the ip");
+ snprintf(ipbuffer, sizeof(ipbuffer), "%s", "13.124.51.231");
+
+ usleep(500);
+ if (pIP != NULL) {
+ *pIP = strdup(ipbuffer);
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * @brief Entry Point for checking about internet & Cloud connection.
+ * @param DomainName wanted Domain-Name string to look-up IP address. (unit: const char*)
+ * @param pIP Variable pointer to store Founded IP address. (unit: char**)
+ * @return success : return 0 \n
+ * failure : return > 0
+ */
+int ci_connection_pre_check(const char *DomainName, char **pIP)
+{
+ int n_err = 0; // Success return value
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "DomainName=%s, pIP=0x%X", DomainName, pIP);
+
+ if (CICheckDomain("samsung.com", NULL) != 0) {
+ if (DomainName == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "AP is Not Connected to Internet.");
+ return -1;
+ }
+ }
+
+ if (DomainName != NULL) {
+ n_err = CICheckDomain(DomainName, pIP);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Found IP = %s, n_err = %d", *pIP, n_err);
+ }
+
+ return n_err;
+}
+
+/**
+ * @brief Send Sign-UP request to Cloud.
+ * @param host wanted Cloud address. (unit: const char*) \n
+ * Ex) coaps+tcp://123.123.123.123:1234
+ * @param device_id Identifier of device. (unit: const char*)
+ * @param event_data Data structure pointer for Cloud-Provisioning Data.
+ * @param response Call-Back function when cloud response against this request.
+ * @param timeoutHandler Call function when Time-out is occurred.
+ * @param timeout Data structure pointer for Time-out processing Data.
+ * @return success : OC_STACK_OK \n
+ * failure : other value
+ */
+OCStackResult things_cloud_signup(const char *host, const char *device_id, const es_cloud_prov_data_s *event_data, OCClientResponseHandler response, check_time_out_call_func timeoutHandler, timeout_s *timeout)
+{
+ OCDoHandle g_req_handle = NULL;
+ OCStackResult result = OC_STACK_ERROR;
+ char targetUri[MAX_URI_LENGTH * 2] = { 0, };
+ OCCallbackData cb_data;
+ OCRepPayload *registerPayload = NULL;
+
+ if (host == NULL || device_id == NULL || event_data == NULL || (event_data->accesstoken[0] == 0 && event_data->auth_code[0] == 0)) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "Invalid event_data.");
+ goto no_memory;
+ }
+
+ snprintf(targetUri, MAX_URI_LENGTH * 2, "%s%s", host, OC_RSRVD_ACCOUNT_URI);
+ THINGS_LOG_D(THINGS_INFO, TAG, "Signing up to : %s", targetUri);
+
+ memset(&cb_data, 0, sizeof(OCCallbackData));
+ cb_data.cb = response;
+ cb_data.cd = NULL;
+ cb_data.context = (void *)DEFAULT_CONTEXT_VALUE;
+
+ registerPayload = OCRepPayloadCreate();
+ if (!registerPayload) {
+ goto no_memory;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "di : %s", device_id);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "authprovider : %s", event_data->auth_provider);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "devicetype : resource_server");
+
+ OCRepPayloadSetPropString(registerPayload, "di", device_id);
+ OCRepPayloadSetPropString(registerPayload, "authprovider", event_data->auth_provider);
+ OCRepPayloadSetPropString(registerPayload, "devicetype", "resource_server");
+
+ if (event_data->accesstoken[0] != 0) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "accesstoken : %s", event_data->accesstoken);
+ OCRepPayloadSetPropString(registerPayload, "accesstoken", event_data->accesstoken);
+
+ if (event_data->uid[0] != 0) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "uid : %s", event_data->uid);
+ OCRepPayloadSetPropString(registerPayload, "uid", event_data->uid);
+ }
+ } else {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "authcode : %s", event_data->auth_code);
+ OCRepPayloadSetPropString(registerPayload, "authcode", event_data->auth_code);
+ }
+
+ if (event_data->client_id[0] != 0) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "clientid : %s", event_data->client_id);
+ OCRepPayloadSetPropString(registerPayload, OC_RSRVD_ES_CLIENTID, event_data->client_id);
+ }
+
+ THINGS_LOG_D(THINGS_INFO, TAG, "OCToCATransportFlags(CT_ADAPTER_TCP)");
+
+#if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
+ //CASelectCipherSuite(0x35, (1 << 4));
+#endif
+
+ if (is_empty_request_handle() == true) {
+ result = OCDoResource(&g_req_handle, OC_REST_POST, targetUri, NULL, (OCPayload *) registerPayload, CT_ADAPTER_TCP, OC_LOW_QOS, &cb_data, NULL, 0);
+
+ if (result == OC_STACK_OK && timeoutHandler != NULL) {
+ if (add_request_handle(g_req_handle) == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "[Error] ReqHandles array space is small.");
+ goto no_memory;
+ }
+
+ create_time_out_process(g_req_handle, timeoutHandler, timeout);
+ }
+ }
+
+ return result;
+
+no_memory:
+ OCRepPayloadDestroy(registerPayload);
+ return OC_STACK_NO_MEMORY;
+}
+
+/**
+ * @brief Send Sign-IN request to Cloud.
+ * @param host wanted Cloud address. (unit: const char*) \n
+ * Ex) coaps+tcp://123.123.123.123:1234
+ * @param uId Identifier of User. (unit: const char*)
+ * @param device_id Identifier of device. (unit: const char*)
+ * @param accesstoken received access-token from Cloud.
+ * @param response Call-Back function when cloud response against this request.
+ * @param timeoutHandler Call function when Time-out is occurred.
+ * @param timeout Data structure pointer for Time-out processing Data.
+ * @return success : OC_STACK_OK \n
+ * failure : other value
+ */
+OCStackResult things_cloud_session(const char *host, const char *uId, const char *device_id, const char *accesstoken, bool isLogin, OCClientResponseHandler response, check_time_out_call_func timeoutHandler, timeout_s *timeout)
+{
+ OCDoHandle g_req_handle = NULL;
+ OCStackResult result = OC_STACK_ERROR;
+ char targetUri[MAX_URI_LENGTH * 2] = { 0, };
+ char *coreVer = NULL;
+ char *IoTivityVer = NULL;
+
+ if (accesstoken == NULL || accesstoken[0] == 0) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "accesstoken is invalid.(0x%X)", accesstoken);
+ return OC_STACK_ERROR;
+ }
+
+ snprintf(targetUri, MAX_URI_LENGTH * 2, "%s%s", host, OC_RSRVD_ACCOUNT_SESSION_URI);
+
+ THINGS_LOG_D(THINGS_INFO, TAG, "Initiate Session with : %s", targetUri);
+
+ OCCallbackData cb_data;
+ memset(&cb_data, 0, sizeof(OCCallbackData));
+ cb_data.cb = response;
+ cb_data.cd = NULL;
+ cb_data.context = (void *)DEFAULT_CONTEXT_VALUE;
+
+ OCRepPayload *loginoutPayload = OCRepPayloadCreate();
+ if (!loginoutPayload) {
+ goto no_memory;
+ }
+
+ if (OCGetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_SPEC_VERSION, (void **)&coreVer) != OC_STACK_OK || (IoTivityVer = strdup(IOTIVITY_VERSION)) == NULL)
+// OCGetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_PLATFORM_VERSION, (void**)&IoTivityVer) != OC_STACK_OK )
+ {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "Getting Core_Spec_Ver or IoTivity_Ver is failed.");
+ goto no_memory;
+ }
+
+ THINGS_LOG_D(THINGS_INFO, TAG, "coreversion : %s", coreVer);
+ THINGS_LOG_D(THINGS_INFO, TAG, "verticalversion : %s", IoTivityVer);
+
+ if (uId != NULL) {
+ OCRepPayloadSetPropString(loginoutPayload, KEY_ID_USER, uId);
+ }
+ OCRepPayloadSetPropString(loginoutPayload, KEY_ID_DEVICE, device_id);
+ OCRepPayloadSetPropString(loginoutPayload, KEY_TOKEN_ACCESS, accesstoken);
+ OCRepPayloadSetPropBool(loginoutPayload, KEY_LOGINOUT, isLogin);
+ OCRepPayloadSetPropString(loginoutPayload, KEY_ICORE_VER, coreVer);
+ OCRepPayloadSetPropString(loginoutPayload, KEY_IOTIVITY_VER, IoTivityVer);
+
+#if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
+ //CASelectCipherSuite(0x35, (1 << 4));
+#endif
+
+ if (is_empty_request_handle() == true) {
+ result = OCDoResource(&g_req_handle, OC_REST_POST, targetUri, NULL, (OCPayload *) loginoutPayload, CT_ADAPTER_TCP, OC_LOW_QOS, &cb_data, NULL, 0);
+
+ if (result == OC_STACK_OK && timeoutHandler != NULL) {
+ if (add_request_handle(g_req_handle) == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "[Error] ReqHandles array space is small.");
+ goto no_memory;
+ }
+
+ create_time_out_process(g_req_handle, timeoutHandler, timeout);
+ }
+ }
+
+ if (IoTivityVer) {
+ things_free(IoTivityVer);
+ IoTivityVer = NULL;
+ }
+ if (coreVer) {
+ things_free(coreVer);
+ coreVer = NULL;
+ }
+ return result;
+
+no_memory:
+ if (IoTivityVer) {
+ things_free(IoTivityVer);
+ IoTivityVer = NULL;
+ }
+ if (coreVer) {
+ things_free(coreVer);
+ coreVer = NULL;
+ }
+ OCRepPayloadDestroy(loginoutPayload);
+ return OC_STACK_NO_MEMORY;
+}
+
+/**
+ * @brief Send Resources Publish request to Cloud.
+ * @param host wanted Cloud address. (unit: const char*)\n
+ * Ex) coaps+tcp://123.123.123.123:1234
+ * @param list Resource List pointer for Publishing to Cloud.
+ * @param length Count of Resource in Resource List(list).
+ * @param response Call-Back function when cloud response against this request.
+ * @param timeoutHandler Call function when Time-out is occurred.
+ * @param timeout Data structure pointer for Time-out processing Data.
+ * @return success : OC_STACK_OK \n
+ * failure : other value
+ */
+OCStackResult things_cloud_rsc_publish(char *host, things_resource_s **list, int length, OCClientResponseHandler response, check_time_out_call_func timeoutHandler, timeout_s *timeout)
+{
+ OCStackResult result = OC_STACK_ERROR;
+ THINGS_LOG_D(THINGS_INFO, TAG, "Resource Publish Start.");
+
+ OCDoHandle g_req_handle = NULL;
+ OCCallbackData cb_data;
+ cb_data.cb = response;
+ cb_data.context = (void *)DEFAULT_CONTEXT_VALUE;
+ cb_data.cd = NULL;
+
+ OCResourceHandle resourceHandles[length + 2];
+
+ THINGS_LOG_D(THINGS_INFO, TAG, "Publishing [%d] number of resources ", length);
+ int iter = 0;
+ for (iter = 0; iter < length; iter++) {
+ resourceHandles[iter] = list[iter]->resource_handle;
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "URI : %s ", list[iter]->uri);
+ }
+
+ uint8_t numResource = 0;
+ OCGetNumberOfResources(&numResource);
+ if (numResource > 0) {
+ for (uint8_t index = 0; index < numResource; index++) {
+ OCResourceHandle handle = OCGetResourceHandle(index);
+
+ const char *uri = OCGetResourceUri(handle);
+
+ if (0 == strncmp(uri, OC_RSRVD_DEVICE_URI, strlen(OC_RSRVD_DEVICE_URI))
+ || 0 == strncmp(uri, OC_RSRVD_PLATFORM_URI, strlen(OC_RSRVD_PLATFORM_URI))) {
+ resourceHandles[iter++] = handle;
+ }
+ }
+ }
+
+ if (is_empty_request_handle() == true) {
+ result = OCRDPublish(&g_req_handle, host, CT_ADAPTER_TCP, resourceHandles, iter, &cb_data, OC_LOW_QOS);
+
+ if (result == OC_STACK_OK && timeoutHandler != NULL) {
+ if (add_request_handle(g_req_handle) == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "[Error] ReqHandles array space is small.");
+ return OC_STACK_ERROR;
+ }
+
+ create_time_out_process(g_req_handle, timeoutHandler, timeout);
+ }
+ }
+
+ return result;
+}
+
+OCStackResult things_cloud_rsc_publish_with_device_id(char *host, const char *id, things_resource_s **list, int length, OCClientResponseHandler response, check_time_out_call_func timeoutHandler, timeout_s *timeout)
+{
+ OCStackResult result = OC_STACK_ERROR;
+ THINGS_LOG_D(THINGS_INFO, TAG, "Resource Publish Start.");
+
+ OCDoHandle g_req_handle = NULL;
+ OCCallbackData cb_data;
+ cb_data.cb = response;
+ cb_data.context = (void *)DEFAULT_CONTEXT_VALUE;
+ cb_data.cd = NULL;
+
+ OCResourceHandle resourceHandles[length + 2];
+
+ THINGS_LOG_V(THINGS_INFO, TAG, "Device ID ==> %s ", id);
+ THINGS_LOG_V(THINGS_INFO, TAG, "Publishing [%d] number of resources ", length);
+
+ int iter = 0;
+ for (iter = 0; iter < length; iter++) {
+ resourceHandles[iter] = list[iter]->resource_handle;
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "URI : %s ", list[iter]->uri);
+ }
+
+ if (iter > 0) {
+ result = OCRDPublishWithDeviceId(&g_req_handle, host, id, CT_ADAPTER_TCP, resourceHandles, iter, &cb_data, OC_LOW_QOS);
+ }
+// if(result == OC_STACK_OK && timeoutHandler != NULL )
+// {
+// if( add_request_handle(g_req_handle) == NULL )
+// {
+// THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "[Error] ReqHandles array space is small.");
+// return OC_STACK_ERROR;
+// }
+//
+// create_time_out_process(g_req_handle, timeoutHandler, timeout);
+// }
+
+ return result;
+}
+
+/**
+ * @brief Send Dev-Profile Publish request to Cloud.
+ * @param host wanted Cloud address. (unit: const char*)\n
+ * Ex) coaps+tcp://123.123.123.123:1234
+ * @param response Call-Back function when cloud response against this request.
+ * @param timeoutHandler Call function when Time-out is occurred.
+ * @param timeout Data structure pointer for Time-out processing Data.
+ * @return success : OC_STACK_OK \n
+ * failure : other value
+ */
+OCStackResult things_cloud_dev_profile_publish(char *host, OCClientResponseHandler response, check_time_out_call_func timeoutHandler, timeout_s *timeout)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Device-profile Publish Start.");
+
+ long devCnt = 0;
+ st_device_s *dev_info = NULL;
+ int cntArrayPayload = 0;
+ OCRepPayload **arrayPayload = NULL;
+ OCRepPayload *payload = NULL;
+ OCCallbackData cb_data;
+ OCDoHandle g_req_handle = NULL;
+ OCStackResult result = OC_STACK_ERROR;
+ char targetUri[MAX_URI_LENGTH * 2] = { 0, };
+ char *coreVer = NULL;
+ char *IoTivityVer = NULL;
+
+ if ((devCnt = dm_get_num_of_dev_cnt()) < 1) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Not exist device to publish profile-Info of Device.");
+ return OC_STACK_ERROR;
+ }
+
+ snprintf(targetUri, MAX_URI_LENGTH * 2, "%s%s", host, OC_RSRVD_ACCOUNT_DEVPROFILE_URI);
+
+ THINGS_LOG_D(THINGS_INFO, TAG, "Initiate DevProfile with : %s", targetUri);
+
+ cb_data.cb = response;
+ cb_data.context = (void *)DEFAULT_CONTEXT_VALUE;
+ cb_data.cd = NULL;
+
+ payload = OCRepPayloadCreate();
+ if (!payload) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "[Error] memory allocation is failed.(payload)");
+ goto no_memory;
+ }
+
+ if ((arrayPayload = (OCRepPayload **) things_malloc(sizeof(OCRepPayload *) * devCnt)) == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "[Error] memory allocation is failed.(arrayPayload)");
+ goto no_memory;
+ }
+ // Add All-device-info
+ for (unsigned long i = 0; i < devCnt; i++) {
+ if ((dev_info = dm_get_info_of_dev(i)) == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "[Error] device info structure is NULL.(seq=%d)", i);
+ goto no_memory;
+ }
+
+ if (dev_info->is_physical == 1) {
+ if ((arrayPayload[cntArrayPayload] = make_dev_profile_payload(dev_info)) == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "It's failed making payload of Device-Info.(seq=%d)", cntArrayPayload);
+ goto no_memory;
+ }
+ cntArrayPayload++;
+ }
+ }
+
+ if (cntArrayPayload < 1) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "[Error] pysical device is not exist. So, Can not Sending request for Device-Profile.");
+ goto no_memory;
+ }
+
+ size_t dimensions[MAX_REP_ARRAY_DEPTH] = { cntArrayPayload, 0, 0 };
+ OCRepPayloadSetPropObjectArray(payload, "devices", arrayPayload, dimensions);
+
+ if (is_empty_request_handle() == true) {
+ result = OCDoResource(&g_req_handle, OC_REST_POST, targetUri, NULL, (OCPayload *) payload, CT_ADAPTER_TCP, OC_LOW_QOS, &cb_data, NULL, 0);
+
+ if (result == OC_STACK_OK && timeoutHandler != NULL) {
+ if (add_request_handle((OCDoHandle) 1) == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "[Error] ReqHandles array space is small.");
+ /*for SVACE Warning */
+ if (arrayPayload) {
+ for (int i = 0; i < cntArrayPayload; i++) {
+ OCPayloadDestroy((OCPayload *) arrayPayload[i]);
+ }
+ things_free(arrayPayload);
+ arrayPayload = NULL;
+ }
+ return OC_STACK_ERROR;
+ }
+
+ create_time_out_process((OCDoHandle) 1, timeoutHandler, timeout);
+ }
+ }
+
+ if (arrayPayload) {
+ for (int i = 0; i < cntArrayPayload; i++) {
+ OCPayloadDestroy((OCPayload *) arrayPayload[i]);
+ }
+ things_free(arrayPayload);
+ arrayPayload = NULL;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Exit. -Success-");
+ return result;
+
+no_memory:
+
+ if (arrayPayload) {
+ for (int i = 0; i < cntArrayPayload; i++) {
+ OCPayloadDestroy((OCPayload *) arrayPayload[i]);
+ }
+ things_free(arrayPayload);
+ arrayPayload = NULL;
+ }
+ OCRepPayloadDestroy(payload);
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Exit. -Fail-");
+ return OC_STACK_NO_MEMORY;
+}
+
+/**
+ * @brief Send Refresh access-token request to Cloud.\n
+ * Set should call refresh before expiresin of refresh-token or when receive 4.01 during sign-in
+ * @param host wanted Cloud address. (unit: const char*) \n
+ * Ex) coaps+tcp://123.123.123.123:1234
+ * @param uId Identifier of User.
+ * @param device_id Identifier of Device.
+ * @param refreshtoken Token for refreshing access-token from Cloud.
+ * @param response Call-Back function when cloud response against this request.
+ * @return success : OC_STACK_OK \n
+ * failure : other value
+ */
+OCStackResult things_cloud_refresh(const char *host, const char *uId, const char *device_id, const char *refreshtoken, OCClientResponseHandler response)
+{
+ char targetUri[MAX_URI_LENGTH * 2] = { 0, };
+ snprintf(targetUri, MAX_URI_LENGTH * 2, "%s%s", host, OC_RSRVD_ACCOUNT_TOKEN_REFRESH_URI);
+
+ OCCallbackData cb_data;
+ memset(&cb_data, 0, sizeof(OCCallbackData));
+ cb_data.cb = response;
+ cb_data.cd = NULL;
+ cb_data.context = (void *)DEFAULT_CONTEXT_VALUE;
+
+ OCRepPayload *refreshPayload = OCRepPayloadCreate();
+ if (!refreshPayload) {
+ goto no_memory;
+ }
+
+ if (uId != NULL) {
+ OCRepPayloadSetPropString(refreshPayload, KEY_ID_USER, uId);
+ }
+ OCRepPayloadSetPropString(refreshPayload, KEY_ID_DEVICE, device_id);
+ OCRepPayloadSetPropString(refreshPayload, KEY_TYPE_GRANT, VALUE_TYPE_GRANT_TOKEN);
+ OCRepPayloadSetPropString(refreshPayload, KEY_TOKEN_ACCESS_REFRESH, refreshtoken);
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "targetURI =%s", targetUri);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "uid =%s", uId);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "di =%s", device_id);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "granttype =%s", VALUE_TYPE_GRANT_TOKEN);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "refreshtoken =%s", refreshtoken);
+
+#if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
+ //CASelectCipherSuite(0x35, (1 << 4));
+#endif
+
+ return OCDoResource(NULL, OC_REST_POST, targetUri, NULL, (OCPayload *) refreshPayload, CT_ADAPTER_TCP, OC_LOW_QOS, &cb_data, NULL, 0);
+
+no_memory:
+ OCRepPayloadDestroy(refreshPayload);
+ return OC_STACK_NO_MEMORY;
+}
+
+OCStackResult things_cloud_topic_publish_topic(const char *host, const char *topic, OCRepPayload *message, OCClientResponseHandler response)
+{
+ char targetUri[MAX_URI_LENGTH * 2] = { 0, };
+
+ snprintf(targetUri, MAX_URI_LENGTH * 2, "%s%s", host, topic);
+
+ OCCallbackData cb_data;
+ memset(&cb_data, 0, sizeof(OCCallbackData));
+ cb_data.cb = response;
+ cb_data.cd = NULL;
+ cb_data.context = (void *)DEFAULT_CONTEXT_VALUE;
+
+ if (!message) {
+ goto no_memory;
+ }
+#if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
+ //CASelectCipherSuite(0x35, (1 << 4));
+#endif
+ return OCDoResource(NULL, OC_REST_POST, targetUri, NULL, (OCPayload *) message, CT_ADAPTER_TCP, OC_LOW_QOS, &cb_data, NULL, 0);
+
+no_memory:
+ OCRepPayloadDestroy(message);
+ return OC_STACK_NO_MEMORY;
+}
+
+static OCRepPayload *make_dev_profile_payload(const st_device_s *dev_info)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Enter.");
+
+ bool res = false;
+ char *manuFactory = NULL;
+ char *coreVer = NULL;
+ char *IoTivityVer = NULL;
+ OCRepPayload *payload = NULL;
+
+ if (dev_info == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "input argument is invalid.(dev_info is null)");
+ return NULL;
+ }
+
+ if ((payload = OCRepPayloadCreate()) == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "memory allocation is failed.(payload)");
+ return NULL;
+ }
+
+ if (OCGetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_SPEC_VERSION, (void **)&coreVer) != OC_STACK_OK) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Getting CoreVersion of IoTivity is failed.");
+ goto GOTO_OUT;
+ }
+
+ IoTivityVer = strdup(IOTIVITY_VERSION);
+
+ if (OCGetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_MFG_NAME, (void **)&manuFactory) != OC_STACK_OK) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Getting manufacturer-name is failed.");
+ goto GOTO_OUT;
+ }
+
+ OCRepPayloadSetPropString(payload, "di", dev_info->device_id);
+ OCRepPayloadSetPropString(payload, "n", dev_info->name);
+ OCRepPayloadSetPropString(payload, "icv", coreVer);
+ OCRepPayloadSetPropString(payload, "dmv", IoTivityVer);
+// OCRepPayloadSetPropString(payload, "vrv", );
+ OCRepPayloadSetPropString(payload, "rt", dev_info->type);
+ OCRepPayloadSetPropString(payload, "mnmn", manuFactory);
+ OCRepPayloadSetPropString(payload, "mnmo", dev_info->model_num);
+ OCRepPayloadSetPropString(payload, "mnpv", dev_info->ver_p);
+ OCRepPayloadSetPropString(payload, "mnos", dev_info->ver_os);
+ OCRepPayloadSetPropString(payload, "mnhw", dev_info->ver_hw);
+ OCRepPayloadSetPropString(payload, "mnfv", dev_info->ver_fw);
+ OCRepPayloadSetPropString(payload, "vid", dev_info->vender_id);
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "di = %s", dev_info->device_id);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "n = %s", dev_info->name);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "icv = %s", coreVer);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "dmv = %s", IoTivityVer);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "rt = %s", dev_info->type);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "mnmn = %s", manuFactory);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "mnmo = %s", dev_info->model_num);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "mnpv = %s", dev_info->ver_p);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "mnos = %s", dev_info->ver_os);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "mnhw = %s", dev_info->ver_hw);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "mnfv = %s", dev_info->ver_fw);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "vid = %s", dev_info->vender_id);
+
+ res = true;
+
+GOTO_OUT:
+ if (coreVer) {
+ things_free(coreVer);
+ coreVer = NULL;
+ }
+
+ if (IoTivityVer) {
+ things_free(IoTivityVer);
+ IoTivityVer = NULL;
+ }
+
+ if (manuFactory) {
+ things_free(manuFactory);
+ manuFactory = NULL;
+ }
+
+ if (res == false) {
+ OCPayloadDestroy((OCPayload *) payload);
+ payload = NULL;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Exit. payload=0x%X", payload);
+ return payload;
+}
--- /dev/null
+/* ****************************************************************
+ *
+ * Copyright 2017 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 <unistd.h>
+#include <pthread.h>
+
+#include "things_logger.h"
+#include "cloud_evtpend.h"
+#include "resource_handler.h"
+
+#define TAG "[cloudevtpend]"
+
+static es_cloud_pending_event_s pending_event = { false, false, false, };
+
+static pthread_mutex_t g_pending_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+void ci_cp_init_event_pend(void)
+{
+ pthread_mutex_lock(&g_pending_mutex);
+ pending_event.exist = false;
+ pending_event.is_there_ci_prov = false;
+ pending_event.using_count = 0;
+ init_es_cloud_prov_data(&pending_event.event);
+ pthread_mutex_unlock(&g_pending_mutex);
+}
+
+es_cloud_prov_data_s *ci_cp_get_pended_data(void) // [GET] If there pending-Data, then return point of Data.
+{
+ es_cloud_prov_data_s *p_event = NULL;
+
+ pthread_mutex_lock(&g_pending_mutex);
+ if (pending_event.exist == true) {
+ p_event = &pending_event.event;
+ }
+ pthread_mutex_unlock(&g_pending_mutex);
+
+ return p_event;
+}
+
+bool ci_cp_get_is_there_cp(void) // [GET] return is_there_ci_prov value.
+{
+ bool is_there = false;
+
+ pthread_mutex_lock(&g_pending_mutex);
+ is_there = pending_event.is_there_ci_prov;
+ pthread_mutex_unlock(&g_pending_mutex);
+
+ return is_there;
+}
+
+bool ci_cp_cas_is_there_cp_if_false(void) // [CAS] If is_there_ci_prov value is false, then set true and return is_there_ci_prov value.
+{
+ bool is_there = false;
+
+ pthread_mutex_lock(&g_pending_mutex);
+ is_there = pending_event.is_there_ci_prov;
+ if (is_there == false) {
+ pending_event.is_there_ci_prov = true;
+ }
+ pthread_mutex_unlock(&g_pending_mutex);
+
+ return is_there;
+}
+
+void ci_cp_del_pended_data(void) // [SET] Setting false to Flag about existing of pending-Data.
+{
+ bool b_continue = true;
+
+ while (b_continue) {
+ pthread_mutex_lock(&g_pending_mutex);
+ if (pending_event.exist == false || pending_event.using_count == 0) {
+ pending_event.exist = false;
+ b_continue = false;
+ }
+ pthread_mutex_unlock(&g_pending_mutex);
+
+ if (b_continue == true) {
+ usleep(100000); // 0.1 seconds delay.
+ }
+ }
+}
+
+void ci_cp_del_is_there_cp(void) // [SET] Setting false to Flag about existing of new CP-data.
+{
+ pthread_mutex_lock(&g_pending_mutex);
+ pending_event.is_there_ci_prov = false;
+ pthread_mutex_unlock(&g_pending_mutex);
+}
+
+int ci_cp_pend_event_data(es_cloud_prov_data_s *event_data) // [SET] Setting true all Flag and Store Event-Data to pending repo.
+{
+ if (event_data == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Event Data is NULL.");
+ return 0;
+ }
+
+ bool b_continue = true;
+
+ while (b_continue) {
+ pthread_mutex_lock(&g_pending_mutex);
+ if (pending_event.using_count == 0) {
+ pending_event.exist = true;
+ pending_event.is_there_ci_prov = true;
+
+ if (event_data != &pending_event.event) {
+ clone_es_cloud_prov_data(&pending_event.event, event_data);
+ }
+ b_continue = false;
+ }
+ pthread_mutex_unlock(&g_pending_mutex);
+
+ if (b_continue == true) {
+ usleep(100000); // 0.1 seconds delay.
+ }
+ }
+
+ return 1;
+}
+
+int ci_cp_enter_pend_data_block(void)
+{
+ int using_cnt = 0;
+
+ pthread_mutex_lock(&g_pending_mutex);
+ pending_event.using_count++;
+ using_cnt = pending_event.using_count;
+ pthread_mutex_unlock(&g_pending_mutex);
+
+ return using_cnt;
+}
+
+int ci_cp_release_penddata_block(void)
+{
+ int using_cnt = 0;
+
+ pthread_mutex_lock(&g_pending_mutex);
+ pending_event.using_count--;
+ using_cnt = pending_event.using_count;
+ pthread_mutex_unlock(&g_pending_mutex);
+
+ return using_cnt;
+}
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 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.
+ *
+ ****************************************************************************/
+
+#define _POSIX_C_SOURCE 200809L
+#define _BSD_SOURCE
+
+#include <unistd.h>
+#include <string.h>
+#include <pthread.h>
+#include <time.h>
+
+#include "ocstack.h"
+#include "ocpayload.h"
+#include "oic_malloc.h"
+#include "cautilinterface.h"
+
+#include "es_common.h"
+#include "cacommon.h"
+#include "things_string_util.h"
+#include "things_def.h"
+#include "things_logger.h"
+#include "things_malloc.h"
+#include "things_data_manager.h"
+#include "cloud_connector.h"
+#include "cloud_manager.h"
+#include "cloud_evtpend.h"
+#include "things_types.h"
+#include "easysetup.h"
+#include "easysetup_manager.h"
+#include "resource_handler.h"
+#include "../utils/inc/things_network.h"
+#include "NSProviderInterface.h"
+#include "things_ping.h"
+#include "things_thread.h"
+#include "things_security_manager.h"
+#include "things_rtos_util.h"
+
+#define DEFAULT_CI_HOST "52.40.216.160:5683" //!< Non Security Cloud IPv4:Port. Not used in common.
+#define MAX_CI_ADDRESS 256
+#define RESOURCE_DISCOVERY_QUERY "/oic/res"
+#define RESOURCE_DISCOVERY_QUERY_DI "/oic/res?di="
+
+#define ERR_UPPER_UNIT 10000 //!< Unit of Network-State for Cloud Error-Code
+#define MAX_SIGNUP_SENDNUM 1 //!< Max re-transmission count of send_cnt_sign_up variable.
+#define MAX_RETRY_RSCPUBLISH 10 //!< Max re-transmission count of retranslate_rsc_publish_cnt variable.
+
+#define TAG "[cloudmnger]"
+
+typedef void *(*pthread_func_type)(void *);
+
+/*! Cloud Session Management enum. */
+typedef enum {
+ CISESS_NULL = -2,
+ CISESS_APDISCON = -1, //!< -1 : AP Disconnected.
+ CISESS_STOP = 0, //!< 0 : Cloud Connection Disconnected & AP Connected.
+ CISESS_BUSY = 1, //!< 1 : Cloud Connection Connecting & Connected. (Busy)
+ CISESS_STOP_TRIGGER = 2, //!< 2 : Triggered for Cloud Connection disconnect.
+ CISESS_SIGNOUT = 3 //!< 3 : Sign-Out from Cloud.
+} ci_session_level_e;
+
+/*! Provisioned Data + Time-Out Data. */
+typedef struct es_cloud_event_timeout_s {
+ timeout_s timeOut; //!< Time-Out value(unit: seconds)
+ es_cloud_prov_data_s event; //!< Cloud Provisioned Data
+} es_cloud_event_timeout_s;
+
+volatile static ci_session_level_e g_qis_cloud_thread_running = CISESS_APDISCON; //!< Variable for managing Cloud session.(No cached)
+
+static int send_cnt_sign_up = 0; //!< Counter for Sign-UP re-transmission process.
+static int retranslate_rsc_publish_cnt = 0; //!< Counter for Resource-Publish re-transmission process.
+
+static pthread_mutex_t g_es_mutex = PTHREAD_MUTEX_INITIALIZER; //!< Mutex variable for thread-safety of start_ci_connection().
+static pthread_mutex_t g_es_tcp_session_mutex = PTHREAD_MUTEX_INITIALIZER; //!< Mutex variable for thread-safety of ci_retry_stop_by_tcp_cb().
+
+static char g_cloud_ip[IP_PORT] = { 0, }; //!< Current Connected Cloud Ipv4 address.
+static char g_cloud_port[IP_PORT] = { 0, }; //!< Current Connected Cloud Port number.
+static char g_cloud_address[MAX_CI_ADDRESS] = { 0, }; //!< Current Connected Cloud Address.
+
+static es_cloud_signup_s *signed_up_data = NULL;
+
+static things_server_builder_s *g_server_builder = NULL; //!< Server-Builder pointer to get Resource List.
+static things_resource_s **g_resource_lists = NULL; //!< Resource List pointer to be publishing resources to Cloud.
+static int g_len = 0; //!< EA of Resources in "g_resource_lists" variable.
+
+static things_cloud_con_result_func_type things_res_cb_function = NULL; //!< call-back Function pointer : it's called when finish Cloud-Connection.
+
+static OCStackResult publish_resource_main_dev_into_cloud(things_resource_s **list, int length, timeout_s *timeout);
+static int cloud_retry_sign_up(es_cloud_prov_data_s *event_data, timeout_s *timeout);
+static char *make_cloud_address(char *ip, char *port, const char *ci_addr);
+static void cloud_request_retry_trigger(timeout_s *timeout);
+static es_cloud_prov_data_s *if_failed_then_retry(OCDoHandle handle, OCStackResult result, int *n_err);
+static void force_session_stop(ci_session_level_e state);
+static int es_cloud_state_set_and_notify(things_cloud_status_e state, es_error_code_e es_err, OCClientResponse *response, ci_error_code_e *ci_err);
+static int get_cloud_code(OCClientResponse *response, OCMethod method, ci_error_code_e *err);
+static CAResponseResult_t things_result_to_network_result(OCStackResult oc_code, OCMethod method);
+static char *make_ip_port(char *p_ip, char *p_port);
+static es_cloud_event_timeout_s *clone_data_add_timeout(es_cloud_prov_data_s *cloud_data, timeout_s *timeout);
+static void ci_finish_cloud_con(int result);
+static void publish_dev_profile_into_cloud(timeout_s *timeout);
+
+static void *handle_signup_timeout(timeout_s *timeout)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Sign-UP is Time-Out.");
+
+ es_cloud_prov_data_s *pend_cloud_data = NULL;
+
+ if (timeout == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "[Error] timeout is NULL.");
+ return 0;
+ }
+
+ send_cnt_sign_up++;
+
+ if (send_cnt_sign_up <= MAX_SIGNUP_SENDNUM) {
+ if ((pend_cloud_data = ci_cp_get_pended_data()) != NULL) {
+ timeout->cur_counter = timeout->cur_num;
+ THINGS_LOG_V(THINGS_INFO, TAG, "Sign-UP Request Send is re-tryed(%d).", send_cnt_sign_up);
+ if (cloud_retry_sign_up(pend_cloud_data, timeout) == 0) {
+ send_cnt_sign_up = MAX_SIGNUP_SENDNUM + 1;
+ }
+ } else {
+ send_cnt_sign_up = MAX_SIGNUP_SENDNUM + 1;
+ }
+ }
+
+ if (send_cnt_sign_up > MAX_SIGNUP_SENDNUM) {
+ THINGS_LOG_V(THINGS_INFO, TAG, "Sign-UP Re-Try Request Send is failed.");
+
+ oic_ping_unset_mask(g_cloud_ip, PING_ST_ISCLOUD | PING_ST_SIGNIN);
+
+ if (es_cloud_state_set_and_notify(ES_STATE_FAILED_TO_REGISTER_TO_CLOUD, ES_ERRCODE_NO_RESPONSE_FROM_CLOUD_SERVER, NULL, NULL) != 0) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "StateAndNotify is failed.");
+ }
+
+ force_session_stop(CISESS_NULL);
+ send_cnt_sign_up = 0;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Exit.");
+ return 0;
+}
+
+static void *handle_signin_timeout(timeout_s *timeout)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Sign-IN is Time-Out.");
+
+ if (timeout == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "[Error] timeout is NULL.");
+ return 0;
+ }
+
+ int thres_hold = timeout->ori_num * 10; // PDF thres_hold 0.2 --> 5
+
+ if (timeout->cur_num < thres_hold && (timeout->cur_num = (int)next_time_out((long long)timeout->ori_num, (long long)timeout->cur_num)) != -1) {
+ if (timeout->cur_num > thres_hold) {
+ timeout->cur_num = thres_hold;
+ }
+ timeout->cur_counter = timeout->cur_num;
+
+ THINGS_LOG_V(THINGS_INFO, TAG, "Sign-IN Request Send is re-tryed. (PDF interval:%d)", timeout->cur_num);
+
+ force_session_stop(CISESS_SIGNOUT);
+ cloud_request_retry_trigger(timeout);
+ } else {
+ THINGS_LOG_V(THINGS_INFO, TAG, "Sign-IN Re-Try Request Send is failed.");
+
+ oic_ping_unset_mask(g_cloud_ip, PING_ST_ISCLOUD | PING_ST_SIGNIN);
+
+ if (es_cloud_state_set_and_notify(ES_STATE_FAILED_TO_REGISTER_TO_CLOUD, ES_ERRCODE_NO_RESPONSE_FROM_CLOUD_SERVER, NULL, NULL) != 0) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "StateAndNotify is failed.");
+ }
+
+ force_session_stop(CISESS_NULL);
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Exit.");
+ return 0;
+}
+
+static void *handle_publish_timeout(timeout_s *timeout)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Resource-Publish is Time-Out.");
+
+ if (timeout == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "[Error] timeout is NULL.");
+ return 0;
+ }
+
+ int thres_hold = timeout->ori_num * 5; // PDF thres_hold 0.2 --> 5
+
+ if (timeout->cur_num < thres_hold && (timeout->cur_num = (int)next_time_out((long long)timeout->ori_num, (long long)timeout->cur_num)) != -1) {
+ if (timeout->cur_num > thres_hold) {
+ timeout->cur_num = thres_hold;
+ }
+ timeout->cur_counter = timeout->cur_num;
+
+ THINGS_LOG_V(THINGS_INFO, TAG, "RSC_Publish Request Send is re-tryed. (PDF interval:%d)", timeout->cur_num);
+ publish_resource_into_cloud(RSC_PUB_MAIN_ONLY, timeout);
+ } else {
+ THINGS_LOG_V(THINGS_INFO, TAG, "Resource-Publish Re-Try Request Sending is failed.");
+
+ if (es_cloud_state_set_and_notify(ES_STATE_FAILED_TO_PUBLISH_RESOURCES_TO_CLOUD, ES_ERRCODE_NO_RESPONSE_FROM_CLOUD_SERVER, NULL, NULL) != 0) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "StateAndNotify is failed.");
+ }
+
+ force_session_stop(CISESS_NULL);
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Exit.");
+ return 0;
+}
+
+static void *handle_dev_profile_timeout(timeout_s *timeout)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Device Profile Publish is Time-Out.");
+
+ if (timeout == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "[Error] timeout is NULL.");
+ return 0;
+ }
+
+ int thres_hold = timeout->ori_num * 5; // PDF thres_hold 0.2 --> 5
+
+ if (timeout->cur_num < thres_hold && (timeout->cur_num = (int)next_time_out((long long)timeout->ori_num, (long long)timeout->cur_num)) != -1) {
+ if (timeout->cur_num > thres_hold) {
+ timeout->cur_num = thres_hold;
+ }
+ timeout->cur_counter = timeout->cur_num;
+
+ THINGS_LOG_V(THINGS_INFO, TAG, "Device Profile Request Send is re-tryed. (PDF interval:%d)", timeout->cur_num);
+ publish_dev_profile_into_cloud(timeout);
+ } else {
+ THINGS_LOG_V(THINGS_INFO, TAG, "Device Profile publish Re-Try Request Sending is failed.");
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Exit.");
+ return 0;
+}
+
+static int set_def_cloud_info(es_cloud_signup_s *cloud_info, const char *cloud_addr, const es_cloud_prov_data_s *prov_data)
+{
+ int result = 1;
+ char *ip_port = NULL;
+ char *m_domain = NULL;
+ char *t_domain = NULL;
+
+ if (cloud_info == NULL || cloud_addr == NULL || cloud_addr[0] == 0) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "Parameter value is invalid.(cloud_info=0x%X, coud_addr=%s)", cloud_info, cloud_addr);
+ return 0;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "cloud_addr = %s", cloud_addr);
+
+ if (cloud_info->address != NULL) {
+ things_free(cloud_info->address);
+ cloud_info->address = NULL;
+ }
+
+ if (cloud_info->port != NULL) {
+ things_free(cloud_info->port);
+ cloud_info->port = NULL;
+ }
+
+ if (cloud_info->domain != NULL) {
+ things_free(cloud_info->domain);
+ cloud_info->domain = NULL;
+ }
+
+ ip_port = strstr(cloud_addr, "://");
+ if (ip_port == NULL) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "cloud_addr is invalid.");
+ return 0;
+ }
+ ip_port = ip_port + 3;
+
+ if ((cloud_info->address = (char *)things_malloc(sizeof(char) * MAX_CI_ADDRESS)) == NULL) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "Cloud_info address memory allocation is Failed.");
+ return 0;
+ }
+
+ things_strncpy(cloud_info->address, ip_port, MAX_CI_ADDRESS); // Ip:Port save.
+
+ // if exist Cloud m_domain Name, then Save Name and Port.
+ if (cloud_info->redirect_uri != NULL && strlen(cloud_info->redirect_uri) > 0) {
+ m_domain = strdup(cloud_info->redirect_uri);
+ } else if (prov_data != NULL) {
+ m_domain = strdup(prov_data->host_name);
+ }
+
+ if (m_domain != NULL && strlen(m_domain) != 0) {
+ t_domain = m_domain;
+ if (strstr(m_domain, "://") != NULL) {
+ t_domain = strstr(m_domain, "://") + 3;
+ }
+
+ if (strchr(t_domain, ':') != NULL) {
+ ip_port = strchr(t_domain, ':');
+ *ip_port = NULL;
+ ip_port++;
+ } else {
+ if ((ip_port = strchr(ip_port, ':')) == NULL) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "Not exit Port number.");
+ result = 0;
+ goto GOTO_OUT;
+ }
+ ip_port++;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "m_domain = %s", t_domain);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Port = %s", ip_port);
+
+ int length_port = strlen(ip_port) + 1;
+ int length_domain = strlen(t_domain) + 1;
+
+ if ((cloud_info->port = (char *)things_malloc(sizeof(char) * length_port)) == NULL) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "Cloud_info port memory allocation is Failed.");
+ result = 0;
+ goto GOTO_OUT;
+ }
+
+ if ((cloud_info->domain = (char *)things_malloc(sizeof(char) * length_domain)) == NULL) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "Cloud_info domain-name memory allocation is Failed.");
+ result = 0;
+ goto GOTO_OUT;
+ }
+
+ things_strncpy(cloud_info->port, ip_port, length_port); // Cloud Port save.
+
+ things_strncpy(cloud_info->domain, t_domain, length_domain); // Cloud domain name save.
+ }
+
+ if (cloud_info->refresh_token == NULL) {
+ if (prov_data == NULL || prov_data->refreshtoken[0] == 0) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "Not exist Refresh Token. please check your system.");
+ result = 0;
+ goto GOTO_OUT;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "refreshtoken = %s", prov_data->refreshtoken);
+
+ int length_refresh = strlen(prov_data->refreshtoken) + 1;
+
+ if ((cloud_info->refresh_token = (char *)things_malloc(sizeof(char) * length_refresh)) == NULL) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "Cloud_info port memory allocation is Failed.");
+ result = 0;
+ goto GOTO_OUT;
+ }
+
+ things_strncpy(cloud_info->refresh_token, prov_data->refreshtoken, length_refresh); // Cloud Refresh Token save.
+ }
+
+GOTO_OUT:
+ if (m_domain) {
+ things_free(m_domain);
+ m_domain = NULL;
+ t_domain = NULL;
+ }
+ ip_port = NULL;
+
+ if (result == 0) {
+ if (cloud_info->address) {
+ things_free(cloud_info->address);
+ cloud_info->address = NULL;
+ }
+
+ if (cloud_info->port) {
+ things_free(cloud_info->port);
+ cloud_info->port = NULL;
+ }
+
+ if (cloud_info->domain) {
+ things_free(cloud_info->domain);
+ cloud_info->domain = NULL;
+ }
+ }
+
+ return result;
+}
+
+OCStackApplicationResult handle_register_cb(void *ctx, OCDoHandle handle, OCClientResponse *client_response)
+{
+ int res = OC_STACK_DELETE_TRANSACTION;
+ int n_err = 0;
+ es_cloud_prov_data_s *proved_data = NULL;
+
+ if (ctx != (void *)DEFAULT_CONTEXT_VALUE) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Invalid Register callback received");
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Register response received code: %s(%d)", get_result(client_response->result), client_response->result);
+ if ((proved_data = if_failed_then_retry(handle, client_response->result, &n_err)) == NULL) {
+ if (n_err == 1 || n_err == 4) { // OC_STACK_COMM_ERROR or Handle is invalid.
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "OC_STACK_COMM_ERROR(1) or Handle InValid(4) : %d", n_err);
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "System Error occurred.(proved_data=0x%X, n_err=%d)", proved_data, n_err);
+ if (es_cloud_state_set_and_notify(ES_STATE_FAILED_TO_REGISTER_TO_CLOUD, ER_ERRCODE_SYSTEM_ERROR, NULL, NULL) != 0) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "StateAndNotify is failed.");
+ }
+
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+
+ send_cnt_sign_up = 0;
+
+ if (client_response->payload != NULL && client_response->payload->type == PAYLOAD_TYPE_REPRESENTATION) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "PAYLOAD_TYPE_REPRESENTATION received");
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "You can login using received session variable after disconnected or reboot");
+
+ OCRepPayloadValue *val = ((OCRepPayload *) client_response->payload)->values;
+ while (val != NULL) {
+ if (val->type == OCREP_PROP_INT) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Key: %s, Value: %lld, int ", val->name, val->i);
+ } else if (val->type == OCREP_PROP_STRING) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Key: %s, Value: %s, string", val->name, val->str);
+ } else {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Un supported val Type.(0x%d)", val->type);
+ }
+
+ val = val->next;
+ }
+
+ if (client_response->result != OC_STACK_RESOURCE_CHANGED) {
+ ci_error_code_e ci_err = ERRCI_NO_ERROR;
+
+ oic_ping_unset_mask(g_cloud_ip, PING_ST_ISCLOUD | PING_ST_SIGNIN);
+
+ if (es_cloud_state_set_and_notify(ES_STATE_FAILED_TO_REGISTER_TO_CLOUD, (ci_error_code_e) NULL, client_response, &ci_err) != 0) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "StateAndNotify is failed.");
+ res = OC_STACK_DELETE_TRANSACTION;
+ goto GOTO_OUT;
+ }
+
+ switch (ci_err) {
+ case ERRCI_NOT_ACCEPTABLE:
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Cloud received duplicated-request in 500msec. retry-again");
+ if (g_qis_cloud_thread_running != CISESS_APDISCON) {
+ cloud_request_retry_trigger(NULL);
+ }
+ break;
+ case ERRCI_INTERNAL_SERVER_ERROR:
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[ERRCODE]Cloud Server has a issue, Check your Cloud Server.");
+ esm_get_network_status(); // State return
+ break;
+ case ERRCI_SAMSUNG_ACCOUNT_UNAUTHORIZED_TOKEN:
+ case ERRCI_SAMSUNG_ACCOUNT_AUTHORIZATION_FAILED:
+ case ERRCI_FORBIDDEN:
+ case ERRCI_USER_NOT_FOUND:
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[ERRCODE] %d : fix the information and try again.", ci_err);
+ if (cloud_retry_sign_in(NULL) != 0) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "Cloud connection Re-try is failed.");
+ }
+ res = OC_STACK_DELETE_TRANSACTION;
+ break;
+ case ERRCI_DEVICE_DUPLICATE_PARAM:
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[ERRCODE] %d : check your device_id and try again.", ci_err);
+ ; // TODO : need cloud definition.
+ break;
+ default:
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Not Support This Cloud-Error-Code(%d) Exception", ci_err);
+ esm_get_network_status(); // State return
+ res = OC_STACK_DELETE_TRANSACTION;
+ break;
+ }
+
+ goto GOTO_OUT;
+ }
+
+ if (es_cloud_signup_init(&signed_up_data) == false) {
+ es_cloud_state_set_and_notify(ES_STATE_FAILED_TO_REGISTER_TO_CLOUD, ER_ERRCODE_SYSTEM_ERROR, NULL, NULL);
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "signed_up_data-memory allocation is Failed, try again.");
+ res = OC_STACK_DELETE_TRANSACTION;
+ goto GOTO_OUT;
+ }
+ // [Kes] get Signed-data but mandatory key-value are follows. (accesstoken / refreshtoken / token_type / expiresin / uid)
+ OCRepPayloadGetPropString(((OCRepPayload *) client_response->payload), KEY_TOKEN_ACCESS, &signed_up_data->access_token);
+ OCRepPayloadGetPropString(((OCRepPayload *) client_response->payload), KEY_TOKEN_ACCESS_REFRESH, &signed_up_data->refresh_token);
+ OCRepPayloadGetPropString(((OCRepPayload *) client_response->payload), KEY_TOKEN_TYPE, &signed_up_data->token_type);
+ OCRepPayloadGetPropInt(((OCRepPayload *) client_response->payload), KEY_EXPIRE_TIME, &signed_up_data->expire_time);
+ OCRepPayloadGetPropString(((OCRepPayload *) client_response->payload), KEY_ID_USER, &signed_up_data->uid);
+ OCRepPayloadGetPropString(((OCRepPayload *) client_response->payload), KEY_SERVER_REDIRECT_URI, &signed_up_data->redirect_uri);
+ OCRepPayloadGetPropString(((OCRepPayload *) client_response->payload), KEY_CERTIFICATE_FILE, &signed_up_data->certificate);
+ OCRepPayloadGetPropString(((OCRepPayload *) client_response->payload), KEY_SERVER_ID, &signed_up_data->sid);
+
+#ifdef __SECURED__
+ if (sm_save_cloud_acl(signed_up_data->sid) != 0) { // OIC_SEC_OK(0)
+ es_cloud_state_set_and_notify(ES_STATE_FAILED_TO_REGISTER_TO_CLOUD, ER_ERRCODE_SYSTEM_ERROR, NULL, NULL);
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "It's failed to save Cloud UUID to ACL list.");
+ res = OC_STACK_DELETE_TRANSACTION;
+ goto GOTO_OUT;
+ }
+#endif //__SECURED__
+
+ if (set_def_cloud_info(signed_up_data, g_cloud_address, proved_data) == 0) {
+ es_cloud_state_set_and_notify(ES_STATE_FAILED_TO_REGISTER_TO_CLOUD, ER_ERRCODE_SYSTEM_ERROR, NULL, NULL);
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "signed_up_data default setting is Failed.");
+ res = OC_STACK_DELETE_TRANSACTION;
+ goto GOTO_OUT;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "expiresin : %lld", signed_up_data->expire_time);
+
+ if (signed_up_data->access_token == NULL || strlen(signed_up_data->access_token) < 1) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Session Key is NULL");
+
+ if (es_cloud_state_set_and_notify(ES_STATE_FAILED_TO_REGISTER_TO_CLOUD, ES_ERRCODE_INVALID_ACCESSTOKEN, NULL, NULL) != 0) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "StateAndNotify is failed.");
+ res = OC_STACK_DELETE_TRANSACTION;
+ goto GOTO_OUT;
+ }
+ } else {
+ THINGS_LOG(THINGS_DEBUG, TAG, "Write Sign-Up data to file.");
+ if (dm_update_things_cloud(signed_up_data) == 0) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Sign-UP data can not write to info file.");
+ res = OC_STACK_DELETE_TRANSACTION;
+ goto GOTO_OUT;
+ }
+
+ THINGS_LOG(THINGS_DEBUG, TAG, "Start Login Into Cloud");
+ log_in_out_to_cloud(true, NULL);
+ res = OC_STACK_DELETE_TRANSACTION;
+ }
+ } else {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Received Failed-Response of Sign-UP without payload from Cloud Server.");
+
+ if (es_cloud_state_set_and_notify(ES_STATE_FAILED_TO_REGISTER_TO_CLOUD, ES_ERRCODE_UNKNOWN, NULL, NULL) != 0) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "StateAndNotify is failed.");
+ res = OC_STACK_DELETE_TRANSACTION;
+ goto GOTO_OUT;
+ }
+ }
+
+GOTO_OUT:
+ if (proved_data) {
+ things_free(proved_data);
+ proved_data = NULL;
+ }
+
+ return res;
+}
+
+/**
+ * @brief Call-Back function of "OCDoResource" for Cloud Sign-IN response.
+ * @param ctx User Data. (Not used)
+ * @param handle OCDoHandle of Request correspond to this Cloud-Response.
+ * @param client_response Cloud Response Data.
+ * @return Success return OC_STACK_DELETE_TRANSACTION (1) \n
+ * Failed return OC_STACK_DELETE_TRANSACTION (0)
+ */
+OCStackApplicationResult handle_login_cb(void *ctx, OCDoHandle handle, OCClientResponse *client_response)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Login callback received");
+
+ int n_err = 0;
+ es_cloud_prov_data_s *proved_data = NULL;
+ OCStackApplicationResult res = OC_STACK_DELETE_TRANSACTION;
+
+ if (ctx != (void *)DEFAULT_CONTEXT_VALUE) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Invalid Login callback received");
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Login response received code: %s(%d)", get_result(client_response->result), client_response->result);
+ proved_data = if_failed_then_retry(handle, client_response->result, &n_err);
+
+ if (proved_data) {
+ things_free(proved_data);
+ proved_data = NULL;
+ }
+
+ if (n_err >= 3 || n_err == 1) { // mem alloc error, handle is invalid.
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Memory alloc error or InValid Resp CB.(%d)", n_err);
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+
+ if (client_response->payload != NULL && client_response->payload->type == PAYLOAD_TYPE_REPRESENTATION) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "PAYLOAD_TYPE_REPRESENTATION received");
+
+ OCRepPayloadValue *val = ((OCRepPayload *) client_response->payload)->values;
+ while (val) {
+ if (val->type == OCREP_PROP_INT) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Key: %s, Value: %lld, int", val->name, val->i);
+ } else if (val->type == OCREP_PROP_STRING) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Key: %s, Value: %s, string", val->name, val->str);
+ } else {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Un supported val Type.(0x%d)", val->type);
+ }
+
+ val = val->next;
+ }
+
+ if (client_response->result != OC_STACK_RESOURCE_CHANGED) {
+ ci_error_code_e ci_err = ERRCI_NO_ERROR;
+
+ oic_ping_unset_mask(g_cloud_ip, PING_ST_SIGNIN);
+
+ if (es_cloud_state_set_and_notify(ES_STATE_FAILED_TO_REGISTER_TO_CLOUD, (ci_error_code_e) NULL, client_response, &ci_err) != 0) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "StateAndNotify is failed.");
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+
+ switch (ci_err) {
+ case ERRCI_INTERNAL_SERVER_ERROR:
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[ERRCODE]Cloud Server has a issue, Check your Cloud Server.");
+ oic_ping_unset_mask(g_cloud_ip, PING_ST_ISCLOUD);
+ esm_get_network_status(); // State return
+ break;
+ case ERRCI_TOKEN_VALIDATION_FAILED:
+ case ERRCI_TOKEN_EXPIRED:
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[ERRCODE] AccessToken \"%d\", refresh AccessToken and try again.", ci_err);
+ refresh_token_into_cloud(); // refresh accesstoken.
+ break;
+ case ERRCI_FORBIDDEN:
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[ERRCODE]-> URI is invalid, fix the URI and try again.");
+ cloud_retry_sign_in(NULL); // TODO : need re-code
+ break;
+ case ERRCI_DEVICE_NOT_FOUND:
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[ERRCODE]Device Not Found, Check your device ID and User ID coupling.");
+ oic_ping_unset_mask(g_cloud_ip, PING_ST_ISCLOUD);
+ esm_get_network_status(); // State return
+ if (things_reset(NULL, RST_AUTO_RESET) == -1) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "[Error] things_reset is failed.");
+ }
+ break;
+ default:
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Not Support This Cloud-Error-Code(%d) Exception", ci_err);
+ oic_ping_unset_mask(g_cloud_ip, PING_ST_ISCLOUD);
+ esm_get_network_status(); // State return
+ break;
+ }
+
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+
+ if (es_cloud_state_set_and_notify(ES_STATE_REGISTERED_TO_CLOUD, ES_ERRCODE_NO_ERROR, NULL, NULL) != 0) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "StateAndNotify is failed.");
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+
+ oic_ping_set_mask(g_cloud_ip, atoi(g_cloud_port), PING_ST_SIGNIN);
+
+ // [ysy] Plublish resources to cloud
+ THINGS_LOG(THINGS_DEBUG, TAG, "Start OCCloudPUblish");
+ retranslate_rsc_publish_cnt = 0;
+ publish_resource_into_cloud(RSC_PUB_MAIN_ONLY, NULL);
+#ifdef ENABLE_PUSH_NOTY
+ NSProviderEnableRemoteService(g_cloud_address);
+#endif
+
+ res = OC_STACK_DELETE_TRANSACTION;
+ } else if (client_response->result != OC_STACK_RESOURCE_CHANGED) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Received Failed-Response of Sign-IN without payload from Cloud Server.");
+
+ if (es_cloud_state_set_and_notify(ES_STATE_FAILED_TO_REGISTER_TO_CLOUD, ES_ERRCODE_UNKNOWN, NULL, NULL) != 0) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "StateAndNotify is failed.");
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+ }
+
+ return res;
+}
+
+/**
+ * @brief Call-Back function of "OCDoResource" for Cloud Sign-OUT response.
+ * @param ctx User Data. (Not used)
+ * @param handle OCDoHandle of Request correspond to this Cloud-Response.
+ * @param client_response Cloud Response Data.
+ * @return Success return OC_STACK_DELETE_TRANSACTION (1) \n
+ * Failed return OC_STACK_DELETE_TRANSACTION (0)
+ */
+OCStackApplicationResult handle_logout_cb(void *ctx, OCDoHandle handle, OCClientResponse *client_response)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Logout callback received");
+
+ OCStackApplicationResult res = OC_STACK_DELETE_TRANSACTION;
+
+ if (ctx != (void *)DEFAULT_CONTEXT_VALUE) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Invalid Logout callback received");
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Logout response received code: %s(%d)", get_result(client_response->result), client_response->result);
+
+ if (client_response->payload != NULL && client_response->payload->type == PAYLOAD_TYPE_REPRESENTATION) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "PAYLOAD_TYPE_REPRESENTATION received");
+
+ OCRepPayloadValue *val = ((OCRepPayload *) client_response->payload)->values;
+ while (val) {
+ if (val->type == OCREP_PROP_INT) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Key: %s, Value: %lld, int", val->name, val->i);
+ } else if (val->type == OCREP_PROP_STRING) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Key: %s, Value: %s, string", val->name, val->str);
+ } else {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Un supported val Type.(0x%d)", val->type);
+ }
+
+ val = val->next;
+ }
+ }
+
+ if (g_qis_cloud_thread_running != CISESS_BUSY && g_qis_cloud_thread_running != CISESS_APDISCON) {
+ things_es_enrollee_state_e es_err = ES_STATE_INIT;
+
+ if (esm_get_network_status() == true) {
+ es_err = ES_STATE_CONNECTED_TO_ENROLLER;
+ }
+
+ if (es_cloud_state_set_and_notify(es_err, ES_ERRCODE_NO_ERROR, NULL, NULL) != 0) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "StateAndNotify is failed.");
+ }
+ }
+
+ res = OC_STACK_DELETE_TRANSACTION;
+
+ return res;
+}
+
+static bool check_comm_error_retrans(OCStackResult result)
+{
+#define MAX_COMM_ERROR_RETRANSMISSION 10
+ bool ret = false;
+ static int retransmission_count = 0;
+
+ if (result == OC_STACK_COMM_ERROR) { // Don't Send Request Message.
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Request-Send is Failed.");
+ if (g_qis_cloud_thread_running != CISESS_APDISCON && retransmission_count < MAX_COMM_ERROR_RETRANSMISSION) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Re-transmission try.");
+ retransmission_count++;
+ ret = true;
+ } else {
+ retransmission_count = 0;
+ }
+ } else {
+ retransmission_count = 0;
+ }
+
+ return ret;
+#undef MAX_COMM_ERROR_RETRANSMISSION
+}
+
+OCStackApplicationResult handle_refresh_token_cb(void *ctx, OCDoHandle handle, OCClientResponse *client_response)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Refresh Token callback received");
+
+ OCStackApplicationResult res = OC_STACK_DELETE_TRANSACTION;
+
+ if (ctx != (void *)DEFAULT_CONTEXT_VALUE) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Invalid Login/out callback received");
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Refresh Token response received code: %s(%d)", get_result(client_response->result), client_response->result);
+
+ if (check_comm_error_retrans(client_response->result) == true) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Re-Start Refresh-Token Process.");
+ refresh_token_into_cloud();
+ }
+
+ if (client_response->payload != NULL && client_response->payload->type == PAYLOAD_TYPE_REPRESENTATION) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "PAYLOAD_TYPE_REPRESENTATION received");
+
+ OCRepPayloadValue *val = ((OCRepPayload *) client_response->payload)->values;
+ while (val != NULL) {
+ if (val->type == OCREP_PROP_INT) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Key: %s, Value: %lld, int", val->name, val->i);
+ } else if (val->type == OCREP_PROP_STRING) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Key: %s, Value: %s, string", val->name, val->str);
+ } else {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Un supported val Type.(0x%d)", val->type);
+ }
+
+ val = val->next;
+ }
+
+ if (client_response->result != OC_STACK_RESOURCE_CHANGED) {
+ ci_error_code_e ci_err = ERRCI_NO_ERROR;
+ // Method don't care because issue is not occurred by it.
+ if (get_cloud_code(client_response, OC_REST_POST, &ci_err) == 0) {
+ ci_err = ERRCI_UNKNOWN;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Cloud ErrCode = %d", ci_err);
+// es_set_cloud_error_code(ci_err);
+
+ switch (ci_err) {
+ case ERRCI_INTERNAL_SERVER_ERROR:
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[ERRCODE]Cloud Server has a issue, Check your Cloud Server.");
+ esm_get_network_status(); // State return
+ break;
+ case ERRCI_TOKEN_VALIDATION_FAILED:
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[ERRCODE]-> RefreshToken is invalid, fix RefreshToken and try again.");
+ esm_get_network_status(); // State return
+ break;
+ case ERRCI_SAMSUNG_ACCOUNT_UNAUTHORIZED_TOKEN:
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[ERRCODE]-> RefreshToken is mismatched with client ID, fix RefreshToken or Client ID.");
+ esm_get_network_status(); // State return
+ break;
+ case ERRCI_TOKEN_EXPIRED:
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[ERRCODE]-> RefreshToken is expired, refresh RefreshToken and try again.");
+ esm_get_network_status(); // State return
+ break;
+ case ERRCI_FORBIDDEN:
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[ERRCODE]-> URI is invalid, fix the URI and try again.");
+ esm_get_network_status(); // State return
+ break;
+ default:
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Not Support This Cloud-Error-Code(%d) Exception", ci_err);
+ esm_get_network_status(); // State return
+ break;
+ }
+
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+
+ OICFree(signed_up_data->access_token);
+ OICFree(signed_up_data->refresh_token);
+ OICFree(signed_up_data->token_type);
+ signed_up_data->expire_time = 0;
+
+ OCRepPayloadGetPropString(((OCRepPayload *) client_response->payload), KEY_TOKEN_ACCESS, &signed_up_data->access_token);
+ OCRepPayloadGetPropString(((OCRepPayload *) client_response->payload), KEY_TOKEN_ACCESS_REFRESH, &signed_up_data->refresh_token);
+ OCRepPayloadGetPropString(((OCRepPayload *) client_response->payload), KEY_TOKEN_TYPE, &signed_up_data->token_type);
+ OCRepPayloadGetPropInt(((OCRepPayload *) client_response->payload), KEY_EXPIRE_TIME, &signed_up_data->expire_time);
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "expiresin : %lld", signed_up_data->expire_time);
+
+ if (signed_up_data->access_token == NULL || strlen(signed_up_data->access_token) < 1) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Session Key is NULL. Refresh Token Failed.");
+ } else {
+ THINGS_LOG(THINGS_DEBUG, TAG, "Write Sign-Up data to file.");
+ if (dm_update_things_cloud(signed_up_data) == 1) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Re-Try Sign-IN step.");
+ force_session_stop(CISESS_SIGNOUT);
+ log_in_out_to_cloud(true, NULL);
+ } else {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Refreshed Sign-UP data can not write to info file.");
+ }
+ }
+
+ res = OC_STACK_DELETE_TRANSACTION;
+ }
+
+ return res;
+}
+
+OCStackApplicationResult handle_main_dev_publish_cb(void *ctx, OCDoHandle handle, OCClientResponse *client_response)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Publish callback received");
+
+ if (ctx != (void *)DEFAULT_CONTEXT_VALUE) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Invalid Publish callback received");
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Publish resource response received, code: %s(%d)", get_result(client_response->result), client_response->result);
+ if (cas_request_handle(handle, NULL) == 1) {
+ del_all_request_handle();
+
+ if (check_comm_error_retrans(client_response->result) == true) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Re-Start publish_resource_into_cloud");
+ publish_resource_into_cloud(RSC_PUB_MAIN_ONLY, NULL);
+ }
+
+ } else {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Response Handle(0x%X) is not exist in the Request Handle list.", handle);
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+
+ if (client_response->payload != NULL && client_response->payload->type == PAYLOAD_TYPE_REPRESENTATION) {
+ OCRepPayloadValue *val = ((OCRepPayload *) client_response->payload)->values;
+ while (val != NULL) {
+ if (val->type == OCREP_PROP_INT) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Key: %s, Value: %lld, int", val->name, val->i);
+ } else if (val->type == OCREP_PROP_STRING) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Key: %s, Value: %s, string", val->name, val->str);
+ } else {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Un supported val Type.(0x%d)", val->type);
+ }
+
+ val = val->next;
+ }
+
+ if (client_response->result != OC_STACK_RESOURCE_CHANGED) {
+ ci_error_code_e ci_err = ERRCI_NO_ERROR;
+
+ if (es_cloud_state_set_and_notify(ES_STATE_FAILED_TO_PUBLISH_RESOURCES_TO_CLOUD, (ci_error_code_e) NULL, client_response, &ci_err) != 0) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "StateAndNotify is failed.");
+ PROFILING_TIME("Cloud Provisioning End.");
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+
+ switch (ci_err) {
+ case ERRCI_INTERNAL_SERVER_ERROR:
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[ERRCODE]Cloud Server has a issue, Check your Cloud Server.");
+ esm_get_network_status(); // State return
+ break;
+ case ERRCI_TOKEN_VALIDATION_FAILED:
+ case ERRCI_TOKEN_EXPIRED:
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[ERRCODE]-> AccessToken \"%d\", refresh AccessToken and try again.", ci_err);
+ refresh_token_into_cloud(); // refresh accesstoken.
+ break;
+ case ERRCI_FORBIDDEN:
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[ERRCODE]-> URI is invalid, fix the URI and try again.");
+ break;
+ case ERRCI_RDLINK_INVALID_PARAM:
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[ERRCODE]-> Resource List Cbor syntax is invalid. Re-Translation.");
+ if (retranslate_rsc_publish_cnt < MAX_RETRY_RSCPUBLISH) {
+ publish_resource_into_cloud(RSC_PUB_MAIN_ONLY, NULL);
+ retranslate_rsc_publish_cnt++;
+ } else {
+ THINGS_LOG_D(THINGS_INFO, TAG, "[INFO] Resource Publish is Re-translated about %d\n Please check Network Line.", retranslate_rsc_publish_cnt);
+ retranslate_rsc_publish_cnt = 0;
+ esm_get_network_status(); // State return
+ }
+ break;
+ default:
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Not Support This Cloud-Error-Code(%d) Exception", ci_err);
+ break;
+ }
+ }
+
+ } else if (client_response->result != OC_STACK_RESOURCE_CHANGED) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Received Failed-Response of Resource-Publish without payload from Cloud Server.");
+
+ if (es_cloud_state_set_and_notify(ES_STATE_FAILED_TO_PUBLISH_RESOURCES_TO_CLOUD, ES_ERRCODE_UNKNOWN, NULL, NULL) != 0) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "StateAndNotify is failed.");
+ PROFILING_TIME("Cloud Provisioning End.");
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+ }
+
+ if (client_response->result == OC_STACK_RESOURCE_CHANGED) {
+ if (es_cloud_state_set_and_notify(ES_STATE_PUBLISHED_RESOURCES_TO_CLOUD, ES_ERRCODE_NO_ERROR, NULL, NULL) != 0) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "StateAndNotify is failed.");
+ PROFILING_TIME("Cloud Provisioning End.");
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+
+ publish_resource_into_cloud(RSC_PUB_SUB_ALL, NULL);
+ publish_dev_profile_into_cloud(NULL);
+ }
+
+ PROFILING_TIME("Cloud Provisioning End.");
+ return OC_STACK_DELETE_TRANSACTION;
+}
+
+OCStackApplicationResult handle_sub_dev_publish_cb(void *ctx, OCDoHandle handle, OCClientResponse *client_response)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Sub-Device resource Publish callback received");
+
+ if (ctx != (void *)DEFAULT_CONTEXT_VALUE) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Invalid Publish callback received");
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Publish resource response received, code: %s(%d)", get_result(client_response->result), client_response->result);
+ if (check_comm_error_retrans(client_response->result) == true) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Resource Publish Request-Send is Failed.");
+ publish_resource_into_cloud(RSC_PUB_SUB_ALL, NULL);
+ }
+
+ if (client_response->payload != NULL && client_response->payload->type == PAYLOAD_TYPE_REPRESENTATION) {
+ OCRepPayloadValue *val = ((OCRepPayload *) client_response->payload)->values;
+ while (val != NULL) {
+ if (val->type == OCREP_PROP_INT) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Key: %s, Value: %lld, int", val->name, val->i);
+ } else if (val->type == OCREP_PROP_STRING) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Key: %s, Value: %s, string", val->name, val->str);
+ } else {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Un supported val Type.(0x%d)", val->type);
+ }
+
+ val = val->next;
+ }
+
+ if (client_response->result != OC_STACK_RESOURCE_CHANGED) {
+ ci_error_code_e ci_err = ERRCI_NO_ERROR;
+
+ if (get_cloud_code(client_response, OC_REST_POST, &ci_err) == 0) {
+ ci_err = ERRCI_UNKNOWN;
+ }
+// es_set_cloud_error_code(ci_err);
+
+ switch (ci_err) {
+ case ERRCI_INTERNAL_SERVER_ERROR:
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[ERRCODE]Cloud Server has a issue, Check your Cloud Server.");
+ esm_get_network_status(); // State return
+ break;
+ case ERRCI_TOKEN_VALIDATION_FAILED:
+ case ERRCI_TOKEN_EXPIRED:
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[ERRCODE]-> AccessToken \"%d\", refresh AccessToken and try again.", ci_err);
+ refresh_token_into_cloud(); // refresh accesstoken.
+ break;
+ default:
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Not Support This Cloud-Error-Code(%d) Exception", ci_err);
+ break;
+ }
+ }
+
+ }
+
+ return OC_STACK_DELETE_TRANSACTION;
+}
+
+OCStackApplicationResult handle_dev_profile_cb(void *ctx, OCDoHandle handle, OCClientResponse *client_response)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Device Profile Publish callback received");
+
+ if (ctx != (void *)DEFAULT_CONTEXT_VALUE) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Invalid Publish callback received");
+ }
+
+ del_all_request_handle();
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Device Profile Publish response received, code: %s(%d)", get_result(client_response->result), client_response->result);
+ if (check_comm_error_retrans(client_response->result) == true) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Device Profile Publish Request-Send is Failed.");
+ publish_dev_profile_into_cloud(NULL);
+ }
+
+ if (client_response->payload != NULL && client_response->payload->type == PAYLOAD_TYPE_REPRESENTATION) {
+ OCRepPayloadValue *val = ((OCRepPayload *) client_response->payload)->values;
+ while (val != NULL) {
+ if (val->type == OCREP_PROP_INT) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Key: %s, Value: %lld, int", val->name, val->i);
+ } else if (val->type == OCREP_PROP_STRING) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Key: %s, Value: %s, string", val->name, val->str);
+ } else {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Un supported val Type.(0x%d)", val->type);
+ }
+
+ val = val->next;
+ }
+
+ if (client_response->result != OC_STACK_RESOURCE_CHANGED) {
+ ci_error_code_e ci_err = ERRCI_NO_ERROR;
+
+ if (get_cloud_code(client_response, OC_REST_POST, &ci_err) == 0) {
+ ci_err = ERRCI_UNKNOWN;
+ }
+// es_set_cloud_error_code(ci_err);
+
+ switch (ci_err) {
+ case ERRCI_INTERNAL_SERVER_ERROR:
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[ERRCODE]Cloud Server has a issue, Check your Cloud Server.");
+ esm_get_network_status(); // State return
+ break;
+ case ERRCI_TOKEN_VALIDATION_FAILED:
+ case ERRCI_TOKEN_EXPIRED:
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[ERRCODE]-> AccessToken \"%d\", refresh AccessToken and try again.", ci_err);
+ refresh_token_into_cloud(); // refresh accesstoken.
+ break;
+ default:
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Not Support This Cloud-Error-Code(%d) Exception", ci_err);
+ break;
+ }
+ }
+
+ }
+
+ return OC_STACK_DELETE_TRANSACTION;
+}
+
+OCStackApplicationResult handle_find_resource_cb(void *ctx, OCDoHandle handle, OCClientResponse *client_response)
+{
+ if (ctx == (void *)DEFAULT_CONTEXT_VALUE) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Callback Context for DISCOVER query recvd successfully");
+ }
+
+ if (client_response) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "StackResult: %s(%d)", get_result(client_response->result), client_response->result);
+
+ //char* connectionType = getConnectivityType (client_response->connType);
+ //THINGS_LOG_D(THINGS_DEBUG, TAG, "Discovered on %s", connectionType.c_str());
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Device =============> Discovered @ %s:%d", client_response->devAddr.addr, client_response->devAddr.port);
+
+ if (client_response->payload != NULL && client_response->payload->type == PAYLOAD_TYPE_REPRESENTATION) {
+ OCRepPayloadValue *val = ((OCRepPayload *) client_response->payload)->values;
+ while (val != NULL) {
+ if (val->type == OCREP_PROP_INT) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Key: %s, Value: %lld, int", val->name, val->i);
+ } else if (val->type == OCREP_PROP_STRING) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Key: %s, Value: %s, string", val->name, val->str);
+ } else {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Un supported val Type.(0x%d)", val->type);
+ }
+
+ val = val->next;
+ }
+ }
+
+ if (client_response->result != OC_STACK_OK) {
+ THINGS_LOG_D(THINGS_INFO, TAG, "Refresh Token process Start.");
+ refresh_token_into_cloud();
+ }
+
+ } else {
+ THINGS_LOG_D(THINGS_INFO, TAG, "handle_find_resource_cb received Null client_response");
+ }
+
+ return OC_STACK_DELETE_TRANSACTION;
+}
+
+OCStackApplicationResult handle_publish_topic_cb(void *ctx, OCDoHandle handle, OCClientResponse *client_response)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Publish Topic callback received");
+
+ OCStackApplicationResult res = OC_STACK_DELETE_TRANSACTION;
+
+ if (ctx != (void *)DEFAULT_CONTEXT_VALUE) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Invalid Publish Topic callback received");
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Publish Topic response received code: %s(%d)", get_result(client_response->result), client_response->result);
+
+ if (client_response->payload != NULL && client_response->payload->type == PAYLOAD_TYPE_REPRESENTATION) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "PAYLOAD_TYPE_REPRESENTATION received");
+
+ OCRepPayloadValue *val = ((OCRepPayload *) client_response->payload)->values;
+ while (val) {
+ if (val->type == OCREP_PROP_INT) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Key: %s, Value: %lld, int", val->name, val->i);
+ } else if (val->type == OCREP_PROP_STRING) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Key: %s, Value: %s, string", val->name, val->str);
+ } else {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Un supported val Type.(0x%d)", val->type);
+ }
+
+ val = val->next;
+ }
+
+ if (client_response->result != OC_STACK_RESOURCE_CHANGED) {
+ ci_error_code_e ci_err = ERRCI_NO_ERROR;
+
+ if (0 == get_cloud_code(client_response, OC_REST_POST, &ci_err)) {
+ ci_err = ERRCI_UNKNOWN;
+ }
+
+ switch (ci_err) {
+ case ERRCI_INTERNAL_SERVER_ERROR:
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[ERRCODE]Cloud Server has a issue, Check your Cloud Server.");
+ esm_get_network_status(); // State return
+ break;
+ case ERRCI_TOKEN_VALIDATION_FAILED:
+ case ERRCI_TOKEN_EXPIRED:
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[ERRCODE] AccessToken \"%d\", refresh AccessToken and try again.", ci_err);
+ refresh_token_into_cloud(); // refresh accesstoken.
+ break;
+ default:
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Not Support This Cloud-Error-Code(%d) Exception", ci_err);
+ //esm_get_network_status(); // Don't need to sign out on this session
+ break;
+ }
+ }
+
+ res = OC_STACK_DELETE_TRANSACTION;
+ }
+
+ return res;
+}
+
+static OCStackResult publish_resource_main_dev_into_cloud(things_resource_s **list, int length, timeout_s *timeout)
+{
+ es_error_code_e es_err = ES_ERRCODE_UNKNOWN;
+ OCStackResult res = OC_STACK_ERROR;
+
+ if (list == NULL || length < 1) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Invalid Parameter Inserted");
+ es_cloud_state_set_and_notify(ES_STATE_FAILED_TO_PUBLISH_RESOURCES_TO_CLOUD, ER_ERRCODE_SYSTEM_ERROR, NULL, NULL);
+ return res;
+ } else {
+ if (es_cloud_state_set_and_notify(ES_STATE_PUBLISHING_RESOURCES_TO_CLOUD, ES_ERRCODE_NO_ERROR, NULL, NULL) != 0) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "StateAndNotify is failed.");
+ return res;
+ }
+
+ if (ci_connection_pre_check(NULL, NULL) == 0) {
+ res = things_cloud_rsc_publish(g_cloud_address, list, length, handle_main_dev_publish_cb, handle_publish_timeout, timeout);
+ } else {
+ THINGS_LOG_V(THINGS_INFO, TAG, "AP is not connected to internet.");
+ es_err = ES_ERRCODE_NO_INTERNETCONNECTION;
+ }
+
+ if (res != OC_STACK_OK) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Unable to publish user resources to cloud : %d", res);
+
+ if (es_cloud_state_set_and_notify(ES_STATE_FAILED_TO_PUBLISH_RESOURCES_TO_CLOUD, es_err, NULL, NULL) != 0) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "StateAndNotify is failed.");
+ return res;
+ }
+
+ return res;
+ }
+ }
+
+ return res;
+}
+
+OCStackResult publish_resource_into_cloud(rp_target_e target, timeout_s *timeout)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Enter.");
+
+ int sub_dev_pub_fail = -1;
+ OCStackResult res = OC_STACK_OK;
+
+ if (target == RSC_PUB_ALL || target == RSC_PUB_MAIN_ONLY) {
+ THINGS_LOG(THINGS_DEBUG, TAG, "Main-Device Resource Publish Start.");
+ res = publish_resource_main_dev_into_cloud(g_resource_lists, g_len, timeout);
+ usleep(10000); // 1 device resource-publish per 10 msec.
+ }
+
+ if (res == OC_STACK_OK && target != RSC_PUB_MAIN_ONLY) {
+ THINGS_LOG(THINGS_DEBUG, TAG, "Sub-Devices Resource Publish Start.");
+ int device_cnt = 0;
+ char *device_id = NULL;
+ st_device_s **dList = NULL;
+
+ if (1 == dm_get_device_information(&device_cnt, &dList) && device_cnt > 1) {
+ for (int index = 1; index < device_cnt; index++) {
+ // Get device id of hosted ones..
+ if (dList[index]->is_physical == 1) {
+ if (sub_dev_pub_fail == -1) {
+ sub_dev_pub_fail = 0;
+ }
+
+ device_id = dList[index]->device_id;
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Sub-device ID=%s", device_id);
+ if (device_id == NULL || device_id[0] == 0) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "not exist device ID. So, skip publish resource.");
+ sub_dev_pub_fail = 1;
+ continue;
+ }
+
+ OCStackResult result = things_cloud_rsc_publish_with_device_id(g_cloud_address,
+ device_id,
+ dList[index]->pchild_resources,
+ dList[index]->capa_cnt,
+ handle_sub_dev_publish_cb,
+ handle_publish_timeout,
+ timeout);
+ if (result != OC_STACK_OK) {
+ sub_dev_pub_fail = 1;
+ }
+
+ device_id = NULL;
+ usleep(10000); // 1 device resource-publish per 10 msec.
+ }
+ }
+ }
+
+ if (dList) {
+ things_free(dList);
+ dList = NULL;
+ }
+
+ if (target == RSC_PUB_SUB_ALL || target == RSC_PUB_NEED_SUB_ONLY) {
+ switch (sub_dev_pub_fail) {
+ case 1: // occurred error
+ THINGS_LOG_D(THINGS_INFO, TAG, "Sending-request is failed for Sub-device publish.");
+ res = OC_STACK_ERROR;
+ break;
+ case -1: // not exist sub-dev
+ THINGS_LOG_D(THINGS_INFO, TAG, "Not exist sub-device publish.");
+ res = OC_STACK_ERROR;
+ break;
+ case 0:
+ THINGS_LOG_D(THINGS_INFO, TAG, "Sending-request is Success for Sub-device publish.");
+ res = OC_STACK_OK;
+ break;
+ }
+ }
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Exit.");
+ return res;
+}
+
+OCStackResult log_in_out_to_cloud(bool value, timeout_s *timeout)
+{
+ int port = 0;
+ char *ci_ip = NULL;
+ char *ci_domian = NULL;
+ es_error_code_e es_err = ES_ERRCODE_UNKNOWN;
+ OCStackResult res = OC_STACK_ERROR;
+ OCClientResponseHandler callback = NULL;
+ check_time_out_call_func calltimeout = NULL;
+
+ if (signed_up_data == NULL || signed_up_data->access_token == NULL || strlen(signed_up_data->access_token) < 1) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "No Session Key Retrived from the Cloud ");
+ return res;
+ }
+
+ if (signed_up_data->domain != NULL && (signed_up_data->port == NULL || signed_up_data->port[0] == 0)) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "domain=%s but, not exist port number.(%s)", signed_up_data->domain, signed_up_data->port);
+ return res;
+ }
+
+ if (value == true) {
+ callback = handle_login_cb;
+ calltimeout = handle_signin_timeout;
+ if (es_cloud_state_set_and_notify(ES_STATE_REGISTERING_TO_CLOUD, ES_ERRCODE_NO_ERROR, NULL, NULL) != 0) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "StateAndNotify is failed.");
+ return res;
+ }
+
+ if (signed_up_data->domain != NULL) {
+ ci_domian = strdup(signed_up_data->domain);
+ }
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "*********** Start Sign-IN ********** ci_domian : %s", ci_domian);
+ } else {
+ callback = handle_logout_cb;
+ calltimeout = NULL;
+ g_qis_cloud_thread_running = CISESS_SIGNOUT;
+ if (es_cloud_state_set_and_notify(ES_STATE_LOGOUT_FROM_CLOUD, ES_ERRCODE_NO_ERROR, NULL, NULL) != 0) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "StateAndNotify is failed.");
+ return res;
+ }
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "*********** Start Sign-OUT **********");
+ }
+
+ if (ci_connection_pre_check(ci_domian, &ci_ip) == 0) {
+ if (ci_ip != NULL) {
+ if (make_cloud_address(ci_ip, signed_up_data->port, NULL) == NULL) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "Making CloudAddress is failed.");
+ goto GOTO_OUT;
+ }
+ things_strncpy(g_cloud_ip, ci_ip, IP_PORT);
+ things_strncpy(g_cloud_port, signed_up_data->port, IP_PORT);
+
+ port = atoi(g_cloud_port);
+ if (g_cloud_ip[0] == NULL || g_cloud_port[0] == NULL || 0 >= port || port > 65535) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Cloud info is invalid.(g_cloud_ip=%s, g_cloud_port=%s, port=%d)", g_cloud_ip, g_cloud_port, port);
+ goto GOTO_OUT;
+ }
+ }
+
+ if (g_cloud_address[0] == 0) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "g_cloud_address is invalid.(0x%X)", g_cloud_address);
+ goto GOTO_OUT;
+ }
+
+ THINGS_LOG_D(THINGS_INFO, TAG, "Cloud Addr : %s", g_cloud_address);
+ THINGS_LOG_D(THINGS_INFO, TAG, "device ID : %s", OCGetServerInstanceIDString());
+ THINGS_LOG_D(THINGS_INFO, TAG, "access_token : %s", signed_up_data->access_token);
+ THINGS_LOG_D(THINGS_INFO, TAG, "refresh token : %s", signed_up_data->refresh_token);
+ THINGS_LOG_D(THINGS_INFO, TAG, "user ID : %s", signed_up_data->uid);
+ THINGS_LOG_D(THINGS_INFO, TAG, "toke type : %s", signed_up_data->token_type);
+ THINGS_LOG_D(THINGS_INFO, TAG, "expire Time : %lld", signed_up_data->expire_time);
+ THINGS_LOG_D(THINGS_INFO, TAG, "certificate : %s", signed_up_data->certificate);
+ THINGS_LOG_D(THINGS_INFO, TAG, "redirect URI : %s", signed_up_data->redirect_uri);
+ THINGS_LOG_D(THINGS_INFO, TAG, "sid : %s", signed_up_data->sid);
+
+ if (value == true) {
+ oic_ping_set_mask(g_cloud_ip, port, PING_ST_ISCLOUD);
+ } else {
+ oic_ping_unset_mask(g_cloud_ip, PING_ST_ISCLOUD | PING_ST_SIGNIN | PING_ST_TCPCONNECT);
+ }
+
+ res = things_cloud_session(g_cloud_address, signed_up_data->uid, OCGetServerInstanceIDString(), signed_up_data->access_token, value, callback, calltimeout, timeout);
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "OCCloudLogInOut return : %d", res);
+ } else {
+ THINGS_LOG_V(THINGS_INFO, TAG, "AP is not connected to internet.");
+ es_err = ES_ERRCODE_NO_INTERNETCONNECTION;
+ }
+
+GOTO_OUT:
+ if (ci_ip != NULL) {
+ things_free(ci_ip);
+ ci_ip = NULL;
+ }
+
+ if (ci_domian != NULL) {
+ things_free(ci_domian);
+ ci_domian = NULL;
+ }
+
+ if (res != OC_STACK_OK) {
+ if (value == true) {
+ oic_ping_unset_mask(g_cloud_ip, PING_ST_ISCLOUD);
+
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Cloud Server LogIn Failed : %d", res);
+ if (es_cloud_state_set_and_notify(ES_STATE_FAILED_TO_REGISTER_TO_CLOUD, es_err, NULL, NULL) != 0) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "StateAndNotify is failed.");
+ return res;
+ }
+ } else {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Cloud Server LogOut Failed : %d", res);
+ esm_get_network_status();
+ return res;
+ }
+ }
+
+ return res;
+}
+
+/**
+ * @brief Call function to send request for Finding myself-resource to Cloud.
+ * @return Success return OC_STACK_OK (0) \n
+ * Failed return other OCStackResult value (-)
+ */
+OCStackResult find_cloud_resource(void)
+{
+ OCStackResult ret = OC_STACK_ERROR;
+
+ char *sz_query_uri = NULL;
+ int length = MAX_CI_ADDRESS;
+ int length_query = 0;
+
+ length += strlen(RESOURCE_DISCOVERY_QUERY_DI);
+ length += strlen(OCGetServerInstanceIDString());
+ length_query = sizeof(char) * (length + 2);
+
+ if ((sz_query_uri = (char *)things_malloc(length_query)) == NULL) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "sz_query_uri memory allocation is failed.");
+ return OC_STACK_ERROR;
+ }
+
+ memset(sz_query_uri, 0, length_query);
+ if (things_strcat(sz_query_uri, length_query, g_cloud_address) == NULL) {
+ ret = OC_STACK_NO_MEMORY;
+ }
+ if (things_strcat(sz_query_uri, length_query, RESOURCE_DISCOVERY_QUERY_DI) == NULL) {
+ ret = OC_STACK_NO_MEMORY;
+ }
+ if (things_strcat(sz_query_uri, length_query, OCGetServerInstanceIDString()) == NULL) {
+ ret = OC_STACK_NO_MEMORY;
+ }
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Find Resource to Cloud URI : %s", sz_query_uri);
+
+ OCCallbackData cb_data;
+ cb_data.cb = handle_find_resource_cb;
+ cb_data.context = (void *)DEFAULT_CONTEXT_VALUE;
+ cb_data.cd = NULL;
+
+ if (ret != OC_STACK_NO_MEMORY) {
+ ret = OCDoResource(NULL, OC_REST_DISCOVER, sz_query_uri, NULL, 0, CT_DEFAULT, OC_MEDIUM_QOS, &cb_data, NULL, 0);
+ }
+
+ if (ret != OC_STACK_OK) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "Find Resource in Cloud is failed.");
+ }
+
+ things_free(sz_query_uri);
+
+ return ret;
+}
+
+static OCStackResult register_server_into_cloud(es_cloud_prov_data_s *event_data, timeout_s *timeout)
+{
+ OCStackResult res = OC_STACK_ERROR;
+
+ if (event_data == NULL || (event_data->auth_code[0] == 0 && event_data->accesstoken[0] == 0)) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "Invalid event_data.");
+ return res;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "AuthCode : %s", event_data->auth_code);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Access Token : %s", event_data->accesstoken);
+
+ if (signed_up_data != NULL) {
+ es_cloud_signup_clear(signed_up_data);
+ signed_up_data = NULL;
+ }
+
+ int port = atoi(g_cloud_port);
+ if (g_cloud_ip[0] == NULL || g_cloud_port[0] == NULL || 0 >= port || port > 65535) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Cloud info is invalid.(g_cloud_ip=%s, g_cloud_port=%s, port=%d)", g_cloud_ip, g_cloud_port, port);
+ return res;
+ }
+
+ if (es_cloud_state_set_and_notify(ES_STATE_REGISTERING_TO_CLOUD, ES_ERRCODE_NO_ERROR, NULL, NULL) != 0) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "StateAndNotify is failed.");
+ return res;
+ }
+
+ oic_ping_set_mask(g_cloud_ip, (uint16_t) port, PING_ST_ISCLOUD);
+
+ // Get Session Key
+ res = things_cloud_signup(g_cloud_address, OCGetServerInstanceIDString(), event_data, handle_register_cb, handle_signup_timeout, timeout);
+
+ if (res != OC_STACK_OK) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Cloud Server Registration Failed : %d", res);
+ oic_ping_unset_mask(g_cloud_ip, PING_ST_ISCLOUD);
+ if (es_cloud_state_set_and_notify(ES_STATE_FAILED_TO_REGISTER_TO_CLOUD, ES_ERRCODE_UNKNOWN, NULL, NULL) != 0) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "StateAndNotify is failed.");
+ return res;
+ }
+ }
+
+ return res;
+}
+
+OCStackResult refresh_token_into_cloud(void)
+{
+ OCStackResult res = OC_STACK_ERROR;
+ if (signed_up_data == NULL || signed_up_data->access_token == NULL || strlen(signed_up_data->access_token) < 1) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "No Session Key Retrived from the Cloud ");
+ } else {
+ res = things_cloud_refresh(g_cloud_address, signed_up_data->uid, OCGetServerInstanceIDString(), signed_up_data->refresh_token, handle_refresh_token_cb);
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "OCCloud Refresh Token return : %d", res);
+ }
+
+ if (res != OC_STACK_OK) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Cloud access_token refresh Failed : %d", res);
+ }
+
+ return res;
+}
+
+int push_notification_to_cloud(const char *uri, OCRepPayload *payload)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+
+ int ret = 0;
+
+ if (things_get_reset_mask(RST_NOTI_MODULE_DISABLE) == true) {
+ THINGS_LOG(THINGS_INFO, TAG, "Notification Module Disable.");
+ ret = 0;
+ } else if (NULL != payload) {
+ if (OC_STACK_OK == things_cloud_topic_publish_topic(g_cloud_address, uri, payload, handle_publish_topic_cb)) {
+ ret = 1;
+ }
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_EXIT);
+
+ return ret;
+}
+
+static char *make_cloud_address(char *ip, char *port, const char *ci_addr)
+{
+ char *delmem = NULL;
+ char *ipport = (char *)ci_addr;
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "ip=%s, port=%s, ci_addr=%s", ip, port, ci_addr);
+
+ if (ci_addr != NULL && strlen(ci_addr) > 0) { // ci address.
+ char *point = strstr(ci_addr, DEFAULT_COAP_TCP_HOST);
+ if (point) {
+ ipport = point + strlen(DEFAULT_COAP_TCP_HOST);
+ }
+ } else if ((ipport = make_ip_port(ip, port)) != NULL) { // ip , port coupling.
+ delmem = ipport;
+ } else { // ext case.
+ ipport = DEFAULT_CI_HOST;
+ }
+
+ // Update Cloud Address.
+ memset(g_cloud_address, 0, MAX_CI_ADDRESS);
+ if (things_strcat(g_cloud_address, MAX_CI_ADDRESS, DEFAULT_COAP_TCP_HOST) == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "things_strcat() is failed.");
+ if (delmem) {
+ things_free(delmem);
+ }
+ return NULL;
+ }
+
+ if (things_strcat(g_cloud_address, MAX_CI_ADDRESS, ipport) == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "things_strcat() is failed.");
+ if (delmem) {
+ things_free(delmem);
+ }
+ return NULL;
+ }
+
+ if (delmem) {
+ things_free(delmem);
+ }
+
+ return g_cloud_address;
+}
+
+static int start_ci_connection(const char *cloud_adress, es_cloud_prov_data_s *event_data, things_resource_s **list, int length, timeout_s *timeout)
+{
+ int ret = 0;
+ OCStackResult result = OC_STACK_ERROR;
+
+ g_resource_lists = list;
+ g_len = length;
+
+ if (make_cloud_address(NULL, NULL, cloud_adress) == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Making Cloud Address is failed.");
+ result = OC_STACK_NO_MEMORY;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "CI Svr Addr : %s", g_cloud_address);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "CI Svr AuthCode : %s", event_data->auth_code);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "CI Svr Accesstoken : %s", event_data->accesstoken);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "CI Svr Uid : %s", event_data->uid);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "CI Svr AuthProvider : %s", event_data->auth_provider);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "CI Svr client_id : %s", event_data->client_id);
+
+ if (timeout != NULL) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "CI Svr timeout_cnt : %d", timeout->cur_counter);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "CI Svr timeout_cur_num : %d", timeout->cur_num);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "CI Svr timeout_ori_num : %d", timeout->ori_num);
+ }
+
+ if (result != OC_STACK_NO_MEMORY) {
+ if (event_data != NULL && (event_data->auth_code[0] != 0 || event_data->accesstoken[0] != 0)) {
+ result = register_server_into_cloud(event_data, timeout);
+ } else {
+ if (es_cloud_signup_init(&signed_up_data) == true && (ret = dm_load_legacy_cloud_data(&signed_up_data)) == 1) {
+ result = log_in_out_to_cloud(true, timeout);
+ } else {
+ THINGS_LOG_D(THINGS_INFO, TAG, "Sign-UP data load failed.");
+ }
+ }
+ }
+
+ if (OC_STACK_OK != result) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "start_ci_connection() is failed.");
+ } else {
+ ret = 1; // Success.
+ }
+
+ return ret;
+}
+
+static void *ci_connection_init_loop(es_cloud_event_timeout_s *param)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+
+ int res = 0;
+ char *ci_ip = NULL;
+ char *ci_ip_port = NULL;
+ char *ci_host = NULL;
+ es_error_code_e es_err = ES_ERRCODE_UNKNOWN;
+
+ ci_cp_del_is_there_cp();
+
+ if (param == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "[Error] parameter is NULL.");
+
+ if (es_cloud_state_set_and_notify(ES_STATE_FAILED_TO_REGISTER_TO_CLOUD, ER_ERRCODE_SYSTEM_ERROR, NULL, NULL) != 0) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "StateAndNotify is failed.");
+ }
+
+ force_session_stop(CISESS_NULL);
+ return NULL;
+ }
+
+ es_cloud_prov_data_s *event_data = ¶m->event;
+
+ if (event_data->host_name[0] != 0) {
+ ci_host = &(event_data->host_name[0]);
+ } else if (event_data->ip[0] != 0) {
+ ci_host = &(event_data->ip[0]);
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "* param add= 0x%X *", param);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "* ci_host = %s *", ci_host);
+
+ // Cross check if a network is available
+ if (esm_get_network_status()) {
+ if (g_server_builder != NULL) {
+ THINGS_LOG_V(THINGS_INFO, TAG, "##########################");
+ THINGS_LOG_V(THINGS_INFO, TAG, " Start Cloud Connection ");
+ THINGS_LOG_V(THINGS_INFO, TAG, "##########################");
+
+ if (ci_connection_pre_check(ci_host, &ci_ip) == 0) {
+ ci_ip_port = make_ip_port(ci_ip, event_data->port);
+ things_strncpy(g_cloud_ip, ci_ip, IP_PORT);
+ things_strncpy(g_cloud_port, event_data->port, IP_PORT);
+
+ pthread_mutex_lock(&g_es_mutex);
+ res = start_ci_connection(dm_get_things_cloud_address(ci_ip_port), event_data, g_server_builder->gres_arr, g_server_builder->res_num, ¶m->timeOut);
+ switch (res) {
+ case 1: // Success
+ usleep(500000); // 0.5 sec wait (need for Cloud CI Server cooling.)
+ break;
+ case 0: // Fail start_ci_connection.
+ es_err = ES_ERRCODE_UNKNOWN;
+ break;
+ case -1: // Json Parsing error. or Memory Alloc error. or Invalid argument error.
+ es_err = ER_ERRCODE_SYSTEM_ERROR;
+ break;
+ case -2: // Invalid Contents of Json file.
+ es_err = ER_ERRCODE_INVALID_SAVED_CLOUD_DATA;
+ break;
+ }
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "res = %d, es_err = %d", res, es_err);
+ pthread_mutex_unlock(&g_es_mutex);
+
+ if (ci_ip_port) {
+ things_free(ci_ip_port);
+ ci_ip_port = NULL;
+ }
+ if (ci_ip) {
+ things_free(ci_ip);
+ ci_ip = NULL;
+ }
+ } else {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "AP is Not Connected to Internet.");
+ es_err = ES_ERRCODE_NO_INTERNETCONNECTION;
+ }
+ } else {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "ServerBuilder is NULL.");
+ es_err = ER_ERRCODE_SYSTEM_ERROR;
+ }
+ } else {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Device is not connected to AP.");
+ es_err = ES_ERRCODE_UNKNOWN;
+ }
+
+ if (res != 1) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "###################################");
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, " Exiting without Cloud Connection ");
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "###################################");
+
+ if (es_cloud_state_set_and_notify(ES_STATE_FAILED_TO_REGISTER_TO_CLOUD, es_err, NULL, NULL) != 0) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "StateAndNotify is failed.");
+ }
+
+ force_session_stop(CISESS_NULL);
+ }
+
+ things_free(param);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_EXIT);
+
+ return NULL;
+}
+
+static void *ci_connection_waiting_loop(es_cloud_event_timeout_s *param)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Sleep before cloud_retry_sign_up");
+ sleep(1);
+ if (param == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "[Error] parameter is NULL.");
+ ci_cp_del_is_there_cp();
+ ci_cp_del_pended_data();
+ es_cloud_state_set_and_notify(ES_STATE_FAILED_TO_REGISTER_TO_CLOUD, ER_ERRCODE_SYSTEM_ERROR, NULL, NULL);
+ esm_get_network_status(); // State return
+ return NULL;
+ }
+
+ while (g_qis_cloud_thread_running != CISESS_STOP) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Waiting ...");
+ usleep(100000);
+ }
+
+ ci_cp_pend_event_data(&(param->event));
+ g_qis_cloud_thread_running = CISESS_BUSY;
+ THINGS_LOG(THINGS_DEBUG, TAG, "Create CloudInit thread");
+
+ ci_connection_init_loop(param);
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_EXIT);
+
+ return NULL;
+}
+
+void *cloud_data_cb_esm(es_cloud_prov_data_s *event_data)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "g_qis_cloud_thread_running = %d", g_qis_cloud_thread_running);
+
+ pthread_t cthread_handler;
+ es_cloud_event_timeout_s *cloned_data = NULL;
+#if 0 // pkcloud
+ if (ci_cp_cas_is_there_cp_if_false() == true) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Already exist data of Cloud Provisioning.");
+ return NULL;
+ }
+#endif
+ switch (g_qis_cloud_thread_running) {
+ case CISESS_APDISCON:
+ // Backup loose try..
+ ci_cp_pend_event_data(event_data);
+ return NULL;
+ case CISESS_BUSY: // Occupied
+ case CISESS_STOP_TRIGGER: // Re-Start triggered.
+ case CISESS_SIGNOUT: // doing Auto Log-Out
+ break;
+ case CISESS_STOP: // can start.
+ del_all_request_handle();
+ send_cnt_sign_up = 0;
+ ci_cp_pend_event_data(event_data);
+ g_qis_cloud_thread_running = CISESS_BUSY;
+
+ if ((cloned_data = clone_data_add_timeout(event_data, NULL)) != NULL) {
+#ifdef __ST_THINGS_RTOS__
+ int retp = pthread_create_rtos(&cthread_handler, NULL, (pthread_func_type) ci_connection_init_loop, (void *)cloned_data, THINGS_STACK_CICONNETION_INIT_THREAD);
+#else
+
+ int retp = things_thread_create(&cthread_handler, NULL, (pthread_func_type) ci_connection_init_loop, (void *)cloned_data) != 0)
+#endif
+ if (retp != 0) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Create thread is failed.");
+ things_free(cloned_data);
+ cloned_data = NULL;
+ g_qis_cloud_thread_running = CISESS_STOP;
+ es_cloud_state_set_and_notify(ES_STATE_FAILED_TO_REGISTER_TO_CLOUD, ER_ERRCODE_SYSTEM_ERROR, NULL, NULL);
+ }
+ } else {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "clone_data_add_timeout is failed.");
+ }
+ return NULL;
+ default:
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Not Surpport value(%d) of g_qis_cloud_thread_running.", g_qis_cloud_thread_running);
+ return NULL;
+ }
+
+ del_all_request_handle();
+ send_cnt_sign_up = 0;
+
+ if (cloud_retry_sign_up(event_data, NULL) == 0) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "cloud_retry_sign_up is failed.");
+ ci_cp_del_pended_data();
+ ci_cp_del_is_there_cp();
+ es_cloud_state_set_and_notify(ES_STATE_FAILED_TO_REGISTER_TO_CLOUD, ER_ERRCODE_SYSTEM_ERROR, NULL, NULL);
+ esm_get_network_status(); // State return
+ }
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_EXIT);
+
+ return NULL;
+}
+
+int cloud_retry_sign_in(timeout_s *timeout)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+
+ pthread_t cthread_handler;
+ es_cloud_prov_data_s dummy_data;
+ es_cloud_event_timeout_s *cloned_data = NULL;
+
+ if (ci_cp_get_is_there_cp() == true) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "There is a CloudProvisioning data. Cloud-retry is skiped.");
+ return 1;
+ }
+
+ force_session_stop(CISESS_NULL);
+
+ // Need to check the running state of the thread...
+ if (g_qis_cloud_thread_running == CISESS_STOP) {
+ g_qis_cloud_thread_running = CISESS_BUSY;
+ THINGS_LOG(THINGS_DEBUG, TAG, "Create CloudInit thread");
+
+ // cloud_data setting.
+ init_es_cloud_prov_data(&dummy_data);
+
+ if ((cloned_data = clone_data_add_timeout(&dummy_data, timeout)) == NULL ||
+#ifdef __ST_THINGS_RTOS__
+ pthread_create_rtos(&cthread_handler, NULL, (pthread_func_type) ci_connection_init_loop, (void *)cloned_data, THINGS_STACK_CICONNETION_INIT_THREAD) != 0)
+#else
+ things_thread_create(&cthread_handler, NULL, (pthread_func_type) ci_connection_init_loop, (void *)cloned_data) != 0)
+#endif
+ {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Create thread is failed.");
+ things_free(cloned_data);
+ cloned_data = NULL;
+ g_qis_cloud_thread_running = CISESS_STOP;
+ es_cloud_state_set_and_notify(ES_STATE_FAILED_TO_REGISTER_TO_CLOUD, ER_ERRCODE_SYSTEM_ERROR, NULL, NULL);
+ }
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_EXIT);
+
+ return 0;
+}
+
+static int cloud_retry_sign_up(es_cloud_prov_data_s *event_data, timeout_s *timeout)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Enter.");
+
+ pthread_t cthread_handler;
+ es_cloud_event_timeout_s *cloned_data = NULL;
+
+ if (event_data == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "event_data is NULL.");
+ return 0;
+ }
+
+ g_qis_cloud_thread_running = CISESS_STOP_TRIGGER;
+ esm_get_network_status(); // State return
+
+ if ((cloned_data = clone_data_add_timeout(event_data, timeout)) == NULL ||
+#ifdef __ST_THINGS_RTOS__
+ pthread_create_rtos(&cthread_handler, NULL, (pthread_func_type) ci_connection_waiting_loop, (void *)cloned_data, THINGS_STACK_CICONNETION_INIT_THREAD) != 0)
+#else
+ things_thread_create(&cthread_handler, NULL, (pthread_func_type) ci_connection_waiting_loop, (void *)cloned_data) != 0)
+#endif
+ {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Create thread is failed.");
+ things_free(cloned_data);
+ cloned_data = NULL;
+ return 0;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Exit.");
+ return 1;
+}
+
+static void cloud_request_retry_trigger(timeout_s *timeout)
+{
+ // Stored Backup data is base on time-out.
+ es_cloud_prov_data_s *pendedEvent = NULL;
+ if ((pendedEvent = ci_cp_get_pended_data()) != NULL) {
+ ci_cp_del_is_there_cp();
+ cloud_data_cb_esm(pendedEvent); // 1. Last Cloud Provisioning-ed data. or Last Send Failed data.(Sign-UP)
+ } else {
+ cloud_retry_sign_in(timeout); // default. Cloud retry. (Sign-IN / Resource Publish failed data)
+ }
+}
+
+static es_cloud_prov_data_s *if_failed_then_retry(OCDoHandle handle, OCStackResult result, int *n_err)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "latestRequest 0x%X, RespCB:0x%X]", get_request_handle(), handle);
+
+ es_cloud_prov_data_s *pended_data = NULL;
+ es_cloud_prov_data_s *clone_data = NULL;
+ *n_err = 0;
+
+ ci_cp_enter_pend_data_block();
+ if (cas_request_handle(handle, NULL) == 1) {
+ if (result == OC_STACK_COMM_ERROR) { // Don't Send Request Message.
+ if (g_qis_cloud_thread_running != CISESS_APDISCON) {
+ cloud_request_retry_trigger(NULL);
+ }
+ *n_err = 1; // communication error.
+ } else {
+ del_all_request_handle();
+
+ if ((pended_data = ci_cp_get_pended_data()) == NULL) {
+ THINGS_LOG_V(THINGS_INFO, TAG, "Not exist Pended Event Data.");
+ *n_err = 2; // not exist pended_data.
+ goto GOTO_OUT;
+ }
+
+ if ((clone_data = things_malloc(sizeof(es_cloud_prov_data_s))) == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "memory allocation is failed for clone_data.");
+ *n_err = 3; // mem allocation error.
+ goto GOTO_OUT;
+ }
+
+ clone_es_cloud_prov_data(clone_data, pended_data);
+ }
+ } else {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Response Handle(0x%X) is not exist in the Request Handle list.", handle);
+ *n_err = 4;
+ }
+
+GOTO_OUT:
+ ci_cp_release_penddata_block();
+
+ if (*n_err != 1 && *n_err != 4) {
+ ci_cp_del_pended_data();
+ }
+
+ return clone_data;
+}
+
+void ci_stop_cloud_connection(void *CBfunc)
+{
+ force_session_stop(CISESS_NULL);
+ esm_get_network_status(); // State return
+ sleep(1);
+
+ things_res_cb_function = NULL;
+ if (CBfunc) {
+ things_res_cb_function = (things_cloud_con_result_func_type *) CBfunc;
+ }
+}
+static void force_session_stop(ci_session_level_e state)
+{
+ del_all_request_handle();
+ if (state == CISESS_SIGNOUT) {
+ g_qis_cloud_thread_running = CISESS_SIGNOUT;
+ } else {
+ g_qis_cloud_thread_running = CISESS_STOP_TRIGGER;
+ }
+ esm_get_network_status(); // State return
+}
+
+int ci_retry_stop_by_wifi_cb(bool is_retry)
+{
+ if (is_retry == true) { // Last Failed Cloud Connection Retry. (Permanent setting)
+ del_all_request_handle();
+ g_qis_cloud_thread_running = CISESS_STOP;
+ cloud_request_retry_trigger(NULL);
+ } else if (is_retry == false) { // if Cloud Session valid, then Stop Cloud Connection. And Don't Retry.
+ del_all_request_handle();
+ g_qis_cloud_thread_running = CISESS_APDISCON;
+ esm_get_network_status(); // State return
+ }
+
+ return 1;
+}
+
+// -1 : System Error. 0 : No process. 1 : Sign-IN.
+int ci_retry_stop_by_tcp_cb(const char *addr_ip, const int port)
+{
+ int ret = 1;
+
+ pthread_mutex_lock(&g_es_tcp_session_mutex);
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+
+ int ci_port = 0;
+
+ if (g_qis_cloud_thread_running != CISESS_BUSY || g_cloud_port[0] == 0 || g_cloud_ip[0] == 0) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Don't need something process. IP=%s, Port=%s, RunningState=%d", g_cloud_ip, g_cloud_port, g_qis_cloud_thread_running);
+ ret = 0;
+ goto GOTO_OUT;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "IP = %s, port = %d", addr_ip, port); // I expect that ( IP = 52.37.99.111, port = 443 )
+
+ if ((ci_port = atoi(g_cloud_port)) <= 0) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "[Error] Cloud Port is not invalid.(g_cloud_port = %s = %d)", g_cloud_port, ci_port);
+ ret = -1;
+ goto GOTO_OUT;
+ }
+
+ if (strncmp(g_cloud_ip, addr_ip, strlen(addr_ip)) != 0 || ci_port != port) {
+ THINGS_LOG_V(THINGS_INFO, TAG, "We Support IP:Port is \"%s:%s\"", g_cloud_ip, g_cloud_port);
+ if (strncmp(g_cloud_ip, addr_ip, strlen(addr_ip)) != 0) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Delete OIC_Ping for IP=%s.(Cur_Cloud=%s)", addr_ip, g_cloud_ip);
+ oic_ping_unset_mask(addr_ip, PING_ST_ISCLOUD);
+ }
+ ret = 0;
+ goto GOTO_OUT;
+ }
+ // Case Cloud Connection is BUSY & AP Connected.
+ if (es_get_cloud_login_state() == false) {
+ THINGS_LOG_V(THINGS_INFO, TAG, "process Re-Transmission in Time-Out Process instated of this.");
+ ret = 0;
+ goto GOTO_OUT;
+ }
+ // Force Strong Re Sign-IN or new Sign-UP start.
+ force_session_stop(CISESS_SIGNOUT);
+ cloud_request_retry_trigger(NULL);
+
+GOTO_OUT:
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_EXIT);
+ pthread_mutex_unlock(&g_es_tcp_session_mutex);
+
+ return ret;
+}
+
+bool es_cloud_session_stop_trigger(things_es_enrollee_state_e es_state)
+{
+ //THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+
+ if (g_qis_cloud_thread_running != CISESS_APDISCON) {
+ if ((g_qis_cloud_thread_running == CISESS_STOP_TRIGGER || (ES_STATE_INIT <= es_state && es_state <= ES_STATE_CONNECTED_TO_ENROLLER))
+ && g_qis_cloud_thread_running != CISESS_SIGNOUT && es_get_cloud_login_state() == true) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Sign-Out Start.");
+ log_in_out_to_cloud(false, NULL);
+ return true;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "es_state=%s, get_enrollee_state()=%s", get_prov_status(es_state), get_prov_status(get_enrollee_state()));
+
+ if (ES_STATE_INIT <= es_state && es_state <= ES_STATE_CONNECTED_TO_ENROLLER) {
+ if (g_qis_cloud_thread_running != CISESS_BUSY && g_qis_cloud_thread_running != CISESS_APDISCON && es_get_cloud_login_state() == false) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Setting Cloud Semaphore init.");
+ g_qis_cloud_thread_running = CISESS_STOP;
+ }
+ }
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "g_qis_cloud_thread_running=%d", g_qis_cloud_thread_running);
+
+ //THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_EXIT);
+
+ return false;
+}
+
+static int es_cloud_state_set_and_notify(things_cloud_status_e state, es_error_code_e es_err, OCClientResponse *response, ci_error_code_e *ci_err)
+{
+ const char *strState = get_prov_status(state);
+
+ if (strState == NULL || strncmp(strState, "UNKNOWN", strlen("UNKNOWN")) == 0 || state == ES_STATE_INIT || state == ES_STATE_CONNECTED_TO_ENROLLER) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "state is invalid value(%d)", state);
+ return -1;
+ }
+
+ if (es_set_state(state) == ES_ERROR) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Cloud State(%s) is failed.", strState);
+ return 1;
+ }
+
+ if (response != NULL && ci_err != NULL) {
+ // Method don't care because issue is not occurred by it.
+ if (get_cloud_code(response, OC_REST_POST, ci_err) == 0) {
+ *ci_err = ERRCI_UNKNOWN;
+ }
+
+ es_set_cloud_error_code(*ci_err);
+ } else {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Provisioning last_err_code = %d", es_err);
+ if (es_err == ES_ERRCODE_UNKNOWN) {
+ es_set_cloud_error_code(ERRCI_UNKNOWN);
+ } else {
+ es_set_error_code(es_err);
+ }
+ }
+
+ prov_rsc_notify_all_observers();
+
+ switch (state) {
+ case ES_STATE_FAILED_TO_REGISTER_TO_CLOUD:
+ case ES_STATE_FAILED_TO_PUBLISH_RESOURCES_TO_CLOUD:
+ ci_finish_cloud_con(0);
+ break;
+ case ES_STATE_PUBLISHED_RESOURCES_TO_CLOUD:
+ ci_finish_cloud_con(1);
+ break;
+ }
+
+ return 0;
+}
+
+void es_cloud_signup_clear(es_cloud_signup_s *data)
+{
+ if (data == NULL) {
+ return;
+ }
+
+ if (data->domain != NULL) {
+ things_free(data->domain);
+ data->domain = NULL;
+ }
+
+ if (data->address != NULL) {
+ things_free(data->address);
+ data->address = NULL;
+ }
+
+ if (data->port != NULL) {
+ things_free(data->port);
+ data->port = NULL;
+ }
+
+ if (data->access_token != NULL) {
+ things_free(data->access_token);
+ data->access_token = NULL;
+ }
+
+ if (data->refresh_token != NULL) {
+ things_free(data->refresh_token);
+ data->refresh_token = NULL;
+ }
+
+ if (data->token_type != NULL) {
+ things_free(data->token_type);
+ data->token_type = NULL;
+ }
+
+ if (data->certificate != NULL) {
+ things_free(data->certificate);
+ data->certificate = NULL;
+ }
+
+ if (data->redirect_uri != NULL) {
+ things_free(data->redirect_uri);
+ data->redirect_uri = NULL;
+ }
+
+ if (data->sid != NULL) {
+ things_free(data->sid);
+ data->sid = NULL;
+ }
+
+ if (data->uid != NULL) {
+ things_free(data->uid);
+ data->uid = NULL;
+ }
+
+ data->expire_time = CLOUD_EXPIRESIN_INVALID;
+
+ things_free(data);
+}
+
+bool es_cloud_signup_init(es_cloud_signup_s **data)
+{
+ if (data == NULL) {
+ return false;
+ }
+
+ if (*data != NULL) {
+ es_cloud_signup_clear(*data);
+ *data = NULL;
+ }
+
+ *data = (es_cloud_signup_s *) things_malloc(sizeof(es_cloud_signup_s));
+ if (*data == NULL) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "ESCloud_SignedUp struct data is NULL.");
+ return false;
+ }
+
+ (*data)->domain = NULL;
+ (*data)->address = NULL;
+ (*data)->port = NULL;
+ (*data)->access_token = NULL;
+ (*data)->refresh_token = NULL;
+ (*data)->certificate = NULL;
+ (*data)->expire_time = CLOUD_EXPIRESIN_INVALID;
+ (*data)->redirect_uri = NULL;
+ (*data)->sid = NULL;
+ (*data)->token_type = NULL;
+ (*data)->uid = NULL;
+
+ return true;
+}
+
+void *es_cloud_init(things_server_builder_s *server_builder)
+{
+ unsigned int time_v = (unsigned int)time(NULL);
+
+ if (time_v == -1) {
+ THINGS_LOG_D(THINGS_INFO, TAG, "Random Number Initialization is Failed.");
+ } else {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Random Number Initialization is Success.");
+ srand(time_v);
+ }
+
+ if (oic_ping_init() == false) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "OICPing init is failed.");
+ return NULL;
+ }
+
+ del_all_request_handle();
+ memset(g_cloud_ip, 0, IP_PORT);
+ memset(g_cloud_port, 0, IP_PORT);
+ g_server_builder = server_builder;
+ g_resource_lists = NULL;
+ g_len = 0;
+// gDelDeviceCompletFunc = NULL;
+ send_cnt_sign_up = 0;
+ retranslate_rsc_publish_cnt = 0;
+
+ ci_cp_init_event_pend();
+
+ CARegisterNetworkMonitorHandler((CAAdapterStateChangedCB) things_adapter_state_cb, (CAConnectionStateChangedCB) things_tcp_session_state_cb);
+
+ return (void *)g_server_builder;
+}
+
+void es_cloud_terminate(void)
+{
+ force_session_stop(CISESS_NULL);
+ ci_cp_del_pended_data();
+ ci_cp_del_is_there_cp();
+
+ CAUnregisterNetworkMonitorHandler((CAAdapterStateChangedCB) things_adapter_state_cb, (CAConnectionStateChangedCB) things_tcp_session_state_cb);
+
+ esm_get_network_status();
+
+ es_cloud_signup_clear(signed_up_data);
+ signed_up_data = NULL;
+ memset(g_cloud_address, 0, MAX_CI_ADDRESS);
+ memset(g_cloud_ip, 0, IP_PORT);
+ memset(g_cloud_port, 0, IP_PORT);
+
+ g_server_builder = NULL;
+ g_resource_lists = NULL;
+ g_len = 0;
+
+// gDelDeviceCompletFunc = NULL;
+ send_cnt_sign_up = 0;
+ retranslate_rsc_publish_cnt = 0;
+
+ oic_ping_terminate();
+}
+static int get_cloud_code(OCClientResponse *response, OCMethod method, ci_error_code_e *err)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Enter");
+
+ int ret = 0;
+ OCRepPayloadValue *val = NULL;
+ CAResponseResult_t rawResult = CA_EMPTY;
+
+ if (response == NULL || response->payload == NULL || err == NULL || method == OC_REST_NOMETHOD) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "response(0x%X) or err(0x%X) is NULL", response, err);
+ return ret;
+ }
+
+ rawResult = things_result_to_network_result(response->result, method);
+ *err = rawResult * ERR_UPPER_UNIT;
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "result = %d, rawResult = %d, method = %d, *err = %d", response->result, rawResult, method, *err);
+
+ val = ((OCRepPayload *) response->payload)->values;
+
+ while (val != NULL) {
+ if (strncmp(val->name, CLOUD_ERROR_CODE, strlen(CLOUD_ERROR_CODE)) == 0) {
+ if (val->type != OCREP_PROP_INT) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "DataType of Cloud-Err-Code is not Integer.");
+ } else {
+ *err += (ci_error_code_e) val->i;
+ ret = 1;
+ }
+
+ break;
+ }
+
+ val = val->next;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "*err = %d, ret = %d", *err, ret);
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Exit");
+ return ret;
+}
+
+static CAResponseResult_t things_result_to_network_result(OCStackResult oc_code, OCMethod method)
+{
+ CAResponseResult_t ret = CA_EMPTY;
+
+ switch (oc_code) {
+ case OC_STACK_OK:
+ switch (method) {
+ case OC_REST_PUT:
+ case OC_REST_POST:
+ // This Response Code is like HTTP 204 "No Content" but only used in
+ // response to POST and PUT requests.
+ ret = CA_CHANGED;
+ break;
+ case OC_REST_GET:
+ // This Response Code is like HTTP 200 "OK" but only used in response to
+ // GET requests.
+ ret = CA_CONTENT;
+ break;
+ default:
+ // This should not happen but,
+ // give it a value just in case but output an error
+ ret = CA_CONTENT;
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Unexpected OC_STACK_OK return code for method [%d].", method);
+ }
+ break;
+ case OC_STACK_RESOURCE_CREATED:
+ ret = CA_CREATED;
+ break;
+ case OC_STACK_RESOURCE_DELETED:
+ ret = CA_DELETED;
+ break;
+ case OC_STACK_RESOURCE_CHANGED:
+ ret = CA_CHANGED;
+ break;
+ case OC_STACK_INVALID_QUERY:
+ ret = CA_BAD_REQ;
+ break;
+ case OC_STACK_INVALID_OPTION:
+ ret = CA_BAD_OPT;
+ break;
+ case OC_STACK_FORBIDDEN_REQ:
+ ret = CA_FORBIDDEN_REQ;
+ break;
+ case OC_STACK_NO_RESOURCE:
+ ret = CA_NOT_FOUND;
+ break;
+ case OC_STACK_COMM_ERROR:
+ ret = CA_RETRANSMIT_TIMEOUT;
+ break;
+ case OC_STACK_UNAUTHORIZED_REQ:
+ ret = CA_UNAUTHORIZED_REQ;
+ break;
+ case OC_STACK_INTERNAL_SERVER_ERROR:
+ ret = CA_INTERNAL_SERVER_ERROR;
+ break;
+ default:
+ break;
+ }
+ return ret;
+}
+
+static char *make_ip_port(char *p_ip, char *p_port)
+{
+ char *ipport = NULL;
+ int length = 0;
+
+ if (p_ip == NULL || p_port == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "IP=%s, or Port=%s is NULL.", p_ip, p_port);
+ return NULL;
+ }
+
+ length = strlen(p_ip) + strlen(p_port) + 2;
+ if ((ipport = (char *)things_malloc(length)) == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Memory allocation is failed.");
+ return NULL;
+ }
+
+ memset(ipport, 0, length);
+ if (things_strcat(ipport, length, p_ip) == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "things_strcat is failed.");
+ things_free(ipport);
+ return NULL;
+ }
+ ipport[strlen(p_ip)] = ':';
+ if (things_strcat(ipport, length, p_port) == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "things_strcat is failed.");
+ things_free(ipport);
+ return NULL;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "IP=%s, Port=%s, ipport=%s", p_ip, p_port, ipport);
+ return ipport;
+}
+
+static es_cloud_event_timeout_s *clone_data_add_timeout(es_cloud_prov_data_s *cloud_data, timeout_s *timeout)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+
+ es_cloud_event_timeout_s *cloned_data = NULL;
+
+ if (cloud_data == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "cloud_data is NULL.");
+ return NULL;
+ }
+
+ if ((cloned_data = (es_cloud_event_timeout_s *) things_malloc(sizeof(es_cloud_event_timeout_s) * 1)) == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Memory allocation is failed.");
+ return NULL;
+ }
+
+ clone_es_cloud_prov_data(&cloned_data->event, cloud_data);
+
+ if (timeout == NULL) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Default Setting to cloned Cloud Data.");
+ cloned_data->timeOut.cur_counter = DEFAULT_TIMEOUT;
+ cloned_data->timeOut.cur_num = DEFAULT_TIMEOUT;
+ cloned_data->timeOut.ori_num = DEFAULT_TIMEOUT;
+ } else {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Custom Setting to cloned Cloud Data.");
+ cloned_data->timeOut.cur_counter = timeout->cur_counter;
+ cloned_data->timeOut.cur_num = timeout->cur_num;
+ cloned_data->timeOut.ori_num = timeout->ori_num;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "cur_counter = %d, cur_num = %d, ori_num = %d", cloned_data->timeOut.cur_counter, cloned_data->timeOut.cur_num, cloned_data->timeOut.ori_num);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "cloned_data add= 0x%X", cloned_data);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_EXIT);
+ return cloned_data;
+}
+
+static void ci_finish_cloud_con(int result)
+{
+ char *domain = NULL;
+ char *access_token = NULL;
+ es_cloud_signup_s *Cloud_data = NULL;
+
+ if (things_res_cb_function) {
+ dm_load_legacy_cloud_data(&Cloud_data); // TODO read Cloud-Data.
+ if (Cloud_data != NULL) {
+ if (Cloud_data->domain != NULL) {
+ domain = strdup(Cloud_data->domain);
+ }
+ if (Cloud_data->access_token != NULL) {
+ access_token = strdup(Cloud_data->access_token);
+ }
+ }
+
+ things_res_cb_function(result, domain, access_token);
+ things_res_cb_function = NULL;
+ }
+
+ if (domain) {
+ things_free(domain);
+ domain = NULL;
+ }
+
+ if (access_token) {
+ things_free(access_token);
+ access_token = NULL;
+ }
+}
+
+static void publish_dev_profile_into_cloud(timeout_s *timeout)
+{
+ if (things_cloud_dev_profile_publish(g_cloud_address, handle_dev_profile_cb, handle_dev_profile_timeout, timeout) != OC_STACK_OK) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Publish Device Profile request is failed.");
+ }
+}
--- /dev/null
+/****************************************************************************\r
+ *\r
+ * Copyright 2017 Samsung Electronics All Rights Reserved.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing,\r
+ * software distributed under the License is distributed on an\r
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,\r
+ * either express or implied. See the License for the specific\r
+ * language governing permissions and limitations under the License.\r
+ *\r
+ ****************************************************************************/\r
+\r
+#ifndef _CLOUD_CONNECTOR_H_\r
+#define _CLOUD_CONNECTOR_H_\r
+\r
+#include "ocstack.h"\r
+#include "things_resource.h"\r
+#include "things_wait_handler.h"\r
+#include "es_common.h"\r
+\r
+#define DEFAULT_CONTEXT_VALUE 0x99\r
+\r
+#define KEY_TOKEN_ACCESS "accesstoken" // mandatory\r
+#define KEY_TOKEN_ACCESS_REFRESH "refreshtoken" // mandatory\r
+#define KEY_TOKEN_TYPE "token_type" // mandatory\r
+#define KEY_EXPIRE_TIME "expiresin" // mandatory\r
+#define KEY_ID_USER "uid" // mandatory\r
+#define KEY_SERVER_REDIRECT_URI "redirect_uri" // option\r
+#define KEY_CERTIFICATE_FILE "certificate" // option\r
+#define KEY_SERVER_ID "sid" // option\r
+#define KEY_ID_DEVICE "di"\r
+#define KEY_LOGINOUT "login"\r
+#define KEY_ICORE_VER "coreversion"\r
+#define KEY_IOTIVITY_VER "verticalversion"\r
+#define KEY_TYPE_GRANT "granttype"\r
+#define CLOUD_ERROR_CODE "code"\r
+#define VALUE_TYPE_GRANT_TOKEN "refresh_token"\r
+\r
+\r
+int ci_connection_pre_check(const char *domain_name, char **p_ip);\r
+\r
+\r
+OCStackResult things_cloud_signup(const char *host,\r
+ const char *device_id,\r
+ const es_cloud_prov_data_s *event_data,\r
+ OCClientResponseHandler response,\r
+ check_time_out_call_func timeout_handler,\r
+ timeout_s *timeout);\r
+\r
+OCStackResult things_cloud_session(const char *host,\r
+ const char *uId,\r
+ const char *device_id,\r
+ const char *accesstoken,\r
+ bool is_login,\r
+ OCClientResponseHandler response,\r
+ check_time_out_call_func timeout_handler,\r
+ timeout_s *timeout);\r
+\r
+OCStackResult things_cloud_rsc_publish(char *host,\r
+ things_resource_s **list,\r
+ int length,\r
+ OCClientResponseHandler response,\r
+ check_time_out_call_func timeout_handler,\r
+ timeout_s *timeout);\r
+\r
+OCStackResult things_cloud_rsc_publish_with_device_id(char *host,\r
+ const char *id,\r
+ things_resource_s **list,\r
+ int length,\r
+ OCClientResponseHandler response,\r
+ check_time_out_call_func timeout_handler,\r
+ timeout_s *timeout);\r
+\r
+OCStackResult things_cloud_dev_profile_publish(char *host,\r
+ OCClientResponseHandler response,\r
+ check_time_out_call_func timeout_handler,\r
+ timeout_s *timeout);\r
+\r
+OCStackResult things_cloud_refresh(const char *host,\r
+ const char *uId,\r
+ const char *device_id,\r
+ const char *refreshtoken,\r
+ OCClientResponseHandler response);\r
+\r
+extern OCStackResult things_cloud_topic_publish_topic(const char *host,\r
+ const char *topic,\r
+ OCRepPayload *payload,\r
+ OCClientResponseHandler response);\r
+\r
+#endif /* \r
+ */\r
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 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.
+ *
+ ****************************************************************************/
+
+#ifndef CLOUD_EVENTDATA_PENDING_PROCESS
+#define CLOUD_EVENTDATA_PENDING_PROCESS
+
+#include "es_common.h"
+
+typedef struct es_cloud_pending_event_s {
+ bool exist;
+ bool is_there_ci_prov;
+ int using_count;
+ es_cloud_prov_data_s event;
+} es_cloud_pending_event_s;
+
+void ci_cp_init_event_pend(void);
+
+es_cloud_prov_data_s *ci_cp_get_pended_data(void);
+
+bool ci_cp_get_is_there_cp(void);
+
+bool ci_cp_cas_is_there_cp_if_false(void);
+
+void ci_cp_del_pended_data(void);
+
+void ci_cp_del_is_there_cp(void);
+
+int ci_cp_pend_event_data(es_cloud_prov_data_s *event_data);
+
+int ci_cp_enter_pend_data_block(void);
+
+int ci_cp_release_penddata_block(void);
+
+#endif // CLOUD_EVENTDATA_PENDING_PROCESS
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 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.
+ *
+ ****************************************************************************/
+
+#ifndef _CLOUD_MANAGER_H_
+#define _CLOUD_MANAGER_H_
+
+#include "things_resource.h"
+#include "es_common.h"
+#include "cloud_connector.h"
+#include "things_server_builder.h"
+#include <stdint.h>
+
+#define CI_COMMON_REFRESH_TIME 12 // access token Refresh period time without accesstoken-expire. (unit: hour)
+#define CI_TOKEN_EXPIRECHECK_TIME 3000 // access token Check period time whether it's expired or available. (unit: second)
+
+#define CLOUD_EXPIRESIN_INVALID -1
+
+#ifdef __SECURED__
+#define DEFAULT_COAP_TCP_HOST "coaps+tcp://"
+#define UNSUPPORT_COAP_TCP_HOST "coap+tcp://"
+#define DEFAULT_COAP_PORT "443"
+#else
+#define DEFAULT_COAP_TCP_HOST "coap+tcp://"
+#define UNSUPPORT_COAP_TCP_HOST "coaps+tcp://"
+#define DEFAULT_COAP_PORT "5683"
+#endif
+
+typedef enum rp_target_e {
+ RSC_PUB_ALL = 0,
+ RSC_PUB_MAIN_ONLY = 1,
+ RSC_PUB_SUB_ALL = 2,
+ RSC_PUB_NEED_SUB_ONLY = 3,
+} rp_target_e;
+
+typedef struct es_cloud_signup_s {
+ char *domain;
+ char *address;
+ char *port;
+ char *access_token;
+ char *refresh_token;
+ char *token_type;
+ int64_t expire_time;
+ char *uid;
+ char *redirect_uri;
+ char *certificate;
+ char *sid;
+} es_cloud_signup_s;
+
+void *es_cloud_init(things_server_builder_s *server_builder);
+
+void es_cloud_terminate(void);
+
+void es_cloud_signup_clear(es_cloud_signup_s *data);
+
+bool es_cloud_signup_init(es_cloud_signup_s **data);
+
+bool es_cloud_session_stop_trigger(things_es_enrollee_state_e es_state);
+
+OCStackResult publish_resource_into_cloud(rp_target_e target, timeout_s *timeout);
+
+OCStackResult log_in_out_to_cloud(bool value, timeout_s *timeout);
+
+OCStackResult find_cloud_resource(void);
+
+OCStackResult refresh_token_into_cloud(void);
+
+void *cloud_data_cb_esm(es_cloud_prov_data_s *event_data);
+
+int cloud_retry_sign_in(timeout_s *timeout);
+
+int ci_retry_stop_by_wifi_cb(bool is_retry);
+
+int ci_retry_stop_by_tcp_cb(const char *addr_ip, const int port);
+
+int push_notification_to_cloud(const char *uri, OCRepPayload *payload);
+
+void ci_stop_cloud_connection(void *cb_func);
+
+#endif // _CLOUD_MANAGER_H_
--- /dev/null
+###########################################################################
+#
+# Copyright 2017 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.
+#
+###########################################################################
+
+CSRCS += easysetup.c easysetup_manager.c resource_handler.c
+
+DEPPATH += --dep-path src/st_things/things_stack/src/common/easy-setup
+VPATH += :src/st_things/things_stack/src/common/easy-setup
\ No newline at end of file
--- /dev/null
+/* ****************************************************************
+ *
+ * Copyright 2017 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 "octypes.h"
+#include "easysetup.h"
+#include "things_logger.h"
+#include "resource_handler.h"
+#include "oic_string.h"
+#include "cloud_manager.h"
+#include "things_api.h"
+
+#define ES_ENROLLEE_TAG "[easysetup]"
+
+static bool g_is_secured = false;
+
+static es_provisioning_callbacks_s g_es_provisioning_cb;
+static es_device_property g_es_device_property;
+static things_get_easysetup_state_func_type g_notify_easysetup_state = NULL;
+
+void es_register_notify_easysetup_state(void *func)
+{
+ g_notify_easysetup_state = (things_get_easysetup_state_func_type) func;
+}
+
+void ESWiFiRsrcCallback(es_result_e es_result, es_wifi_prov_data_s *event_data)
+{
+ THINGS_LOG_D(THINGS_DEBUG, ES_ENROLLEE_TAG, "ESWiFiRsrcCallback IN");
+
+ if (es_result != ES_OK) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, ES_ENROLLEE_TAG, "ESWiFiRsrcCallback ES_ERROR Occured");
+ return;
+ }
+ // deliver data to es_provisioning_callbacks_s
+ if (g_es_provisioning_cb.wifi_prov_cb != NULL) {
+ g_es_provisioning_cb.wifi_prov_cb(event_data);
+ } else {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, ES_ENROLLEE_TAG, "wifi_prov_cb is NULL");
+ return;
+ }
+}
+
+void ESCloudRsrcCallback(es_result_e es_resoult, es_cloud_prov_data_s *event_data)
+{
+ THINGS_LOG_D(THINGS_DEBUG, ES_ENROLLEE_TAG, "ESCloudRsrcCallback IN");
+
+ if (es_resoult != ES_OK) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, ES_ENROLLEE_TAG, "ESCloudRsrcCallback ES_ERROR Occured");
+ return;
+ }
+
+ if (g_es_provisioning_cb.cloud_data_prov_cb != NULL) {
+ g_es_provisioning_cb.cloud_data_prov_cb(event_data);
+ } else {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, ES_ENROLLEE_TAG, "cloud_data_prov_cb is NULL");
+ return;
+ }
+}
+
+void ESDevconfRsrcallback(es_result_e es_resoult, es_dev_conf_prov_data_s *event_data)
+{
+ THINGS_LOG_D(THINGS_DEBUG, ES_ENROLLEE_TAG, "ESDevconfRsrcallback IN");
+
+ if (es_resoult != ES_OK) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, ES_ENROLLEE_TAG, "ESDevconfRsrcallback ES_ERROR Occured");
+ return;
+ }
+
+ if (g_es_provisioning_cb.dev_conf_prov_cb != NULL) {
+ g_es_provisioning_cb.dev_conf_prov_cb(event_data);
+ } else {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, ES_ENROLLEE_TAG, "dev_conf_prov_cb is NULL");
+ return;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, ES_ENROLLEE_TAG, "ESDevconfRsrcallback OUT");
+}
+
+es_result_e es_init_enrollee(bool is_secured, es_resource_mask_e resource_mask, es_provisioning_callbacks_s callbacks)
+{
+ THINGS_LOG_D(THINGS_DEBUG, ES_ENROLLEE_TAG, "es_init_enrollee IN");
+
+ g_is_secured = is_secured;
+ g_es_provisioning_cb.wifi_prov_cb = NULL;
+ g_es_provisioning_cb.dev_conf_prov_cb = NULL;
+ g_es_provisioning_cb.cloud_data_prov_cb = NULL;
+
+ if ((resource_mask & ES_WIFI_RESOURCE) == ES_WIFI_RESOURCE) {
+ if (callbacks.wifi_prov_cb != NULL) {
+ g_es_provisioning_cb.wifi_prov_cb = callbacks.wifi_prov_cb;
+ register_wifi_rsrc_event_callback(ESWiFiRsrcCallback);
+ } else {
+ THINGS_LOG_ERROR(THINGS_ERROR, ES_ENROLLEE_TAG, "wifi_prov_cb NULL");
+ return ES_ERROR;
+ }
+ }
+ if ((resource_mask & ES_DEVCONF_RESOURCE) == ES_DEVCONF_RESOURCE) {
+ if (callbacks.dev_conf_prov_cb != NULL) {
+ g_es_provisioning_cb.dev_conf_prov_cb = callbacks.dev_conf_prov_cb;
+ register_dev_conf_rsrc_event_callback(ESDevconfRsrcallback);
+ } else {
+ THINGS_LOG_ERROR(THINGS_ERROR, ES_ENROLLEE_TAG, "dev_conf_prov_cb NULL");
+ return ES_ERROR;
+ }
+ }
+ if ((resource_mask & ES_CLOUD_RESOURCE) == ES_CLOUD_RESOURCE) {
+ if (callbacks.cloud_data_prov_cb != NULL) {
+ g_es_provisioning_cb.cloud_data_prov_cb = callbacks.cloud_data_prov_cb;
+ register_cloud_rsrc_event_callback(ESCloudRsrcCallback);
+ } else {
+ THINGS_LOG_ERROR(THINGS_ERROR, ES_ENROLLEE_TAG, "cloud_data_prov_cb NULL");
+ return ES_ERROR;
+ }
+ }
+
+ if (create_easysetup_resources(g_is_secured, resource_mask) != OC_STACK_OK) {
+ unregister_resource_event_callback();
+
+ if (delete_easysetup_resources() != OC_STACK_OK) {
+ THINGS_LOG_ERROR(THINGS_ERROR, ES_ENROLLEE_TAG, "Deleting prov resource ES_ERROR!!");
+ }
+
+ return ES_ERROR;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, ES_ENROLLEE_TAG, "es_init_enrollee OUT");
+ return ES_OK;
+}
+
+things_es_enrollee_state_e es_get_state(void)
+{
+ return get_enrollee_state();
+}
+
+bool es_get_cloud_login_state(void)
+{
+ switch (get_enrollee_state()) {
+ case ES_STATE_REGISTERED_TO_CLOUD:
+ case ES_STATE_PUBLISHING_RESOURCES_TO_CLOUD:
+ case ES_STATE_PUBLISHED_RESOURCES_TO_CLOUD:
+ case ES_STATE_FAILED_TO_PUBLISH_RESOURCES_TO_CLOUD:
+ return true;
+ }
+
+ return false;
+}
+
+es_result_e es_set_device_property(es_device_property *device_property)
+{
+ THINGS_LOG_D(THINGS_DEBUG, ES_ENROLLEE_TAG, "es_set_device_property IN");
+
+ if (set_device_property(device_property) != OC_STACK_OK) {
+ THINGS_LOG_ERROR(THINGS_ERROR, ES_ENROLLEE_TAG, "es_set_device_property ES_ERROR");
+ return ES_ERROR;
+ }
+
+ int mode_idx = 0;
+ while ((device_property->WiFi).mode[mode_idx] != WiFi_EOF) {
+ (g_es_device_property.WiFi).mode[mode_idx] = (device_property->WiFi).mode[mode_idx];
+ THINGS_LOG_D(THINGS_DEBUG, ES_ENROLLEE_TAG, "WiFi Mode : %d", (g_es_device_property.WiFi).mode[mode_idx]);
+ mode_idx++;
+ }
+ (g_es_device_property.WiFi).freq = (device_property->WiFi).freq;
+ THINGS_LOG_D(THINGS_DEBUG, ES_ENROLLEE_TAG, "WiFi Freq : %d", (g_es_device_property.WiFi).freq);
+
+ things_strncpy((g_es_device_property.dev_conf_s).device_name, (device_property->dev_conf_s).device_name, MAX_DEVICELEN);
+ THINGS_LOG_D(THINGS_DEBUG, ES_ENROLLEE_TAG, "Device Name : %s", (g_es_device_property.dev_conf_s).device_name);
+
+ THINGS_LOG_D(THINGS_DEBUG, ES_ENROLLEE_TAG, "es_set_device_property OUT");
+ return ES_OK;
+}
+
+es_result_e es_set_state(things_es_enrollee_state_e es_state)
+{
+ //THINGS_LOG_D(THINGS_DEBUG, ES_ENROLLEE_TAG, "es_set_state IN");
+ OCStackResult res = OC_STACK_ERROR;
+
+ if (es_state < ES_STATE_INIT || es_state >= ES_STATE_EOF) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, ES_ENROLLEE_TAG, "Invalid things_es_enrollee_state_e : %d", es_state);
+ return ES_ERROR;
+ }
+
+ if (es_cloud_session_stop_trigger(es_state) == true) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, ES_ENROLLEE_TAG, "Cloud Connection Log-Out ing...");
+ return ES_ERROR;
+ }
+
+ if ((res = set_enrollee_state(es_state)) == OC_STACK_ERROR) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, ES_ENROLLEE_TAG, "es_set_state setting is failed.");
+ return ES_ERROR;
+ }
+
+ if (g_notify_easysetup_state != NULL && res == OC_STACK_OK) {
+ THINGS_LOG_D(THINGS_DEBUG, ES_ENROLLEE_TAG, "Notify Easy-Setup State to THINGS_APP. %d", es_state);
+ g_notify_easysetup_state(es_state);
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, ES_ENROLLEE_TAG, "Set ESState succesfully : %d", es_state);
+ //THINGS_LOG_D(THINGS_DEBUG, ES_ENROLLEE_TAG, "es_set_state OUT");
+ return ES_OK;
+}
+
+static es_error_code_e ci_errcode_to_es_errcode(ci_error_code_e cm_err_code)
+{
+ es_error_code_e es_err_code = ES_ERRCODE_NO_ERROR;
+
+ switch (cm_err_code) {
+ case ERRCI_NO_ERROR:
+ case ERRCI_SUCCESS:
+ es_err_code = ES_ERRCODE_NO_ERROR;
+ break;
+ case ERRCI_SAMSUNG_ACCOUNT_AUTHORIZATION_FAILED:
+ case ERRCI_SAMSUNG_ACCOUNT_UNAUTHORIZED_TOKEN:
+ es_err_code = ES_ERRCODE_INVALID_AUTHCODE;
+ break;
+ case ERRCI_TOKEN_VALIDATION_FAILED:
+ es_err_code = ES_ERRCODE_INVALID_ACCESSTOKEN;
+ break;
+ case ERRCI_DEVICE_NOT_FOUND:
+ es_err_code = ES_ERRCODE_FAILED_TO_FIND_REGISTERED_DEVICE_IN_CLOUD;
+ break;
+ case ERRCI_USER_NOT_FOUND:
+ es_err_code = ES_ERRCODE_FAILED_TO_FIND_REGISTERED_USER_IN_CLOUD;
+ break;
+ default:
+ es_err_code = ES_ERRCODE_UNKNOWN;
+ break;
+ }
+
+ return es_err_code;
+}
+
+es_result_e es_set_error_code(es_error_code_e es_err_code)
+{
+ THINGS_LOG_D(THINGS_DEBUG, ES_ENROLLEE_TAG, "es_set_error_code IN");
+
+ if (es_err_code < ES_ERRCODE_NO_ERROR || es_err_code > ES_ERRCODE_UNKNOWN) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, ES_ENROLLEE_TAG, "Invalid es_set_error_code : %d", es_err_code);
+ return ES_ERROR;
+ }
+
+ if (set_enrollee_err_code(es_err_code) != OC_STACK_OK) {
+ THINGS_LOG_ERROR(THINGS_ERROR, ES_ENROLLEE_TAG, "es_set_error_code ES_ERROR");
+ return ES_ERROR;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, ES_ENROLLEE_TAG, "Set es_error_code_e successfully : %d", es_err_code);
+ return ES_OK;
+}
+
+es_result_e es_set_cloud_error_code(ci_error_code_e es_err_code)
+{
+ THINGS_LOG_D(THINGS_DEBUG, ES_ENROLLEE_TAG, "es_set_cloud_error_code IN");
+
+ es_error_code_e esError = ES_ERRCODE_NO_ERROR;
+
+ if (es_err_code < ERRCI_NO_ERROR || es_err_code > ERRCI_UNKNOWN) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, ES_ENROLLEE_TAG, "Invalid es_set_cloud_error_code : %d", es_err_code);
+ return ES_ERROR;
+ }
+
+ esError = ci_errcode_to_es_errcode(es_err_code);
+
+ if (set_cloud_err_code(es_err_code) != OC_STACK_OK) {
+ THINGS_LOG_ERROR(THINGS_ERROR, ES_ENROLLEE_TAG, "es_set_cloud_error_code ES_ERROR");
+ return ES_ERROR;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, ES_ENROLLEE_TAG, "Set es_error_code_e successfully : %d", es_err_code);
+
+ es_set_error_code(esError);
+
+ THINGS_LOG_D(THINGS_DEBUG, ES_ENROLLEE_TAG, "es_set_cloud_error_code OUT");
+ return ES_OK;
+}
+
+es_result_e es_terminate_enrollee()
+{
+ THINGS_LOG_D(THINGS_DEBUG, ES_ENROLLEE_TAG, "es_terminate_enrollee IN");
+
+ unregister_resource_event_callback();
+
+ //Delete Prov resource
+ if (delete_easysetup_resources() != OC_STACK_OK) {
+ THINGS_LOG_ERROR(THINGS_ERROR, ES_ENROLLEE_TAG, "Deleting prov resource ES_ERROR!!");
+ return ES_ERROR;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, ES_ENROLLEE_TAG, "es_terminate_enrollee success");
+ return ES_OK;
+}
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 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.
+ *
+ ****************************************************************************/
+
+#define _POSIX_C_SOURCE 200809L
+#define _BSD_SOURCE // for the usleep
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <pthread.h>
+#include <errno.h>
+#include <sys/select.h>
+
+#include "../utils/inc/things_network.h"
+#include "things_wait_handler.h"
+#include "easysetup_manager.h"
+#include "resource_handler.h"
+#include "cloud_manager.h"
+#include "easysetup.h"
+#include "things_logger.h"
+#include "things_malloc.h"
+
+#include "things_thread.h"
+#include "things_rtos_util.h"
+
+#ifdef __SECURED__
+#include "pinoxmcommon.h"
+#include "oxmverifycommon.h"
+#endif // #ifdef __SECURED__
+
+#define TAG "[ezsetup-mg]"
+#define MAX_REFRESHCHECK_CNT 30 // 30 times
+
+es_dev_conf_prov_data_s *g_dev_conf_prov_data = NULL;
+es_wifi_prov_data_s *g_wifi_prov_data = NULL;
+es_cloud_prov_data_s *g_cloud_prov_data = NULL;
+
+static things_server_builder_s *g_server_builder = NULL;
+static things_update_dev_prov_data_func_type g_update_dev_prov_data = NULL;
+static pin_generated_func_type g_pin_generated_cb = NULL;
+static pin_close_func_type g_pin_close_cb = NULL;
+static user_confirm_result_func_type g_user_confirm_cb = NULL;
+
+int esm_continue = 0;
+#ifdef __ST_THINGS_RTOS__
+int ci_token_expire_fds[2] = { -1, -1 };
+#endif
+static pthread_t gthread_id_network_status_check = 0;
+static pthread_t gthread_id_cloud_refresh_check = 0;
+
+static const int i_common_sleep_sec = CI_TOKEN_EXPIRECHECK_TIME;
+static const int i_fail_sleep_sec = 60; // 60 sec
+static pthread_mutex_t g_es_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static bool is_set_device_property = false;
+static es_device_property device_property;
+static const char *def_device_name = "ST_Things Device";
+
+void wifi_prov_cb_in_app(es_wifi_prov_data_s *event_data);
+void dev_conf_prov_cb_in_app(es_dev_conf_prov_data_s *event_data);
+void cloud_data_prov_cb_in_app(es_cloud_prov_data_s *event_data);
+
+typedef void (*callback_to_app)(es_cloud_prov_data_s *);
+callback_to_app g_cloud_data_cb_to_app = NULL;
+
+es_provisioning_callbacks_s g_callbacks = {
+ .wifi_prov_cb = &wifi_prov_cb_in_app,
+ .dev_conf_prov_cb = &dev_conf_prov_cb_in_app,
+ .cloud_data_prov_cb = &cloud_data_prov_cb_in_app
+};
+
+static void *wifi_prov_set_loop(void *param);
+static void *cloud_refresh_check_loop(void *param);
+static void *wifi_prov_timeout_handler(timeout_s *param);
+
+#ifdef __SECURED__
+void generate_pin_cb(char *pin, size_t pin_size)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+
+ if (NULL == pin || pin_size <= 0) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "INVALID PIN");
+ return;
+ }
+
+ THINGS_LOG_V(THINGS_INFO, TAG, "PIN CODE : %s", pin);
+
+ // TODO: print out pin number using display panel - ysy
+ if (g_pin_generated_cb) {
+ g_pin_generated_cb(pin, pin_size);
+ } else {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "PIN GENERATED CB Not Registered~!!!");
+ }
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_EXIT);
+}
+
+void pin_close_cb(void)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+
+ // TODO: print out pin number using display panel - ysy
+ if (g_pin_close_cb) {
+ g_pin_close_cb();
+ } else {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "PIN GENERATED CB Not Registered~!!!");
+ }
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_EXIT);
+}
+
+OCStackResult get_user_confirmation(void *ctx)
+{
+ OCStackResult ret = OC_STACK_USER_DENIED_REQ;
+
+ if (g_user_confirm_cb) {
+ int result = g_user_confirm_cb();
+
+ switch (result) {
+ case 1: {
+ THINGS_LOG_V(THINGS_INFO, TAG, "User Confirmed~!!");
+ ret = OC_STACK_OK;
+ break;
+ }
+ default: {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "User Denied~!! : [ %d ]", result);
+ break;
+ }
+ }
+ } else {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "MUTUAL AUTHENTICATION CONFIRM CB Not Registered~!!!");
+ }
+
+ THINGS_LOG_V(THINGS_INFO, TAG, "User Confirm Result : [ %d ]", ret);
+
+ return ret;
+}
+
+#endif //#ifdef __SECURED__
+
+/*******************************************************************
+ *
+ * st_things API Function register
+ *
+ *******************************************************************/
+void esm_register_update_dev_prov_data_func(things_update_dev_prov_data_func_type func)
+{
+ g_update_dev_prov_data = func;
+}
+
+int esm_set_device_property_by_app(char *name, const wifi_mode_e *mode, int ea_mode, const wifi_freq_e freq)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Enter.");
+
+ int i = 0;
+
+ if (mode == NULL || ea_mode < 1 || WiFi_24G > freq || freq >= WiFi_FREQ_EOF) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Invalid Input Arguments.(mode=0x%X, ea_mode=%d, freq=%d)", mode, ea_mode, freq);
+ return 0;
+ }
+
+ if (name == NULL) {
+ name = def_device_name;
+ }
+
+ if (ea_mode > NUM_WIFIMODE - 1) {
+ ea_mode = NUM_WIFIMODE - 1;
+ }
+
+ things_strncpy(device_property.dev_conf_s.device_name, name, sizeof(device_property.dev_conf_s.device_name));
+ device_property.WiFi.freq = freq;
+ for (i = 0; i < ea_mode; i++) {
+ device_property.WiFi.mode[i] = mode[i];
+ }
+ device_property.WiFi.mode[ea_mode] = WiFi_EOF;
+ is_set_device_property = true;
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "device_name=%s, WiFi_frequence=%d, count of WiFi_mode=%d", device_property.dev_conf_s.device_name, device_property.WiFi.freq, ea_mode);
+ for (i = 0; i <= ea_mode; i++) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "WiFi_mode[%d]=%d", i, device_property.WiFi.mode[i]);
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Exit.(result=%d)", is_set_device_property);
+ return 1;
+}
+
+esm_result_e esm_init_easysetup(int restart_flag, things_server_builder_s *server_builder)
+{
+ THINGS_LOG_D(THINGS_INFO, TAG, "Init EasySetup");
+
+ wifi_mode_e wifi_mode[5] = { 0, };
+ wifi_freq_e wifi_freq = dm_get_wifi_property_freq();
+ int wifiIntf = dm_get_wifi_property_interface();
+ int mode_count = 0;
+
+ if (wifiIntf) {
+ if (wifiIntf & 0x01) {
+ wifi_mode[mode_count++] = WiFi_11A;
+ }
+ if (wifiIntf & 0x02) {
+ wifi_mode[mode_count++] = WiFi_11B;
+ }
+ if (wifiIntf & 0x04) {
+ wifi_mode[mode_count++] = WiFi_11G;
+ }
+ if (wifiIntf & 0x08) {
+ wifi_mode[mode_count++] = WiFi_11N;
+ }
+ if (wifiIntf & 0x10) {
+ wifi_mode[mode_count++] = WiFi_11AC;
+ }
+ }
+ esm_set_device_property_by_app(NULL, wifi_mode, mode_count, wifi_freq);
+
+ if (is_set_device_property == false) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "[Error] Please Check whether you call \"OICSetDeviceProperty\" API.(We need value of WiFi-property.)");
+ return ESM_ERROR;
+ }
+
+ if (restart_flag == 1 || g_dev_conf_prov_data || g_wifi_prov_data || g_cloud_prov_data) {
+ THINGS_LOG_D(THINGS_INFO, TAG, "Restart EasySetup");
+ esm_continue = 0;
+ if (gthread_id_cloud_refresh_check) {
+#ifdef __ST_THINGS_RTOS__
+ if (ci_token_expire_fds[1] != -1) {
+ ssize_t len = 0;
+ do {
+ len = write(ci_token_expire_fds[1], "w", 1);
+ } while ((len == -1) && (errno == EINTR));
+ if ((len == -1) && (errno != EINTR) && (errno != EPIPE)) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "write failed: %s", strerror(errno));
+ return ESM_ERROR;
+ }
+ }
+ pthread_join(gthread_id_cloud_refresh_check, NULL);
+ close(ci_token_expire_fds[0]);
+ close(ci_token_expire_fds[1]);
+ ci_token_expire_fds[0] = -1;
+ ci_token_expire_fds[1] = -1;
+#else
+ pthread_join(gthread_id_cloud_refresh_check, NULL);
+#endif
+ gthread_id_cloud_refresh_check = 0;
+ }
+
+ if (gthread_id_network_status_check) {
+ pthread_join(gthread_id_network_status_check, NULL);
+ gthread_id_network_status_check = 0;
+ }
+
+ if (es_terminate_enrollee() == ES_ERROR) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "Init EasySetup Failed");
+ return ESM_ERROR;
+ }
+
+ if (g_dev_conf_prov_data) {
+ things_free(g_dev_conf_prov_data);
+ g_dev_conf_prov_data = NULL;
+ }
+
+ if (g_wifi_prov_data) {
+ things_free(g_wifi_prov_data);
+ g_wifi_prov_data = NULL;
+ }
+
+ if (g_cloud_prov_data) {
+ things_free(g_cloud_prov_data);
+ g_cloud_prov_data = NULL;
+ }
+ }
+
+ g_dev_conf_prov_data = (es_dev_conf_prov_data_s *) things_malloc(sizeof(es_dev_conf_prov_data_s));
+ g_wifi_prov_data = (es_wifi_prov_data_s *) things_malloc(sizeof(es_wifi_prov_data_s));
+ g_cloud_prov_data = (es_cloud_prov_data_s *) things_malloc(sizeof(es_cloud_prov_data_s));
+
+ if (g_dev_conf_prov_data == NULL || g_wifi_prov_data == NULL || g_cloud_prov_data == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Easy Setup Memory allocation is failed.");
+ return ESM_ERROR;
+ }
+// es_device_property device_property = {
+// {{WiFi_11G, WiFi_11N, WiFi_11AC, WiFi_EOF}, WiFi_5G}, {"Test Device"}
+// };
+
+ if (server_builder != NULL) {
+ g_server_builder = server_builder;
+ }
+
+ if (g_server_builder == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "[Error] g_server_builder is NULL.");
+ return ESM_ERROR;
+ }
+#ifdef __SECURED__
+ bool g_is_secured = true;
+#else
+ bool g_is_secured = false;
+#endif
+
+ es_resource_mask_e resourcem_mask = ES_WIFI_RESOURCE | ES_CLOUD_RESOURCE | ES_DEVCONF_RESOURCE;
+ // Easy Setup Module Initiation
+
+ if (es_init_enrollee(g_is_secured, resourcem_mask, g_callbacks) != ES_OK) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "StartEasySetup and onboarding Fail!!");
+ return ESM_ERROR;
+ }
+
+ es_set_state(ES_STATE_INIT);
+ es_set_error_code(ES_ERRCODE_NO_ERROR);
+
+ if (es_set_device_property(&device_property) == ES_ERROR) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "es_set_device_property funtion Failed");
+ }
+#ifdef __SECURED__
+
+ if (OC_STACK_OK != SetRandomPinPolicy(8, NUM_PIN)) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Set to Non-Numerical PIN Generation~!!!!!");
+ } else {
+ THINGS_LOG(THINGS_INFO, TAG, "Set to Numerical PIN Generation~!!!!!");
+ }
+
+ SetGeneratePinCB(&generate_pin_cb);
+ SetClosePinDisplayCB(&pin_close_cb);
+ SetUserConfirmCB(NULL, get_user_confirmation);
+ SetVerifyOption(USER_CONFIRM);
+
+#endif //#ifdef __SECURED__
+ if (gthread_id_cloud_refresh_check == 0) {
+ int ret = pipe(ci_token_expire_fds);
+ if (-1 == ret) {
+ close(ci_token_expire_fds[0]);
+ close(ci_token_expire_fds[1]);
+ ci_token_expire_fds[0] = -1;
+ ci_token_expire_fds[1] = -1;
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "pipe failed: %s", strerror(errno));
+ return ESM_ERROR;
+ }
+ esm_continue = 1;
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Create cloud_refresh_check_loop thread");
+#ifdef __ST_THINGS_RTOS__
+ pthread_create_rtos(>hread_id_cloud_refresh_check, NULL, cloud_refresh_check_loop, (void *)&esm_continue, THINGS_STACK_CLOUD_REFRESH_THREAD);
+#else
+ things_thread_create(>hread_id_cloud_refresh_check, NULL, cloud_refresh_check_loop, (void *)&esm_continue);
+#endif
+ }
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_EXIT);
+ return ESM_OK;
+}
+
+esm_result_e esm_terminate_easysetup()
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Terminate EasySetup");
+ esm_continue = 0;
+ if (gthread_id_cloud_refresh_check) {
+#ifdef __ST_THINGS_RTOS__
+ if (ci_token_expire_fds[1] != -1) {
+ ssize_t len = 0;
+ do {
+ len = write(ci_token_expire_fds[1], "w", 1);
+ } while ((len == -1) && (errno == EINTR));
+ if ((len == -1) && (errno != EINTR) && (errno != EPIPE)) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "write failed: %s", strerror(errno));
+ return ESM_ERROR;
+ }
+ }
+ pthread_join(gthread_id_cloud_refresh_check, NULL);
+ close(ci_token_expire_fds[0]);
+ close(ci_token_expire_fds[1]);
+ ci_token_expire_fds[0] = -1;
+ ci_token_expire_fds[1] = -1;
+#else
+ pthread_join(gthread_id_cloud_refresh_check, NULL);
+#endif
+ gthread_id_cloud_refresh_check = 0;
+ }
+ if (gthread_id_network_status_check) {
+ pthread_join(gthread_id_network_status_check, NULL);
+ gthread_id_network_status_check = 0;
+ }
+
+ if (es_terminate_enrollee() != ES_OK) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Terminate EasySetup Error");
+ return ESM_ERROR;
+ }
+
+ if (g_dev_conf_prov_data) {
+ things_free(g_dev_conf_prov_data);
+ g_dev_conf_prov_data = NULL;
+ }
+
+ if (g_wifi_prov_data) {
+ things_free(g_wifi_prov_data);
+ g_wifi_prov_data = NULL;
+ }
+
+ if (g_cloud_prov_data) {
+ things_free(g_cloud_prov_data);
+ g_cloud_prov_data = NULL;
+ }
+
+ g_server_builder = NULL;
+ esm_continue = 0;
+
+ return ESM_MODULE_TERMINATED;
+}
+
+static int checkRefresh(int *hour_cnt_24)
+{
+ OCStackResult ret = OC_STACK_ERROR;
+ int sleep_sec = 0;
+
+ if (*hour_cnt_24 >= CI_COMMON_REFRESH_TIME) {
+ if ((ret = refresh_token_into_cloud()) != OC_STACK_OK) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "refresh_token_into_cloud is failed in cloud_refresh_check_loop");
+ } else {
+ *hour_cnt_24 = 0;
+ }
+ } else {
+ // Find Resource & if accesstoken is expireded then refresh process is called.
+ if ((ret = find_cloud_resource()) != OC_STACK_OK) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "find_cloud_resource is failed in cloud_refresh_check_loop");
+ }
+ }
+
+ if (ret != OC_STACK_OK) {
+ sleep_sec = i_fail_sleep_sec;
+ } else {
+ sleep_sec = i_common_sleep_sec;
+ (*hour_cnt_24)++;
+ }
+
+ return sleep_sec;
+}
+
+static void *cloud_refresh_check_loop(void *param)
+{
+#ifdef __ST_THINGS_RTOS__
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "cloud_refresh_check_loop Close Loop Enter.");
+ int i_failed_cnt = 0;
+ int *i_continue = (int *)param;
+ int hour_cnt_24 = 0;
+ int ret = -1;
+ fd_set readFds;
+ struct timeval timeout;
+
+ timeout.tv_sec = i_common_sleep_sec;
+ timeout.tv_usec = 0;
+ int maxFd = ci_token_expire_fds[0];
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "device ID = %s", OCGetServerInstanceIDString());
+
+ // Close Loop Thread.
+ while (*i_continue) {
+ if (es_get_state() != ES_STATE_PUBLISHED_RESOURCES_TO_CLOUD) {
+ hour_cnt_24++;
+ timeout.tv_sec = i_common_sleep_sec;
+ FD_ZERO(&readFds);
+ FD_SET(ci_token_expire_fds[0], &readFds);
+ ret = select(maxFd + 1, &readFds, NULL, NULL, &timeout);
+ if (ret == 0) {
+ continue;
+ }
+ if (FD_ISSET(ci_token_expire_fds[0], &readFds)) {
+ char buf[2] = { 0 };
+ ssize_t len = read(ci_token_expire_fds[0], buf, sizeof(buf));
+ if (len > 0 && buf[0] == 'w') {
+ break;
+ }
+ continue;
+ }
+ continue;
+ }
+ if ((timeout.tv_sec = checkRefresh(&hour_cnt_24)) == i_fail_sleep_sec) {
+ i_failed_cnt++;
+ } else {
+ i_failed_cnt = 0;
+ }
+
+ if (i_failed_cnt >= MAX_REFRESHCHECK_CNT) {
+ THINGS_LOG_D(THINGS_INFO, TAG, "Refresh checking routin is Failed. Return cloud state to INIT.");
+ i_failed_cnt = 0;
+ esm_get_network_status(); // State return
+ }
+ FD_ZERO(&readFds);
+ FD_SET(ci_token_expire_fds[0], &readFds);
+ ret = select(maxFd + 1, &readFds, NULL, NULL, &timeout);
+ if (ret == 0) {
+ continue;
+ }
+ if (FD_ISSET(ci_token_expire_fds[0], &readFds)) {
+ char buf[2] = { 0 };
+ ssize_t len = read(ci_token_expire_fds[0], buf, sizeof(buf));
+ if (len > 0 && buf[0] == 'w') {
+ break;
+ }
+ }
+ }
+ FD_CLR(ci_token_expire_fds[0], &readFds);
+ FD_CLR(ci_token_expire_fds[1], &readFds);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "cloud_refresh_check_loop Close Loop Exit.");
+ return NULL;
+#else
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "cloud_refresh_check_loop Close Loop Enter.");
+
+ int i_failed_cnt = 0;
+ int sleep_sec = i_common_sleep_sec;
+ int *i_continue = (int *)param;
+ int hour_cnt_24 = 0;
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "device ID = %s", OCGetServerInstanceIDString());
+
+ // Close Loop Thread.
+ while (*i_continue) {
+ if (es_get_state() != ES_STATE_PUBLISHED_RESOURCES_TO_CLOUD) {
+ hour_cnt_24++;
+ sleep_sec = i_common_sleep_sec;
+ sleep(sleep_sec);
+ continue;
+ }
+
+ if ((sleep_sec = checkRefresh(&hour_cnt_24)) == i_fail_sleep_sec) {
+ i_failed_cnt++;
+ } else {
+ i_failed_cnt = 0;
+ }
+
+ if (i_failed_cnt >= MAX_REFRESHCHECK_CNT) {
+ THINGS_LOG_D(THINGS_INFO, TAG, "Refresh checking routin is Failed. Return cloud state to INIT.");
+ i_failed_cnt = 0;
+ esm_get_network_status(); // State return
+ }
+
+ sleep(sleep_sec);
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "cloud_refresh_check_loop Close Loop Exit.");
+
+ return NULL;
+#endif
+}
+
+static int OICUpdateDevProvData(es_dev_conf_prov_data_s *dev_prov_data)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Enter.");
+
+ if (dev_prov_data == NULL) {
+ return -1;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Country=%s, DateTime=%s, Language=%s", dev_prov_data->country, dev_prov_data->datetime, dev_prov_data->language);
+
+ if (g_update_dev_prov_data == NULL) {
+ THINGS_LOG_D(THINGS_INFO, TAG, "st_things API is not registered.(gUpdateDateTime)");
+ return -1;
+ }
+
+ return g_update_dev_prov_data(dev_prov_data);
+}
+
+static void *wifi_prov_set_loop(void *param)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Open Loop Enter.");
+
+ static int timeout_handle_num = 100;
+ timeout_s timeout;
+
+ es_set_state(ES_STATE_CONNECTING_TO_ENROLLER);
+ set_wifi_prov_state(WIFI_READY);
+
+ while (get_wifi_prov_state() == WIFI_READY) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "waiting... WIFI_RESPONSE-Done for wifi provisioning.");
+ usleep(50000);
+ }
+
+ if (get_wifi_prov_state() != WIFI_RESPONSE) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "WiFi Response is failed.");
+ set_wifi_prov_state(WIFI_INIT);
+ things_free((access_point_info_s *) param);
+ return 0;
+ }
+ // Notify DevConfProvData to THINGS_App.
+ OICUpdateDevProvData(g_dev_conf_prov_data);
+
+ usleep(50000);
+
+ int res = things_set_ap_connection((access_point_info_s *) param);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Set AP Connection Result : %d", res);
+
+ if (res != 1) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Wifi Provisioning is Failed");
+ es_set_state(ES_STATE_FAILED_TO_CONNECT_TO_ENROLLER);
+ things_free((access_point_info_s *) param);
+ set_wifi_prov_state(WIFI_INIT);
+ return 0;
+ }
+
+ things_wifi_state_changed_cb_init();
+ set_wifi_prov_state(WIFI_SET);
+ things_free((access_point_info_s *) param);
+
+ if (add_request_handle((OCDoHandle) timeout_handle_num) != NULL) {
+ timeout.cur_num = 300; // 5 min because, st_things-App wait AP-Connecting for 5 min.
+ timeout.cur_counter = timeout.cur_num;
+ create_time_out_process((OCDoHandle) timeout_handle_num++, wifi_prov_timeout_handler, &timeout);
+ }
+
+ gthread_id_network_status_check = 0;
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Open Loop Exit.");
+
+ return NULL;
+}
+
+static void *wifi_prov_timeout_handler(timeout_s *param)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "WiFi Setting of Provisioning data was Time-Out.");
+
+ es_set_state(ES_STATE_FAILED_TO_CONNECT_TO_ENROLLER);
+ es_set_error_code(ES_ERRCODE_NO_INTERNETCONNECTION);
+
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "es_set_state ES_STATE_CONNECTED_FAIL_TO_ENROLLER");
+
+ if (ESM_OK != esm_init_easysetup(1, NULL)) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Easy-Setup Module Initialization failed");
+ things_stop();
+ return NULL;
+ }
+
+ PROFILING_TIME("WiFi Provisioning End.");
+
+ set_wifi_prov_state(WIFI_INIT);
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Exit.");
+
+ return NULL;
+}
+
+int esm_wifi_prov_check_cb(int enabled, char *ssid, char *addr)
+{
+ int ret = -1;
+
+ if (get_wifi_prov_state() != WIFI_SET) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "WiFi Provisioning State is Not WIFI_SET step.(%d)", get_wifi_prov_state());
+ return 0;
+ }
+
+ if (enabled != 1 || ssid == NULL || addr == NULL) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "enabled=%d, ssid=%s, addr=%s", enabled, ssid, addr);
+ return 0;
+ }
+
+ pthread_mutex_lock(&g_es_mutex);
+ if (strncmp(ssid, g_wifi_prov_data->ssid, strlen(g_wifi_prov_data->ssid)) == 0) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "CONNECTED TO TARGET AP %s ", ssid);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "GET IP ADDR : %s ", addr);
+ ret = 1;
+ } else {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "SSID is not Targeted One : (%s), (%s)", ssid, g_wifi_prov_data->ssid);
+ ret = 0;
+ }
+ pthread_mutex_unlock(&g_es_mutex);
+
+ if (ret == 1) {
+ es_set_state(ES_STATE_CONNECTED_TO_ENROLLER);
+ set_wifi_prov_state(WIFI_DONE);
+ THINGS_LOG(THINGS_DEBUG, TAG, "es_set_state ES_STATE_CONNECTED_TO_ENROLLER");
+
+ if (g_server_builder->broadcast_presence(g_server_builder, 20) == 1) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "Broadcast Presence Failed.");
+ ret = 0;
+ }
+
+ del_all_request_handle(); // clear time-out thread.
+ PROFILING_TIME("WiFi Provisioning End.");
+
+ set_wifi_prov_state(WIFI_INIT);
+ }
+
+ return ret;
+}
+
+void wifi_prov_cb_in_app(es_wifi_prov_data_s *event_data)
+{
+ THINGS_LOG_V(THINGS_DEBUG, TAG, "Enter");
+ access_point_info_s *p_info = NULL;
+
+ if (event_data == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "es_wifi_prov_data_s Data Is NULL");
+ return;
+ }
+
+ if (things_is_net_initialize() != 1) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "Network API Is not ready.");
+ return;
+ }
+
+ p_info = (access_point_info_s *) things_malloc(sizeof(access_point_info_s));
+ if (p_info == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "access_point_info_s memory allocation is failed.");
+ return;
+ }
+
+ pthread_mutex_lock(&g_es_mutex);
+ memcpy(g_wifi_prov_data, event_data, sizeof(es_wifi_prov_data_s));
+ pthread_mutex_unlock(&g_es_mutex);
+
+ // Attention : when 64bit linux Build, runtime-error occur. (memset () at ../sysdeps/x86_64/memset.S: Not Found File or Directory)
+ // It's because of p_info.(64 bit malloc internal code flow is not support that character array data-type of access_point_info_s)
+ // TODO : Fix Bug for 64bit support.
+ memset(p_info->e_ssid, 0, MAX_ESSID);
+ memset(p_info->security_key, 0, MAX_SECUIRTYKEY);
+ memset(p_info->enc_type, 0, MAX_TYPE_ENC);
+ memset(p_info->auth_type, 0, MAX_TYPE_AUTH);
+ memset(p_info->channel, 0, MAX_CHANNEL);
+ memset(p_info->bss_id, 0, MAX_BSSID);
+ memset(p_info->signal_level, 0, MAX_LEVEL_SIGNAL);
+
+ if (strlen(event_data->ssid) > 0) {
+ things_strncpy(p_info->e_ssid, event_data->ssid, strlen(event_data->ssid));
+ }
+
+ if (strlen(event_data->pwd) > 0) {
+ things_strncpy(p_info->security_key, event_data->pwd, strlen(event_data->pwd));
+ }
+
+ if (event_data->authtype >= NONE_AUTH && event_data->authtype <= WPA2_PSK) {
+ switch (event_data->authtype) {
+ case WEP:
+ things_strncpy(p_info->auth_type, "WEP", strlen("WEP"));
+ break;
+ case WPA_PSK:
+ things_strncpy(p_info->auth_type, "WPA-PSK", strlen("WPA-PSK"));
+ break;
+ case WPA2_PSK:
+ things_strncpy(p_info->auth_type, "WPA2-PSK", strlen("WPA2-PSK"));
+ break;
+ case NONE_AUTH:
+ default:
+ things_strncpy(p_info->auth_type, "NONE", strlen("NONE"));
+ break;
+ }
+ } else {
+ things_strncpy(p_info->auth_type, "NONE", strlen("NONE"));
+ }
+
+ if (event_data->enctype >= NONE_ENC && event_data->enctype <= TKIP_AES) {
+ switch (event_data->enctype) {
+ case WEP_64:
+ things_strncpy(p_info->enc_type, "WEP_64", strlen("WEP_64"));
+ break;
+ case WEP_128:
+ things_strncpy(p_info->enc_type, "WEP_128", strlen("WEP_128"));
+ break;
+ case TKIP:
+ things_strncpy(p_info->enc_type, "TKIP", strlen("TKIP"));
+ break;
+ case AES:
+ things_strncpy(p_info->enc_type, "AES", strlen("AES"));
+ break;
+ case TKIP_AES:
+ things_strncpy(p_info->enc_type, "TKIP_AES", strlen("TKIP_AES"));
+ break;
+ default:
+ things_strncpy(p_info->enc_type, "NONE", strlen("NONE"));
+ break;
+ }
+ } else {
+ things_strncpy(p_info->enc_type, "NONE", strlen("NONE"));
+ }
+
+ if (event_data->discovery_channel != -1) {
+ snprintf(p_info->channel, MAX_CHANNEL, "%d", event_data->discovery_channel);
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "e_ssid : %s", p_info->e_ssid);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "security_key : %s", p_info->security_key);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "auth_type : %s", p_info->auth_type);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "enc_type : %s", p_info->enc_type);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "channel : %s", p_info->channel);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Copied ssid = %s", g_wifi_prov_data->ssid);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Copied pwd = %s", g_wifi_prov_data->pwd);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Copied enctype = %d", g_wifi_prov_data->enctype);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Copied discovery_channel = %d", g_wifi_prov_data->discovery_channel);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Copied authtype = %d", g_wifi_prov_data->authtype);
+
+ // Connect to AP
+ if (gthread_id_network_status_check == 0) {
+ THINGS_LOG(THINGS_DEBUG, TAG, "Create NetworkStatusCheck thread");
+ del_all_request_handle(); // clear time-out thread.
+ set_wifi_prov_state(WIFI_INIT);
+
+#ifdef __ST_THINGS_RTOS__
+ pthread_create_rtos(>hread_id_network_status_check, NULL, wifi_prov_set_loop, (void *)p_info, THINGS_STACK_CLOUD_REFRESH_THREAD);
+#else
+ things_thread_create(>hread_id_network_status_check, NULL, wifi_prov_set_loop, (void *)p_info);
+#endif
+ set_wifi_prov_state(WIFI_READY);
+ } else {
+ things_free(p_info);
+ }
+
+ THINGS_LOG_V(THINGS_DEBUG, TAG, "Exit");
+}
+
+void dev_conf_prov_cb_in_app(es_dev_conf_prov_data_s *event_data)
+{
+ if (event_data == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "es_dev_conf_prov_data_s Is NULL");
+ return;
+ }
+
+ pthread_mutex_lock(&g_es_mutex);
+ memcpy(g_dev_conf_prov_data, event_data, sizeof(es_dev_conf_prov_data_s));
+ pthread_mutex_unlock(&g_es_mutex);
+
+ if (strlen(event_data->language) > 0) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Language : %s", event_data->language);
+ }
+
+ if (strlen(event_data->country) > 0) {
+ // check payload
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Country : %s", event_data->country);
+ }
+
+ if (strlen(event_data->datetime) > 0) {
+ // check payload
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Datetime : %s", event_data->datetime);
+ }
+}
+
+void cloud_data_prov_cb_in_app(es_cloud_prov_data_s *event_data)
+{
+ if (event_data == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "es_cloud_prov_data_s Data Is NULL");
+ return;
+ }
+
+ pthread_mutex_lock(&g_es_mutex);
+ memcpy(g_cloud_prov_data, event_data, sizeof(es_cloud_prov_data_s));
+ pthread_mutex_unlock(&g_es_mutex);
+
+ if (strlen(event_data->auth_code) > 0) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "AuthCode : %s", g_cloud_prov_data->auth_code);
+ }
+
+ if (strlen(event_data->accesstoken) > 0) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Accesstoken : %s", g_cloud_prov_data->accesstoken);
+ }
+
+ if (strlen(event_data->refreshtoken) > 0) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Refreshtoken : %s", g_cloud_prov_data->refreshtoken);
+ }
+
+ if (strlen(event_data->uid) > 0) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Uid : %s", g_cloud_prov_data->uid);
+ }
+
+ if (strlen(event_data->auth_provider) > 0) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "AuthProvider : %s", g_cloud_prov_data->auth_provider);
+ }
+
+ if (strlen(event_data->host_name) > 0) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "CIHostName : %s", g_cloud_prov_data->host_name);
+ }
+
+ if (strlen(event_data->ip) > 0) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "CIip : %s", g_cloud_prov_data->ip);
+ }
+
+ if (strlen(event_data->port) > 0) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "CIPort : %s", g_cloud_prov_data->port);
+ }
+
+ if (strlen(event_data->ci_server) > 0) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "CIServer : %s", g_cloud_prov_data->ci_server);
+ }
+
+ if (strlen(event_data->server_id) > 0) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Server ID : %s", g_cloud_prov_data->server_id);
+ }
+
+ g_cloud_data_cb_to_app(g_cloud_prov_data);
+ // CB to things_stack.c
+ // Need to check the running state of the thread...
+}
+
+bool esm_get_network_status(void)
+{
+ //THINGS_LOG_D(THINGS_DEBUG, TAG, "Enter.");
+
+ bool is_ok = false;
+
+ if (things_is_net_initialize() != 1) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "Network API is not initialized.");
+ return false;
+ }
+
+ if (things_is_connected_ap() == true) {
+ THINGS_LOG_V(THINGS_INFO, TAG, "Connected to AP");
+ es_set_state(ES_STATE_CONNECTED_TO_ENROLLER);
+
+ if (g_server_builder != NULL && g_server_builder->broadcast_presence != NULL) {
+ if (g_server_builder->broadcast_presence(g_server_builder, 20) == 1) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Broadcast Presence Failed.");
+ return is_ok;
+ }
+ } else {
+ THINGS_LOG_V(THINGS_INFO, TAG, "ServerBuilder is not initialized.");
+ }
+
+ is_ok = true;
+ } else {
+ THINGS_LOG_V(THINGS_INFO, TAG, "Disconnected to AP");
+ es_set_state(ES_STATE_INIT);
+ }
+
+ //THINGS_LOG_D(THINGS_DEBUG, TAG, "Exit.");
+ return is_ok;
+}
+
+void *esm_register_cloud_cb(void *func)
+{
+ g_cloud_data_cb_to_app = func;
+ return NULL;
+}
+
+esm_result_e esm_set_wifi_conn_rrr(void)
+{
+ es_set_state(ES_STATE_FAILED_TO_CONNECT_TO_ENROLLER);
+ es_set_error_code(ES_ERRCODE_UNKNOWN);
+ return ESM_OK;
+}
+
+int esm_register_pin_generated_cb(pin_generated_func_type func)
+{
+ if (func) {
+ g_pin_generated_cb = func;
+ // SetGeneratePinCB(generate_pin_cb);
+ return 1;
+ } else {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Invalid PINGeneratedCB function");
+ return 0;
+ }
+}
+
+int esm_register_pin_close_cb(pin_close_func_type func)
+{
+ if (func) {
+ g_pin_close_cb = func;
+ // SetGeneratePinCB(generate_pin_cb);
+ return 1;
+ } else {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Invalid PINGeneratedCB function");
+ return 0;
+ }
+}
+
+int esm_register_user_confirm_cb(user_confirm_result_func_type func)
+{
+ if (func) {
+ g_user_confirm_cb = func;
+
+ // SetUserConfirmCB(NULL, get_user_confirmation);
+ return 1;
+ } else {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Invalid UserConformCB function");
+ return 0;
+ }
+}
--- /dev/null
+/* ****************************************************************
+ *
+ * Copyright 2017 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.
+ *
+ ******************************************************************/
+
+#ifndef EASYSETUP_ENROLLEE_H__
+#define EASYSETUP_ENROLLEE_H__
+
+#include "es_common.h"
+
+typedef void (*es_enrollee_event_callback)(es_result_e es_result, things_es_enrollee_state_e enrolleeState);
+
+typedef struct {
+ void (*wifi_prov_cb)(es_wifi_prov_data_s *);
+ void (*dev_conf_prov_cb)(es_dev_conf_prov_data_s *);
+ void (*cloud_data_prov_cb)(es_cloud_prov_data_s *);
+} es_provisioning_callbacks_s;
+
+es_result_e es_init_enrollee(bool is_secured, es_resource_mask_e resource_mask, es_provisioning_callbacks_s callbacks);
+
+void es_register_notify_easysetup_state(void *func);
+
+things_es_enrollee_state_e es_get_state(void);
+
+bool es_get_cloud_login_state(void);
+
+es_result_e es_set_device_property(es_device_property *device_property);
+
+es_result_e es_set_state(things_es_enrollee_state_e es_state);
+
+es_result_e es_set_error_code(es_error_code_e es_err_code);
+
+es_result_e es_set_cloud_error_code(ci_error_code_e es_err_code);
+
+es_result_e es_terminate_enrollee();
+
+#endif /* EASYSETUP_ENROLLEE_H__ */
--- /dev/null
+/* ****************************************************************
+ *
+ * Copyright 2017 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.
+ *
+ ******************************************************************/
+
+#define _POSIX_C_SOURCE 200809L
+
+#ifndef _EASYSETUP_MANAGER_H_
+#define _EASYSETUP_MANAGER_H_
+
+#include "things_api.h"
+#include "es_common.h"
+#include "things_server_builder.h"
+
+typedef enum {
+ ESM_OK = 0,
+ ESM_ERROR,
+ ESM_PARAM_INVAIND,
+ ESM_MODULE_STARTED,
+ ESM_MODULE_TERMINATED,
+ ESM_REQ_DENIED
+} esm_result_e;
+
+typedef void (*pin_generated_func_type)(char *pin_data, size_t pin_size);
+
+typedef int (*pin_close_func_type)(void);
+
+typedef int (*user_confirm_result_func_type)(void);
+
+int esm_set_device_property_by_app(char *name, const wifi_mode_e *mode, int ea_mode, const wifi_freq_e freq);
+
+esm_result_e esm_init_easysetup(int restart_flag, things_server_builder_s *server_builder);
+
+esm_result_e esm_terminate_easysetup(void);
+
+esm_result_e esm_set_wifi_conn_rrr(void);
+
+bool esm_get_network_status(void);
+
+void *esm_register_cloud_cb(void *);
+
+void esm_register_update_dev_prov_data_func(things_update_dev_prov_data_func_type func);
+
+int esm_register_pin_generated_cb(pin_generated_func_type func);
+
+int esm_register_pin_close_cb(pin_close_func_type func);
+
+int esm_register_user_confirm_cb(user_confirm_result_func_type func);
+
+int esm_wifi_prov_check_cb(int enabled, char *ssid, char *addr);
+
+#endif // _EASYSETUP_MANAGER_H_
--- /dev/null
+/* ****************************************************************
+ *
+ * Copyright 2017 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.
+ *
+ ******************************************************************/
+
+#ifndef ES_COMMON_H_
+#define ES_COMMON_H_
+
+#include "ocstack.h"
+#include "octypes.h"
+#include "things_types.h"
+
+#define THINGS_STRING_MAX_HOSTNAME 256
+#define THINGS_STRING_MAX_VALUE 100
+#define IP_PORT 22
+
+/**
+ * Attributes used to form a proper easysetup conforming JSON message.
+ */
+#define OC_RSRVD_ES_PROVSTATUS "ps"
+#define OC_RSRVD_ES_LAST_ERRORCODE "lec"
+#define OC_RSRVD_ES_LINKS "links"
+#define OC_RSRVD_ES_SUPPORTEDWIFIMODE "swmt"
+#define OC_RSRVD_ES_SUPPORTEDWIFIFREQ "swf"
+#define OC_RSRVD_ES_SSID "tnn"
+#define OC_RSRVD_ES_CRED "cd"
+#define OC_RSRVD_ES_AUTHTYPE "wat"
+#define OC_RSRVD_ES_ENCTYPE "wet"
+#define OC_RSRVD_ES_AUTHCODE "ac"
+#define OC_RSRVD_ES_AUTHPROVIDER "apn"
+#define OC_RSRVD_ES_CISERVER "cis"
+#define OC_RSRVD_ES_SERVERID "sid"
+#define OC_RSRVD_ES_CLIENTID "clientid"
+#define OC_RSRVD_ES_DEVNAME "dn"
+#define OC_RSRVD_ES_LANGUAGE "lang"
+#define OC_RSRVD_ES_COUNTRY "ctry"
+#define OC_RSRVD_ES_VENDOR_DEVTYPE "x.com.samsung.dt"
+#define OC_RSRVD_ES_VENDOR_DEVSUBTYPE "x.com.samsung.sdt"
+#define OC_RSRVD_ES_VENDOR_DISCOVERYCHANNEL "x.com.samsung.chn"
+#define OC_RSRVD_ES_VENDOR_CLIENTID "x.com.samsung.clientid"
+#define OC_RSRVD_ES_VENDOR_ERRORCODE "x.com.samsung.vd.errcode"
+#define OC_RSRVD_ES_VENDOR_ACCESS_TOKEN "at"
+#define OC_RSRVD_ES_VENDOR_ACCESS_TOKEN_TYPE "att"
+#define SC_RSRVD_ES_VENDOR_REFRESH_TOKEN "x.com.samsung.refreshtoken"
+#define OC_RSRVD_ES_VENDOR_USER_ID "x.com.samsung.uid"
+#define OC_RSRVD_ES_VENDOR_UTC_DATE_TIME "x.com.samsung.datetime"
+
+/**
+ * Easysetup defined resoruce types and uris.
+ */
+#define OC_RSRVD_ES_RES_TYPE_PROV "oic.r.easysetup" //"oic.wk.prov"
+#define OC_RSRVD_ES_URI_PROV "/EasySetupResURI" //"/ProvisioningResURI"
+#define OC_RSRVD_ES_RES_TYPE_WIFI "oic.r.wificonf" //"oic.wk.wifi"
+#define OC_RSRVD_ES_URI_WIFI "/WiFiConfResURI" //"/WiFiProvisioningResURI"
+#define OC_RSRVD_ES_RES_TYPE_CLOUDSERVER "oic.r.coapcloudconf" //"oic.wk.cloudserver"
+#define OC_RSRVD_ES_URI_CLOUDSERVER "/CoapCloudConfResURI" //"/CloudServerProvisioningResURI"
+#define OC_RSRVD_ES_RES_TYPE_DEVCONF "oic.r.devconf" //"oic.wk.devconf"
+#define OC_RSRVD_ES_URI_DEVCONF "/DevConfResURI" //"/DevConfProvisioningResURI"
+
+#define NUM_WIFIMODE 10
+
+#define MAX_DEVICELEN 100
+
+typedef enum {
+ ES_ERROR = -1,
+ ES_OK = 0,
+ ES_NETWORKFOUND = 1,
+ ES_NETWORKCONNECTED,
+ ES_NETWORKNOTCONNECTED,
+ ES_RESOURCECREATED = 11,
+ ES_RECVREQOFPROVRES = 21,
+ ES_RECVREQOFNETRES,
+ ES_RECVUPDATEOFPROVRES,
+ ES_RECVTRIGGEROFPROVRES,
+ ES_UNAUTHORIZED = 31
+} es_result_e;
+
+typedef enum {
+ ES_WIFI_RESOURCE = 0x01,
+ ES_CLOUD_RESOURCE = 0x02,
+ ES_DEVCONF_RESOURCE = 0x04
+} es_resource_mask_e;
+
+typedef struct {
+ struct {
+ wifi_mode_e mode[NUM_WIFIMODE];
+ wifi_freq_e freq;
+ } WiFi;
+ struct {
+ char device_name[MAX_DEVICELEN];
+ char device_type[THINGS_STRING_MAX_VALUE];
+ char device_sub_type[THINGS_STRING_MAX_VALUE];
+ } dev_conf_s;
+} es_device_property;
+
+/**
+ * @brief Indicate last error code to describe a reason of error during easy setup.
+ */
+typedef enum {
+ /**
+ * Initialize Error Code
+ */
+ ES_ERRCODE_NO_ERROR = 0,
+
+ /**
+ * Error Code that given WiFi's SSID is not found
+ */
+ ES_ERRCODE_SSID_NOT_FOUND,
+
+ /**
+ * Error Code that given WiFi's Password is wrong
+ */
+ ES_ERRCODE_PW_WRONG,
+
+ /**
+ * Error Code that IP address is not allocated
+ */
+ ES_ERRCODE_IP_NOT_ALLOCATED,
+
+ /**
+ * Error Code that there is no Internet connection
+ */
+ ES_ERRCODE_NO_INTERNETCONNECTION,
+
+ /**
+ * Error Code that Timeout occurred about wifi provisioning.
+ */
+ ES_ERRCODE_TIMEOUT,
+
+ /**
+ * Error Code that cloud server is not reachable due to wrong URL of cloud server, for example.
+ */
+ ES_ERRCODE_FAILED_TO_ACCESS_CLOUD_SERVER,
+
+ /**
+ * Error Code that no response is arrived from cloud server
+ */
+ ES_ERRCODE_NO_RESPONSE_FROM_CLOUD_SERVER,
+
+ /**
+ * Error Code that a delivered authcode is not valid.
+ */
+ ES_ERRCODE_INVALID_AUTHCODE,
+
+ /**
+ * Error Code that a given access token is not valid due to its expiration, for example.
+ */
+ ES_ERRCODE_INVALID_ACCESSTOKEN,
+
+ /**
+ * Error Code that a refresh of expired access token is failed due to some reasons.
+ */
+ ES_ERRCODE_FAILED_TO_REFRESH_ACCESSTOKEN,
+
+ /**
+ * Error Code that a target device is not discovered in cloud server
+ */
+ ES_ERRCODE_FAILED_TO_FIND_REGISTERED_DEVICE_IN_CLOUD,
+
+ /**
+ * Error Code that a target user does not exist in cloud server.
+ */
+ ES_ERRCODE_FAILED_TO_FIND_REGISTERED_USER_IN_CLOUD,
+
+ /**
+ * Cloud Provisioning Error
+ */
+ ER_ERRCODE_INVALID_PROV_PAYLOAD = 100,
+
+ /**
+ * Cloud Data invalid in provisioning.json file.
+ */
+ ER_ERRCODE_INVALID_SAVED_CLOUD_DATA = 101,
+
+ /**
+ * Device System Error.
+ */
+ ER_ERRCODE_SYSTEM_ERROR = 102, // System Error of device.
+
+ /**
+ * Error Code that Unknown error occurred
+ */
+ ES_ERRCODE_UNKNOWN = 255
+} es_error_code_e;
+
+/*
+ * * Used HTTP Status Code
+ * 200 : OK
+ * 201 : Created
+ * 400 : Bad Request
+ * 401 : Unauthorized
+ * 403 : Forbidden
+ * 404 : Not Found
+ * 500 : Internal Server Error
+ *
+ *
+ * * Serial Number
+ * 00xx : Common
+ * 01xx : User
+ * 02xx : Device
+ * 03xx : RD (ResourceDirectory)
+ * 04xx : RD Link
+ * 05xx : Group
+ * 06xx : ACL
+ * 07xx : CI (Cloud Interface)
+ * 08xx : Push
+ *
+ * * Sub-Serial Number
+ * xx00 : Not Found.
+ * xx01 : Duplicated.
+ * xx02 : Invalid Param.
+ *
+ * * Result Code is made by
+ * HTTP Status Code(xxx) + Serial Number(xxxx)
+ */
+
+typedef enum {
+ // No error
+ ERRCI_NO_ERROR = 0,
+
+ /**
+ * Cloud Error Code
+ */
+ // No error
+ ERRCI_SUCCESS = 2000000,
+
+ //COMMON
+ ERRCI_SAMSUNG_ACCOUNT_AUTHORIZATION_FAILED = 4010001, // Invalid authcode value.
+ ERRCI_TOKEN_VALIDATION_FAILED = 4000002,
+ ERRCI_FORBIDDEN = 4030003,
+ ERRCI_TOKEN_EXPIRED = 4000004,
+ ERRCI_AUTHORIZATION_FAILED = 4000005,
+ ERRCI_UNSUPPORTED_REQ = 4000901,
+ ERRCI_NOT_ACCEPTABLE = 4060001,
+
+ //USER
+ ERRCI_USER_DUPLICATE_PARAM = 4000101,
+ ERRCI_USER_INVALID_PARAM = 4000102,
+ ERRCI_USER_NOT_FOUND = 4040100,
+ ERRCI_UNAUTHORIZED_TOKEN = 4010200,
+ ERRCI_SAMSUNG_ACCOUNT_UNAUTHORIZED_TOKEN = 4010201, // Already registered device for other user.
+
+ //DEVICE
+ ERRCI_DEVICE_DUPLICATE_PARAM = 4000201,
+ ERRCI_DEVICE_INVALID_PARAM = 4000202,
+ ERRCI_DEVICE_NOT_CONNECTED = 4010900,
+ ERRCI_DEVICE_NOT_FOUND = 4040200,
+
+ //RD
+ ERRCI_RD_DUPLICATE_PARAM = 4000301,
+ ERRCI_RD_INVALID_PARAM = 4000302,
+ ERRCI_RD_NOT_FOUND = 4040300,
+
+ //RD LINK
+ ERRCI_RDLINK_DUPLICATE_PARAM = 4000401,
+ ERRCI_RDLINK_INVALID_PARAM = 4000402,
+ ERRCI_RDLINK_NOT_FOUND = 4040400,
+
+ //GROUP
+ ERRCI_GROUP_DUPLICATE_PARAM = 4000501,
+ ERRCI_GROUP_INVALID_PARAM = 4000502,
+ ERRCI_GROUP_NOT_FOUND = 4040500,
+
+ //ACL
+ ERRCI_ACL_DUPLICATE_PARAM = 4000601,
+ ERRCI_ACL_INVALID_PARAM = 4000602,
+ ERRCI_ACL_NOT_FOUND = 4040600,
+
+ //CI
+ ERRCI_CI_DUPLICATE_PARAM = 4000701,
+ ERRCI_CI_INVALID_PARAM = 4000702,
+ ERRCI_CI_NOT_FOUND = 4040700,
+
+ //PUSH
+ ERRCI_PUSH_DUPLICATE_PARAM = 4000801,
+ ERRCI_PUSH_INVALID_PARAM = 4000802,
+ ERRCI_PUSH_NOT_FOUND = 4040800,
+
+ //COMMON
+ ERRCI_INTERNAL_SERVER_ERROR = 5000000,
+ ERRCI_DB_CONNECTION_FAIL = 5000002,
+
+ /**
+ * Error Code that Unknown error occurred
+ */
+ ERRCI_UNKNOWN = 6000000
+} ci_error_code_e;
+
+#endif //ES_COMMON_H_
--- /dev/null
+/* ****************************************************************
+ *
+ * Copyright 2017 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 <string.h>
+#include "ocstack.h"
+#include "es_common.h"
+#include "octypes.h"
+
+#ifndef ES_RESOURCE_HANDLER_H_
+#define ES_RESOURCE_HANDLER_H_
+
+typedef enum {
+ WIFI_INIT = 0,
+ WIFI_READY = 1,
+ WIFI_RESPONSE = 2,
+ WIFI_SET = 3,
+ WIFI_DONE
+} wifi_prov_state_e;
+
+typedef void (*es_wifi_cb)(es_result_e, es_wifi_prov_data_s *);
+typedef void (*es_cloud_cb)(es_result_e, es_cloud_prov_data_s *);
+typedef void (*es_dev_conf_cb)(es_result_e, es_dev_conf_prov_data_s *);
+
+/* Structure to represent a Light resource */
+typedef struct prov_resource_s {
+ OCResourceHandle handle;
+ things_prov_status_e status; // provisiong status
+ es_error_code_e last_err_code;
+ ci_error_code_e vd_err_code;
+} prov_resource_s;
+
+typedef struct {
+ OCResourceHandle handle;
+ wifi_mode_e supported_mode[NUM_WIFIMODE];
+ uint8_t num_mode; // the number of device's supported wifi modes
+ wifi_freq_e supported_freq;
+ char ssid[MAX_SSIDLEN]; // target network name, i.e. SSID for WLAN, MAC address for BT.
+ char cred[MAX_CREDLEN]; // credential information.
+ wifi_auth_type_e auth_type;
+ wifi_enc_type_e enc_type;
+ int discovery_channel;
+} wifi_resource_s;
+
+typedef struct {
+ OCResourceHandle handle;
+ char auth_code[THINGS_STRING_MAX_VALUE];
+ char auth_provider[THINGS_STRING_MAX_VALUE];
+ char ci_server[THINGS_STRING_MAX_VALUE];
+ char server_id[THINGS_STRING_MAX_VALUE];
+ char client_id[THINGS_STRING_MAX_VALUE];
+ char accesstoken[THINGS_STRING_MAX_VALUE];
+ int actoken_type;
+ char refreshtoken[THINGS_STRING_MAX_VALUE];
+ char uid[THINGS_STRING_MAX_VALUE];
+} cloud_resource_s;
+
+typedef struct {
+ OCResourceHandle handle;
+ char devName[MAX_DEVICELEN];
+ char language[THINGS_STRING_MAX_VALUE];
+ char country[THINGS_STRING_MAX_VALUE];
+ char device_type[THINGS_STRING_MAX_VALUE];
+ char device_sub_type[THINGS_STRING_MAX_VALUE];
+ char datetime[THINGS_STRING_MAX_VALUE];
+} dev_conf_resource_s;
+
+void set_ssid_in_wifi_resource(const char *ssid);
+void init_es_cloud_prov_data(es_cloud_prov_data_s *p_cloud_data);
+void clone_es_cloud_prov_data(es_cloud_prov_data_s *des, es_cloud_prov_data_s *src);
+void set_wifi_prov_state(wifi_prov_state_e value);
+wifi_prov_state_e get_wifi_prov_state(void);
+
+OCStackResult create_easysetup_resources(bool is_secured, es_resource_mask_e resource_mask);
+OCStackResult delete_easysetup_resources();
+OCStackResult prov_rsc_notify_all_observers(void);
+
+things_es_enrollee_state_e get_enrollee_state(void);
+
+OCStackResult set_device_property(es_device_property *device_property);
+OCStackResult set_enrollee_state(things_es_enrollee_state_e es_state);
+OCStackResult set_enrollee_err_code(es_error_code_e es_err_code);
+
+void get_target_network_info_from_prov_resource(char *, char *);
+void register_wifi_rsrc_event_callback(es_wifi_cb);
+void register_cloud_rsrc_event_callback(es_cloud_cb);
+void register_dev_conf_rsrc_event_callback(es_dev_conf_cb);
+void unregister_resource_event_callback(void);
+
+const char *get_result(OCStackResult result);
+const char *get_prov_status(things_es_enrollee_state_e status);
+const char *get_prov_errcode(es_error_code_e last_errcode);
+
+bool start_cloud_provisioning(void *CIinfo);
+
+#endif //ES_RESOURCE_HANDLER_H_
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 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 "resource_handler.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+#ifdef __ST_THINGS_RTOS__
+#include <net/lwip/ipv4/inet.h>
+#else
+#include <arpa/inet.h>
+#endif
+#include "things_api.h"
+#include "octypes.h"
+#include "ocpayload.h"
+#include "oic_string.h"
+#include "things_logger.h"
+#include "cloud_manager.h"
+#include "things_string_util.h"
+#include "things_malloc.h"
+#include "cautilinterface.h"
+#include "things_common.h"
+
+#include "../utils/inc/things_network.h"
+#include <time.h>
+
+#define ES_RH_TAG "[ezsetup-RH]"
+
+static prov_resource_s g_prov_resource;
+static wifi_resource_s g_wifi_resource;
+static cloud_resource_s g_cloud_resource;
+static dev_conf_resource_s g_dev_conf_resource;
+
+/**
+ * @var g_wifi_data
+ * @brief Structure for holding the target information required to
+ * connect to the target network
+ */
+static es_wifi_prov_data_s g_wifi_data;
+
+/**
+ * @var g_dev_conf_data
+ * @brief Structure for holding the device information
+ */
+static es_dev_conf_prov_data_s g_dev_conf_data;
+
+/**
+ * @var g_cloud_data
+ * @brief Structure for holding the cloud information required to
+ * connect to CI Server
+ */
+static es_cloud_prov_data_s g_cloud_data;
+
+static wifi_prov_state_e es_wifi_prov_state = WIFI_INIT;
+
+static pthread_mutex_t g_status_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+//-----------------------------------------------------------------------------
+// Private internal function prototypes
+//-----------------------------------------------------------------------------
+OCEntityHandlerResult things_entity_handler_cb(OCEntityHandlerFlag flag, OCEntityHandlerRequest *eh_request, void *callback);
+OCEntityHandlerResult process_get_request(OCEntityHandlerRequest *eh_request, OCRepPayload **payload);
+OCEntityHandlerResult process_put_request(OCEntityHandlerRequest *eh_request, OCRepPayload **payload);
+OCEntityHandlerResult process_post_request(OCEntityHandlerRequest *eh_request, OCRepPayload **payload);
+void update_prov_resource(OCEntityHandlerRequest *eh_request, OCRepPayload *input);
+void update_wifi_resource(OCRepPayload *input);
+bool update_cloud_resource(OCRepPayload *input);
+void update_dev_conf_resource(OCRepPayload *input);
+static int check_ci_server_ipv4(char *ci_server, es_cloud_prov_data_s *cloud_data);
+
+es_wifi_cb g_wifi_rsrc_evt_cb = NULL;
+es_cloud_cb g_cloud_rsrc_evt_cb = NULL;
+es_dev_conf_cb g_dev_conf_rsrc_evt_cb = NULL;
+
+static inline void delete_child_payload(OCRepPayload *payload)
+{
+ if (payload == NULL) {
+ return;
+ }
+
+ delete_child_payload(payload->next);
+ OCPayloadDestroy((OCPayload *) payload);
+}
+
+static bool compare_resource_interface(const char *from, const char *iface)
+{
+ bool ret = false;
+ char *str = NULL;
+ char *ptr = NULL;
+
+ if (from == NULL || iface == NULL) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, ES_RH_TAG, "invalid input data.(from=%s, iface=%s)", from, iface);
+ return ret;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "Input data.(from=%s, iface=%s)", from, iface);
+
+ if ((str = OICStrdup(from)) == NULL) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, ES_RH_TAG, "OICStrdup function is failed.");
+ return ret;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "strFrom=%s", str);
+
+ ptr = str;
+ while ((ptr = strtok(ptr, ";")) != NULL) {
+ if (strstr(ptr, ".if.")) {
+ char *if_ptr = NULL;
+ if_ptr = strtok(ptr, "=");
+ if_ptr = strtok(NULL, "=");
+
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "if_ptr=%s", if_ptr);
+
+ if (if_ptr != NULL && !strncmp(if_ptr, iface, strlen(iface))) {
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "Found interface.(%s)", iface);
+ ret = true;
+ break;
+ }
+ }
+
+ ptr = NULL;
+ }
+
+ free(str);
+ return ret;
+}
+
+static OCRepPayload *make_rep_payload(OCResourceHandle rsc_handle, OCDevAddr *dev_addr)
+{
+ OCRepPayload *add = NULL;
+ char *resource_type[1] = { NULL, };
+ char *resource_interface[1] = { NULL, };
+ size_t dimensions[MAX_REP_ARRAY_DEPTH] = { 1, 0, 0 };
+
+ if (rsc_handle == NULL || dev_addr == NULL) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, ES_RH_TAG, "Invalid input data.(rsc_handle=0x%X, dev_addr=0x%X)", rsc_handle, dev_addr);
+ return NULL;
+ }
+
+ if ((add = OCRepPayloadCreate()) == NULL) {
+ THINGS_LOG_ERROR(THINGS_ERROR, ES_RH_TAG, "Failed to allocate Payload");
+ return NULL;
+ }
+
+ add->base.type = PAYLOAD_TYPE_REPRESENTATION;
+
+ if (rsc_handle == g_wifi_resource.handle) {
+ resource_type[0] = OICStrdup(OC_RSRVD_ES_RES_TYPE_WIFI);
+ resource_interface[0] = OICStrdup(OC_RSRVD_INTERFACE_DEFAULT);
+ OCRepPayloadSetPropString(add, OC_RSRVD_HREF, OC_RSRVD_ES_URI_WIFI);
+ } else if (rsc_handle == g_dev_conf_resource.handle) {
+ resource_type[0] = OICStrdup(OC_RSRVD_ES_RES_TYPE_DEVCONF);
+ resource_interface[0] = OICStrdup(OC_RSRVD_INTERFACE_DEFAULT);
+ OCRepPayloadSetPropString(add, OC_RSRVD_HREF, OC_RSRVD_ES_URI_DEVCONF);
+ } else if (rsc_handle == g_cloud_resource.handle) {
+ resource_type[0] = OICStrdup(OC_RSRVD_ES_RES_TYPE_CLOUDSERVER);
+ resource_interface[0] = OICStrdup(OC_RSRVD_INTERFACE_DEFAULT);
+ OCRepPayloadSetPropString(add, OC_RSRVD_HREF, OC_RSRVD_ES_URI_CLOUDSERVER);
+ } else {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, ES_RH_TAG, "Not supported resource handler(rsc_handle=0x%X)", rsc_handle);
+ OCPayloadDestroy((OCPayload *) add);
+ return NULL;
+ }
+
+ OCRepPayloadSetStringArray(add, OC_RSRVD_RESOURCE_TYPE, (const char **)resource_type, dimensions);
+ OCRepPayloadSetStringArray(add, OC_RSRVD_INTERFACE, (const char **)resource_interface, dimensions);
+ /*! Added by st_things for Memory leak fix */
+ if (resource_type[0]) {
+ free(resource_type[0]);
+ }
+ if (resource_interface[0]) {
+ free(resource_interface[0]);
+ }
+
+ OCResourceProperty p = OCGetResourceProperties(rsc_handle);
+ OCRepPayload *policy = OCRepPayloadCreate();
+ if (!policy) {
+ THINGS_LOG_ERROR(THINGS_ERROR, ES_RH_TAG, "Failed to allocate Payload");
+ OCPayloadDestroy((OCPayload *) add);
+ return NULL;
+ }
+
+ OCRepPayloadSetPropInt(policy, OC_RSRVD_BITMAP, ((p & OC_DISCOVERABLE) | (p & OC_OBSERVABLE)));
+ if (p & OC_SECURE) {
+ OCRepPayloadSetPropBool(policy, OC_RSRVD_SECURE, p & OC_SECURE);
+ uint16_t securePort = CAGetAssignedPortNumber(dev_addr->adapter, dev_addr->flags);
+ OCRepPayloadSetPropInt(policy, OC_RSRVD_HOSTING_PORT, securePort);
+ }
+
+ OCRepPayloadSetPropObject(add, OC_RSRVD_POLICY, policy);
+ OCPayloadDestroy((OCPayload *) policy);
+
+ return add;
+}
+
+void set_wifi_prov_state(wifi_prov_state_e value)
+{
+ if (es_wifi_prov_state == (value - 1) || value == WIFI_INIT) {
+ es_wifi_prov_state = value;
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "Set wifi_prov_state_e=%d", es_wifi_prov_state);
+ }
+}
+
+wifi_prov_state_e get_wifi_prov_state(void)
+{
+ return es_wifi_prov_state;
+}
+
+void register_wifi_rsrc_event_callback(es_wifi_cb cb)
+{
+ g_wifi_rsrc_evt_cb = cb;
+}
+
+void register_cloud_rsrc_event_callback(es_cloud_cb cb)
+{
+ g_cloud_rsrc_evt_cb = cb;
+}
+
+void register_dev_conf_rsrc_event_callback(es_dev_conf_cb cb)
+{
+ g_dev_conf_rsrc_evt_cb = cb;
+}
+
+void unregister_resource_event_callback()
+{
+ if (g_wifi_rsrc_evt_cb) {
+ g_wifi_rsrc_evt_cb = NULL;
+ }
+ if (g_cloud_rsrc_evt_cb) {
+ g_cloud_rsrc_evt_cb = NULL;
+ }
+ if (g_dev_conf_rsrc_evt_cb) {
+ g_dev_conf_rsrc_evt_cb = NULL;
+ }
+}
+
+void get_target_network_info_from_prov_resource(char *name, char *pass)
+{
+ if (name != NULL && pass != NULL) {
+ things_strncpy(name, g_wifi_resource.ssid, MAX_SSIDLEN);
+ things_strncpy(pass, g_wifi_resource.cred, MAX_CREDLEN);
+ }
+}
+
+OCStackResult initProvResource(bool is_secured)
+{
+ es_set_state(ES_STATE_INIT);
+ g_prov_resource.last_err_code = ES_ERRCODE_NO_ERROR;
+ g_prov_resource.vd_err_code = ERRCI_NO_ERROR;
+
+ OCStackResult res = OC_STACK_ERROR;
+ if (is_secured) {
+ res = OCCreateResource(&g_prov_resource.handle, OC_RSRVD_ES_RES_TYPE_PROV, OC_RSRVD_INTERFACE_DEFAULT, OC_RSRVD_ES_URI_PROV, things_entity_handler_cb, NULL, OC_DISCOVERABLE | OC_OBSERVABLE | OC_SECURE);
+ } else {
+ res = OCCreateResource(&g_prov_resource.handle, OC_RSRVD_ES_RES_TYPE_PROV, OC_RSRVD_INTERFACE_DEFAULT, OC_RSRVD_ES_URI_PROV, things_entity_handler_cb, NULL, OC_DISCOVERABLE | OC_OBSERVABLE);
+ }
+ if (res) {
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "Created Prov resource with result: %s", get_result(res));
+ return res;
+ }
+
+ res = OCBindResourceTypeToResource(g_prov_resource.handle, OC_RSRVD_RESOURCE_TYPE_COLLECTION);
+ if (res) {
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "Binding Resource type with result: %s", get_result(res));
+ return res;
+ }
+
+ res = OCBindResourceInterfaceToResource(g_prov_resource.handle, OC_RSRVD_INTERFACE_LL);
+ if (res) {
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "Created Prov resource with result: %s", get_result(res));
+ return res;
+ }
+ res = OCBindResourceInterfaceToResource(g_prov_resource.handle, OC_RSRVD_INTERFACE_BATCH);
+ if (res) {
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "Created Prov resource with result: %s", get_result(res));
+ return res;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "Created Prov resource with result: %s", get_result(res));
+ return res;
+}
+
+OCStackResult initWiFiResource(bool is_secured)
+{
+ OCStackResult res = OC_STACK_ERROR;
+
+ g_wifi_resource.supported_freq = WiFi_BOTH;
+ g_wifi_resource.supported_mode[0] = WiFi_11A;
+ g_wifi_resource.supported_mode[1] = WiFi_11B;
+ g_wifi_resource.supported_mode[2] = WiFi_11G;
+ g_wifi_resource.supported_mode[3] = WiFi_11N;
+ g_wifi_resource.supported_mode[4] = WiFi_11AC;
+ g_wifi_resource.num_mode = 5;
+ g_wifi_resource.auth_type = NONE_AUTH;
+ g_wifi_resource.enc_type = NONE_ENC;
+ memset(g_wifi_resource.ssid, 0, sizeof(char) *MAX_SSIDLEN);
+ memset(g_wifi_resource.cred, 0, sizeof(char) *MAX_CREDLEN);
+ g_wifi_resource.discovery_channel = 1;
+
+ if (is_secured) {
+ res = OCCreateResource(&g_wifi_resource.handle, OC_RSRVD_ES_RES_TYPE_WIFI, OC_RSRVD_INTERFACE_DEFAULT, OC_RSRVD_ES_URI_WIFI, things_entity_handler_cb, NULL, OC_DISCOVERABLE | OC_OBSERVABLE | OC_SECURE);
+ } else {
+ res = OCCreateResource(&g_wifi_resource.handle, OC_RSRVD_ES_RES_TYPE_WIFI, OC_RSRVD_INTERFACE_DEFAULT, OC_RSRVD_ES_URI_WIFI, things_entity_handler_cb, NULL, OC_DISCOVERABLE | OC_OBSERVABLE);
+ }
+
+ things_apply_current_ap();
+
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "Created WiFi resource with result: %s", get_result(res));
+ return res;
+
+}
+
+static void initCloudResourceData(cloud_resource_s *p_cloud_resource)
+{
+ if (p_cloud_resource == NULL) {
+ return;
+ }
+
+ memset(p_cloud_resource->auth_code, 0, sizeof(char) *THINGS_STRING_MAX_VALUE);
+ memset(p_cloud_resource->auth_provider, 0, sizeof(char) *THINGS_STRING_MAX_VALUE);
+ memset(p_cloud_resource->ci_server, 0, sizeof(char) *THINGS_STRING_MAX_VALUE);
+ memset(p_cloud_resource->server_id, 0, sizeof(char) *THINGS_STRING_MAX_VALUE);
+ memset(p_cloud_resource->client_id, 0, sizeof(char) *THINGS_STRING_MAX_VALUE);
+ memset(p_cloud_resource->accesstoken, 0, sizeof(char) *THINGS_STRING_MAX_VALUE);
+ p_cloud_resource->actoken_type = 0;
+ memset(p_cloud_resource->refreshtoken, 0, sizeof(char) *THINGS_STRING_MAX_VALUE);
+ memset(p_cloud_resource->uid, 0, sizeof(char) *THINGS_STRING_MAX_VALUE);
+
+}
+
+void init_es_cloud_prov_data(es_cloud_prov_data_s *p_cloud_data)
+{
+ if (p_cloud_data == NULL) {
+ return;
+ }
+
+ memset(p_cloud_data->auth_code, 0, sizeof(char) *THINGS_STRING_MAX_VALUE);
+ memset(p_cloud_data->auth_provider, 0, sizeof(char) *THINGS_STRING_MAX_VALUE);
+ memset(p_cloud_data->ci_server, 0, sizeof(char) *THINGS_STRING_MAX_VALUE);
+ memset(p_cloud_data->host_name, 0, sizeof(char) *THINGS_STRING_MAX_VALUE);
+ memset(p_cloud_data->ip, 0, sizeof(char) *IP_PORT);
+ memset(p_cloud_data->port, 0, sizeof(char) *IP_PORT);
+ memset(p_cloud_data->server_id, 0, sizeof(char) *THINGS_STRING_MAX_VALUE);
+ memset(p_cloud_data->client_id, 0, sizeof(char) *THINGS_STRING_MAX_VALUE);
+ memset(p_cloud_data->accesstoken, 0, sizeof(char) *THINGS_STRING_MAX_VALUE);
+ p_cloud_data->actoken_type = 0;
+ memset(p_cloud_data->refreshtoken, 0, sizeof(char) *THINGS_STRING_MAX_VALUE);
+ memset(p_cloud_data->uid, 0, sizeof(char) *THINGS_STRING_MAX_VALUE);
+}
+
+void clone_es_cloud_prov_data(es_cloud_prov_data_s *des, es_cloud_prov_data_s *src)
+{
+ if (des == NULL || src == NULL) {
+ return;
+ }
+
+ memcpy(des->auth_code, src->auth_code, sizeof(char) *THINGS_STRING_MAX_VALUE);
+ memcpy(des->auth_provider, src->auth_provider, sizeof(char) *THINGS_STRING_MAX_VALUE);
+ memcpy(des->ci_server, src->ci_server, sizeof(char) *THINGS_STRING_MAX_VALUE);
+ memcpy(des->host_name, src->host_name, sizeof(char) *THINGS_STRING_MAX_VALUE);
+ memcpy(des->ip, src->ip, sizeof(char) *IP_PORT);
+ memcpy(des->port, src->port, sizeof(char) *IP_PORT);
+ memcpy(des->server_id, src->server_id, sizeof(char) *THINGS_STRING_MAX_VALUE);
+ memcpy(des->client_id, src->client_id, sizeof(char) *THINGS_STRING_MAX_VALUE);
+ memcpy(des->accesstoken, src->accesstoken, sizeof(char) *THINGS_STRING_MAX_VALUE);
+ des->actoken_type = src->actoken_type;
+ memcpy(des->refreshtoken, src->refreshtoken, sizeof(char) *THINGS_STRING_MAX_VALUE);
+ memcpy(des->uid, src->uid, sizeof(char) *THINGS_STRING_MAX_VALUE);
+}
+
+static void initESWiFiProvData(es_wifi_prov_data_s *p_wifi_data)
+{
+ if (p_wifi_data == NULL) {
+ return;
+ }
+
+ memset(p_wifi_data->ssid, 0, sizeof(char) *MAX_SSIDLEN);
+ memset(p_wifi_data->pwd, 0, sizeof(char) *MAX_CREDLEN);
+ p_wifi_data->authtype = -1;
+ p_wifi_data->enctype = -1;
+ p_wifi_data->discovery_channel = -1;
+}
+
+void set_ssid_in_wifi_resource(const char *ssid)
+{
+ if (ssid == NULL) {
+ memset(g_wifi_resource.ssid, 0, sizeof(char) *MAX_SSIDLEN);
+ memset(g_wifi_resource.cred, 0, sizeof(char) *MAX_CREDLEN);
+ g_wifi_resource.auth_type = NONE_AUTH;
+ g_wifi_resource.enc_type = NONE_ENC;
+ g_wifi_resource.discovery_channel = 0;
+ } else if (strncmp(ssid, g_wifi_data.ssid, strlen(g_wifi_data.ssid)) == 0) {
+ things_strncpy(g_wifi_resource.ssid, g_wifi_data.ssid, sizeof(char) *MAX_SSIDLEN);
+ things_strncpy(g_wifi_resource.cred, g_wifi_data.pwd, sizeof(char) *MAX_CREDLEN);
+ g_wifi_resource.auth_type = g_wifi_data.authtype;
+ g_wifi_resource.enc_type = g_wifi_data.enctype;
+ g_wifi_resource.discovery_channel = g_wifi_data.discovery_channel;
+ } else {
+ things_strncpy(g_wifi_resource.ssid, ssid, sizeof(char) *MAX_SSIDLEN);
+ memset(g_wifi_resource.cred, 0, sizeof(char) *MAX_CREDLEN);
+ g_wifi_resource.auth_type = NONE_AUTH;
+ g_wifi_resource.enc_type = NONE_ENC;
+ g_wifi_resource.discovery_channel = 1;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "Connected SSID=%s", ssid);
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "g_wifi_data.ssid=%s", g_wifi_data.ssid);
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "g_wifi_resource.ssid=%s", g_wifi_resource.ssid);
+}
+
+OCStackResult initCloudServerResource(bool is_secured)
+{
+ OCStackResult res = OC_STACK_ERROR;
+
+ initCloudResourceData(&g_cloud_resource);
+
+ if (is_secured) {
+ res = OCCreateResource(&g_cloud_resource.handle, OC_RSRVD_ES_RES_TYPE_CLOUDSERVER, OC_RSRVD_INTERFACE_DEFAULT, OC_RSRVD_ES_URI_CLOUDSERVER, things_entity_handler_cb, NULL, OC_DISCOVERABLE | OC_OBSERVABLE | OC_SECURE);
+ } else {
+ res = OCCreateResource(&g_cloud_resource.handle, OC_RSRVD_ES_RES_TYPE_CLOUDSERVER, OC_RSRVD_INTERFACE_DEFAULT, OC_RSRVD_ES_URI_CLOUDSERVER, things_entity_handler_cb, NULL, OC_DISCOVERABLE | OC_OBSERVABLE);
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "Created CloudServer resource with result: %s", get_result(res));
+ return res;
+
+}
+
+OCStackResult initDevConfResource(bool is_secured)
+{
+ OCStackResult res = OC_STACK_ERROR;
+
+ memset(g_dev_conf_resource.devName, 0, sizeof(char) *MAX_DEVICELEN);
+ memset(g_dev_conf_resource.country, 0, sizeof(char) *THINGS_STRING_MAX_VALUE);
+ memset(g_dev_conf_resource.language, 0, sizeof(char) *THINGS_STRING_MAX_VALUE);
+ memset(g_dev_conf_resource.device_type, 0, sizeof(char) *THINGS_STRING_MAX_VALUE);
+ memset(g_dev_conf_resource.device_sub_type, 0, sizeof(char) *THINGS_STRING_MAX_VALUE);
+ memset(g_dev_conf_resource.datetime, 0, sizeof(char) *THINGS_STRING_MAX_VALUE);
+
+ if (is_secured) {
+ res = OCCreateResource(&g_dev_conf_resource.handle, OC_RSRVD_ES_RES_TYPE_DEVCONF, OC_RSRVD_INTERFACE_DEFAULT, OC_RSRVD_ES_URI_DEVCONF, things_entity_handler_cb, NULL, OC_DISCOVERABLE | OC_OBSERVABLE | OC_SECURE);
+ } else {
+ res = OCCreateResource(&g_dev_conf_resource.handle, OC_RSRVD_ES_RES_TYPE_DEVCONF, OC_RSRVD_INTERFACE_DEFAULT, OC_RSRVD_ES_URI_DEVCONF, things_entity_handler_cb, NULL, OC_DISCOVERABLE | OC_OBSERVABLE);
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "Created dev_conf_s resource with result: %s", get_result(res));
+ return res;
+
+}
+
+void update_prov_resource(OCEntityHandlerRequest *eh_request, OCRepPayload *input)
+{
+ THINGS_LOG_V(THINGS_INFO, ES_RH_TAG, "g_prov_resource.status %d", get_enrollee_state());
+
+ if (eh_request->query) {
+ if (strstr(eh_request->query, OC_RSRVD_INTERFACE_BATCH)) {
+ // When Provisioning resource has a POST with BatchInterface
+ update_cloud_resource(input);
+ update_wifi_resource(input);
+ update_dev_conf_resource(input);
+ }
+ }
+}
+
+void update_wifi_resource(OCRepPayload *input)
+{
+ initESWiFiProvData(&g_wifi_data);
+
+ char *ssid = NULL;
+ if (OCRepPayloadGetPropString(input, OC_RSRVD_ES_SSID, &ssid) == false || ssid == NULL) {
+ return;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "Current AP SSID: %s", g_wifi_resource.ssid);
+ if (strncmp(ssid, g_wifi_resource.ssid, strlen(g_wifi_resource.ssid)) == 0) {
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "Already connected SSID(%s).", ssid);
+ free(ssid);
+ return;
+ }
+
+ things_strncpy(g_wifi_data.ssid, ssid, sizeof(g_wifi_data.ssid));
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "g_wifi_data.ssid : %s", g_wifi_data.ssid);
+
+ char *cred = NULL;
+ if (OCRepPayloadGetPropString(input, OC_RSRVD_ES_CRED, &cred)) {
+ things_strncpy(g_wifi_data.pwd, cred, sizeof(g_wifi_data.pwd));
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "g_wifi_data.pwd %s", g_wifi_data.pwd);
+ }
+
+ int64_t auth_type = -1;
+ if (OCRepPayloadGetPropInt(input, OC_RSRVD_ES_AUTHTYPE, &auth_type)) {
+ g_wifi_data.authtype = auth_type;
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "g_wifi_data.authtype %u", g_wifi_data.authtype);
+ }
+
+ int64_t enc_type = -1;
+ if (OCRepPayloadGetPropInt(input, OC_RSRVD_ES_ENCTYPE, &enc_type)) {
+ g_wifi_data.enctype = enc_type;
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "g_wifi_data.enctype %u", g_wifi_data.enctype);
+ }
+
+ int64_t channel = -1;
+ if (OCRepPayloadGetPropInt(input, OC_RSRVD_ES_VENDOR_DISCOVERYCHANNEL, &channel)) {
+ g_wifi_data.discovery_channel = channel;
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "g_wifi_data.discovery_channel %u", g_wifi_data.discovery_channel);
+ }
+
+ if (ssid || cred || auth_type != -1 || enc_type != -1) {
+ THINGS_LOG(THINGS_INFO, ES_RH_TAG, "Send WiFiRsrc Callback To ES");
+ PROFILING_TIME("WiFi Provisioning Start.");
+
+ // TODO : Need to check appropriateness of g_wifi_data
+ if (g_wifi_rsrc_evt_cb != NULL) {
+ g_wifi_rsrc_evt_cb(ES_OK, &g_wifi_data);
+ } else {
+ THINGS_LOG_ERROR(THINGS_ERROR, ES_RH_TAG, "g_wifi_rsrc_evt_cb is NULL");
+ }
+ }
+
+ /*! Added by st_things for memory Leak fix
+ */
+ if (ssid) {
+ free(ssid);
+ }
+ if (cred) {
+ free(cred);
+ }
+}
+
+bool update_cloud_resource(OCRepPayload *input)
+{
+ bool res = false;
+ initCloudResourceData(&g_cloud_resource);
+ init_es_cloud_prov_data(&g_cloud_data);
+
+ char *auth_code = NULL;
+ if (OCRepPayloadGetPropString(input, OC_RSRVD_ES_AUTHCODE, &auth_code)) {
+ things_strncpy(g_cloud_resource.auth_code, auth_code, sizeof(g_cloud_resource.auth_code));
+ things_strncpy(g_cloud_data.auth_code, auth_code, sizeof(g_cloud_data.auth_code));
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "g_cloud_resource.auth_code %s", g_cloud_resource.auth_code);
+ }
+
+ char *accesstoken = NULL;
+ if (OCRepPayloadGetPropString(input, OC_RSRVD_ES_VENDOR_ACCESS_TOKEN, &accesstoken)) {
+ things_strncpy(g_cloud_resource.accesstoken, accesstoken, sizeof(g_cloud_resource.accesstoken));
+ things_strncpy(g_cloud_data.accesstoken, accesstoken, sizeof(g_cloud_data.accesstoken));
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "g_cloud_resource.accesstoken %s", g_cloud_resource.accesstoken);
+ }
+
+ int accesstokenType = NULL;
+ if (OCRepPayloadGetPropInt(input, OC_RSRVD_ES_VENDOR_ACCESS_TOKEN_TYPE, &accesstokenType)) {
+ g_cloud_resource.actoken_type = accesstokenType;
+ g_cloud_data.actoken_type = accesstokenType;
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "g_cloud_resource.actoken_type %d", g_cloud_resource.actoken_type);
+ }
+
+ char *refreshtoken = NULL;
+ if (OCRepPayloadGetPropString(input, SC_RSRVD_ES_VENDOR_REFRESH_TOKEN, &refreshtoken)) {
+ things_strncpy(g_cloud_resource.refreshtoken, refreshtoken, sizeof(g_cloud_resource.refreshtoken));
+ things_strncpy(g_cloud_data.refreshtoken, refreshtoken, sizeof(g_cloud_data.refreshtoken));
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "g_cloud_resource.refreshtoken %s", g_cloud_resource.refreshtoken);
+ }
+
+ char *uid = NULL;
+ if (OCRepPayloadGetPropString(input, OC_RSRVD_ES_VENDOR_USER_ID, &uid)) {
+ things_strncpy(g_cloud_resource.uid, uid, sizeof(g_cloud_resource.uid));
+ things_strncpy(g_cloud_data.uid, uid, sizeof(g_cloud_data.uid));
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "g_cloud_resource.uid %s", g_cloud_resource.uid);
+ }
+
+ char *auth_provider = NULL;
+ if (OCRepPayloadGetPropString(input, OC_RSRVD_ES_AUTHPROVIDER, &auth_provider)) {
+ things_strncpy(g_cloud_resource.auth_provider, auth_provider, sizeof(g_cloud_resource.auth_provider));
+ things_strncpy(g_cloud_data.auth_provider, auth_provider, sizeof(g_cloud_data.auth_provider));
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "g_cloud_resource.auth_provider %s", g_cloud_resource.auth_provider);
+ }
+
+ char *ci_server = NULL;
+ if (OCRepPayloadGetPropString(input, OC_RSRVD_ES_CISERVER, &ci_server)) {
+ if (check_ci_server_ipv4(ci_server, &g_cloud_data) == 1) {
+ things_strncpy(g_cloud_resource.ci_server, ci_server, sizeof(g_cloud_resource.ci_server));
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "g_cloud_resource.ci_server %s", g_cloud_resource.ci_server);
+ } else {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, ES_RH_TAG, "check_ci_server_ipv4 is failed.");
+ g_prov_resource.last_err_code = ER_ERRCODE_INVALID_PROV_PAYLOAD;
+ g_prov_resource.vd_err_code = ERRCI_NO_ERROR;
+ }
+ }
+
+ char *server_id = NULL;
+ if (OCRepPayloadGetPropString(input, OC_RSRVD_ES_SERVERID, &server_id)) {
+ things_strncpy(g_cloud_resource.server_id, server_id, sizeof(g_cloud_resource.server_id));
+ things_strncpy(g_cloud_data.server_id, server_id, sizeof(g_cloud_data.server_id));
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "g_cloud_resource.server_id %s", g_cloud_resource.server_id);
+ }
+
+ char *client_id = NULL;
+ if (OCRepPayloadGetPropString(input, OC_RSRVD_ES_VENDOR_CLIENTID, &client_id)) {
+ things_strncpy(g_cloud_resource.client_id, client_id, sizeof(g_cloud_resource.client_id));
+ things_strncpy(g_cloud_data.client_id, client_id, sizeof(g_cloud_data.client_id));
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "g_cloud_resource.client_id %s", g_cloud_resource.client_id);
+ }
+
+ if ((g_cloud_data.auth_code[0] || (g_cloud_data.accesstoken[0] && g_cloud_data.refreshtoken[0])) && g_cloud_data.auth_provider[0] && g_cloud_data.ci_server[0]) {
+ THINGS_LOG(THINGS_INFO, ES_RH_TAG, "Send CloudRsrc Callback To ES");
+ PROFILING_TIME("Cloud Provisioning Start.");
+
+ if (g_cloud_rsrc_evt_cb != NULL) {
+ es_set_state(ES_STATE_INIT);
+ g_prov_resource.last_err_code = ERRCI_NO_ERROR;
+ g_prov_resource.vd_err_code = ERRCI_NO_ERROR;
+
+ g_cloud_rsrc_evt_cb(ES_OK, &g_cloud_data);
+ res = true;
+ } else {
+ THINGS_LOG_ERROR(THINGS_ERROR, ES_RH_TAG, "g_cloud_rsrc_evt_cb is NULL");
+ g_prov_resource.last_err_code = ER_ERRCODE_SYSTEM_ERROR;
+ g_prov_resource.vd_err_code = ERRCI_NO_ERROR;
+ }
+ } else {
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "Cloud Provisioning Data is invalid: auth_code=%s auth_provider=%s ci_server=%s", g_cloud_data.auth_code, g_cloud_data.auth_provider, g_cloud_data.ci_server);
+ }
+
+ if (auth_code) {
+ things_free(auth_code);
+ }
+
+ if (accesstoken) {
+ things_free(accesstoken);
+ }
+
+ /*! Added by st_things for leak fix */
+ if (refreshtoken) {
+ things_free(refreshtoken);
+ }
+ if (uid) {
+ things_free(uid);
+ }
+
+ if (auth_provider) {
+ things_free(auth_provider);
+ }
+
+ if (ci_server) {
+ things_free(ci_server);
+ }
+
+ if (server_id) {
+ things_free(server_id);
+ }
+
+ if (client_id) {
+ things_free(client_id);
+ }
+
+ return res;
+}
+
+void update_dev_conf_resource(OCRepPayload *input)
+{
+ char *country = NULL;
+ if (OCRepPayloadGetPropString(input, OC_RSRVD_ES_COUNTRY, &country)) {
+ things_strncpy(g_dev_conf_resource.country, country, sizeof(g_dev_conf_resource.country));
+ things_strncpy(g_dev_conf_data.country, country, sizeof(g_dev_conf_data.country));
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "g_dev_conf_resource.country %s", g_dev_conf_resource.country);
+ }
+
+ char *language = NULL;
+ if (OCRepPayloadGetPropString(input, OC_RSRVD_ES_LANGUAGE, &language)) {
+ things_strncpy(g_dev_conf_resource.language, language, sizeof(g_dev_conf_resource.language));
+ things_strncpy(g_dev_conf_data.language, language, sizeof(g_dev_conf_data.language));
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "g_dev_conf_resource.language %s", g_dev_conf_resource.language);
+ }
+
+ char *datetime = NULL;
+ if (OCRepPayloadGetPropString(input, OC_RSRVD_ES_VENDOR_UTC_DATE_TIME, &datetime)) {
+ things_strncpy(g_dev_conf_resource.datetime, datetime, sizeof(g_dev_conf_resource.datetime));
+ things_strncpy(g_dev_conf_data.datetime, datetime, sizeof(g_dev_conf_data.datetime));
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "g_dev_conf_resource.datetime %s", g_dev_conf_resource.datetime);
+
+ //Added by THINGS to set time in appliance yyyy-mm-ddThh-mm-ss
+ char chYear[5], chMonth[3], chDay[3], chHour[3], chMin[3], chSec[3];
+ struct tm stTime;
+ memset(&stTime, 0, sizeof(stTime));
+
+ int itr = 0;
+ for (; itr < 4; itr++) {
+ chYear[itr] = g_dev_conf_resource.datetime[itr];
+ }
+ chYear[itr] = '\0';
+ stTime.tm_year = (atoi(chYear) - 1900);
+
+ chMonth[0] = g_dev_conf_resource.datetime[++itr];
+ chMonth[1] = g_dev_conf_resource.datetime[++itr];
+ chMonth[2] = '\0';
+ stTime.tm_mon = (atoi(chMonth) - 1);
+
+ itr++;
+ chDay[0] = g_dev_conf_resource.datetime[++itr];
+ chDay[1] = g_dev_conf_resource.datetime[++itr];
+ chDay[2] = '\0';
+ stTime.tm_mday = atoi(chDay);
+
+ itr++;
+ chHour[0] = g_dev_conf_resource.datetime[++itr];
+ chHour[1] = g_dev_conf_resource.datetime[++itr];
+ chHour[2] = '\0';
+ stTime.tm_hour = atoi(chHour);
+
+ itr++;
+ chMin[0] = g_dev_conf_resource.datetime[++itr];
+ chMin[1] = g_dev_conf_resource.datetime[++itr];
+ chMin[2] = '\0';
+ stTime.tm_min = atoi(chMin);
+
+ itr++;
+ chSec[0] = g_dev_conf_resource.datetime[++itr];
+ chSec[1] = g_dev_conf_resource.datetime[++itr];
+ chSec[2] = '\0';
+ stTime.tm_sec = atoi(chSec);
+
+ unsigned int epTime = (unsigned int)mktime(&stTime);
+
+ struct timespec current_time;
+
+ current_time.tv_sec = epTime;
+ current_time.tv_nsec = 0;
+
+ if (clock_settime(CLOCK_REALTIME, ¤t_time) != 0) {
+ THINGS_LOG_ERROR(THINGS_ERROR, ES_RH_TAG, "Failed to clock_settime");
+ }
+ }
+
+ if (country || language || datetime) {
+ THINGS_LOG(THINGS_INFO, ES_RH_TAG, "Send DevConfRsrc Callback To ES");
+
+ // TODO : Need to check appropriateness of g_dev_conf_data
+ if (g_dev_conf_rsrc_evt_cb != NULL) {
+ g_dev_conf_rsrc_evt_cb(ES_OK, &g_dev_conf_data);
+ } else {
+ THINGS_LOG_ERROR(THINGS_ERROR, ES_RH_TAG, "g_dev_conf_rsrc_evt_cb is NULL");
+ }
+ }
+
+ /*! Added by st_things for memory Leak fix
+ */
+ if (country) {
+ free(country);
+ }
+ if (language) {
+ free(language);
+ }
+ if (datetime) {
+ free(datetime);
+ }
+}
+
+OCRepPayload *construct_response_of_wifi(const char *interface)
+{
+ OCRepPayload *payload = OCRepPayloadCreate();
+ if (!payload) {
+ THINGS_LOG_ERROR(THINGS_ERROR, ES_RH_TAG, "Failed to allocate Payload");
+ return NULL;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "constructResponse wifi res");
+ OCRepPayloadSetUri(payload, OC_RSRVD_ES_URI_WIFI);
+
+ OCRepPayload *rep_payload = NULL;
+ OCRepPayload *tempPayload = NULL;
+ if (interface != NULL && !strncmp(interface, OC_RSRVD_INTERFACE_BATCH, strlen(OC_RSRVD_INTERFACE_BATCH))) { // Temporary Code.
+ char *interfaces[1] = { NULL, };
+ char *resource_types[1] = { NULL, };
+ size_t interfacesDimensions[MAX_REP_ARRAY_DEPTH] = { 1, 0, 0 };
+ size_t resourceTypesDimensions[MAX_REP_ARRAY_DEPTH] = { 1, 0, 0 };
+
+ rep_payload = OCRepPayloadCreate();
+ if (!rep_payload) {
+ THINGS_LOG_ERROR(THINGS_ERROR, ES_RH_TAG, "Failed to allocate rep_payload");
+ goto GOTO_ERROR;
+ }
+ // Swap
+ tempPayload = payload;
+ payload = rep_payload;
+
+ interfaces[0] = OICStrdup(OC_RSRVD_INTERFACE_DEFAULT);
+ OCRepPayloadSetStringArray(payload, OC_RSRVD_INTERFACE, (const char **)interfaces, interfacesDimensions);
+
+ resource_types[0] = OICStrdup(OC_RSRVD_ES_RES_TYPE_WIFI);
+ OCRepPayloadSetStringArray(payload, OC_RSRVD_RESOURCE_TYPE, (const char **)resource_types, resourceTypesDimensions);
+ /*! Added by st_things for memory Leak fix
+ */
+ if (interfaces[0]) {
+ free(interfaces[0]);
+ }
+ if (resource_types[0]) {
+ free(resource_types[0]);
+ }
+ } else {
+ OCRepPayloadAddInterface(payload, OC_RSRVD_INTERFACE_DEFAULT);
+ OCRepPayloadAddResourceType(payload, OC_RSRVD_ES_RES_TYPE_WIFI);
+ }
+
+ size_t dimensions[MAX_REP_ARRAY_DEPTH] = { g_wifi_resource.num_mode, 0, 0 };
+ int64_t *modes_64 = (int64_t *)malloc(g_wifi_resource.num_mode * sizeof(int64_t));
+ for (int i = 0; i < g_wifi_resource.num_mode; ++i) {
+ modes_64[i] = g_wifi_resource.supported_mode[i];
+ }
+
+ OCRepPayloadSetIntArray(payload, OC_RSRVD_ES_SUPPORTEDWIFIMODE, (int64_t *) modes_64, dimensions);
+ OCRepPayloadSetPropInt(payload, OC_RSRVD_ES_SUPPORTEDWIFIFREQ, g_wifi_resource.supported_freq);
+ OCRepPayloadSetPropString(payload, OC_RSRVD_ES_SSID, g_wifi_resource.ssid);
+ OCRepPayloadSetPropString(payload, OC_RSRVD_ES_CRED, g_wifi_resource.cred);
+ OCRepPayloadSetPropInt(payload, OC_RSRVD_ES_AUTHTYPE, (int)g_wifi_resource.auth_type);
+ OCRepPayloadSetPropInt(payload, OC_RSRVD_ES_ENCTYPE, (int)g_wifi_resource.enc_type);
+ OCRepPayloadSetPropInt(payload, OC_RSRVD_ES_VENDOR_DISCOVERYCHANNEL, (int)g_wifi_resource.discovery_channel);
+
+ if (interface != NULL && !strncmp(interface, OC_RSRVD_INTERFACE_BATCH, strlen(OC_RSRVD_INTERFACE_BATCH))) {
+ payload = tempPayload;
+ OCRepPayloadSetPropObject(payload, OC_RSRVD_REPRESENTATION, rep_payload);
+ OCPayloadDestroy((OCPayload *) rep_payload);
+ rep_payload = NULL;
+ tempPayload = NULL;
+ }
+ /*! Added by st_things for memory Leak fix
+ */
+ if (tempPayload != NULL) {
+ OCPayloadDestroy((OCPayload *) tempPayload);
+ }
+ /*! Added by st_things for memory Leak fix
+ */
+ if (modes_64 != NULL) {
+ free(modes_64);
+ }
+
+ return payload;
+
+GOTO_ERROR:
+ if (payload != NULL) {
+ OCPayloadDestroy((OCPayload *) payload);
+ payload = NULL;
+ }
+
+ return NULL;
+}
+
+OCRepPayload *construct_response_of_cloud(const char *interface)
+{
+ OCRepPayload *payload = OCRepPayloadCreate();
+ if (!payload) {
+ THINGS_LOG_ERROR(THINGS_ERROR, ES_RH_TAG, "Failed to allocate Payload");
+ return NULL;
+ }
+
+ THINGS_LOG(THINGS_INFO, ES_RH_TAG, "constructResponse cloud res");
+ OCRepPayloadSetUri(payload, OC_RSRVD_ES_URI_CLOUDSERVER);
+
+ OCRepPayload *rep_payload = NULL;
+ OCRepPayload *tempPayload = NULL;
+ if (interface != NULL && !strncmp(interface, OC_RSRVD_INTERFACE_BATCH, strlen(OC_RSRVD_INTERFACE_BATCH))) { // Temporary Code.
+ char *interfaces[1] = { NULL, };
+ char *resource_types[1] = { NULL, };
+ size_t interfacesDimensions[MAX_REP_ARRAY_DEPTH] = { 1, 0, 0 };
+ size_t resourceTypesDimensions[MAX_REP_ARRAY_DEPTH] = { 1, 0, 0 };
+
+ rep_payload = OCRepPayloadCreate();
+ if (!rep_payload) {
+ THINGS_LOG_ERROR(THINGS_ERROR, ES_RH_TAG, "Failed to allocate rep_payload");
+ goto GOTO_ERROR;
+ }
+ // Swap
+ tempPayload = payload;
+ payload = rep_payload;
+
+ interfaces[0] = OICStrdup(OC_RSRVD_INTERFACE_DEFAULT);
+ OCRepPayloadSetStringArray(payload, OC_RSRVD_INTERFACE, (const char **)interfaces, interfacesDimensions);
+
+ resource_types[0] = OICStrdup(OC_RSRVD_ES_RES_TYPE_CLOUDSERVER);
+ OCRepPayloadSetStringArray(payload, OC_RSRVD_RESOURCE_TYPE, (const char **)resource_types, resourceTypesDimensions);
+ /*! Added by st_things for memory Leak fix
+ */
+ if (interfaces[0]) {
+ free(interfaces[0]);
+ }
+ if (resource_types[0]) {
+ free(resource_types[0]);
+ }
+ } else {
+ OCRepPayloadAddInterface(payload, OC_RSRVD_INTERFACE_DEFAULT);
+ OCRepPayloadAddResourceType(payload, OC_RSRVD_ES_RES_TYPE_CLOUDSERVER);
+ }
+
+ OCRepPayloadSetPropString(payload, OC_RSRVD_ES_AUTHCODE, g_cloud_resource.auth_code);
+ OCRepPayloadSetPropString(payload, OC_RSRVD_ES_AUTHPROVIDER, g_cloud_resource.auth_provider);
+ OCRepPayloadSetPropString(payload, OC_RSRVD_ES_CISERVER, g_cloud_resource.ci_server);
+ OCRepPayloadSetPropString(payload, OC_RSRVD_ES_SERVERID, g_cloud_resource.server_id);
+ OCRepPayloadSetPropString(payload, OC_RSRVD_ES_VENDOR_CLIENTID, g_cloud_resource.client_id);
+ OCRepPayloadSetPropString(payload, OC_RSRVD_ES_VENDOR_ACCESS_TOKEN, g_cloud_resource.accesstoken);
+ OCRepPayloadSetPropInt(payload, OC_RSRVD_ES_VENDOR_ACCESS_TOKEN_TYPE, g_cloud_resource.actoken_type);
+ OCRepPayloadSetPropString(payload, SC_RSRVD_ES_VENDOR_REFRESH_TOKEN, g_cloud_resource.refreshtoken);
+ OCRepPayloadSetPropString(payload, OC_RSRVD_ES_VENDOR_USER_ID, g_cloud_resource.uid);
+
+ if (interface != NULL && !strncmp(interface, OC_RSRVD_INTERFACE_BATCH, strlen(OC_RSRVD_INTERFACE_BATCH))) {
+ payload = tempPayload;
+ OCRepPayloadSetPropObject(payload, OC_RSRVD_REPRESENTATION, rep_payload);
+ OCPayloadDestroy((OCPayload *) rep_payload);
+ rep_payload = NULL;
+ tempPayload = NULL;
+ }
+ /*! Added by st_things for memory Leak fix
+ */
+ if (tempPayload != NULL) {
+ OCPayloadDestroy((OCPayload *) tempPayload);
+ }
+
+ return payload;
+
+GOTO_ERROR:
+ if (payload != NULL) {
+ OCPayloadDestroy((OCPayload *) payload);
+ payload = NULL;
+ }
+
+ return NULL;
+}
+
+OCRepPayload *construct_response_of_dev_conf(const char *interface)
+{
+ OCRepPayload *payload = OCRepPayloadCreate();
+ if (!payload) {
+ THINGS_LOG_ERROR(THINGS_ERROR, ES_RH_TAG, "Failed to allocate Payload");
+ return NULL;
+ }
+
+ THINGS_LOG(THINGS_INFO, ES_RH_TAG, "constructResponse devConf res");
+ OCRepPayloadSetUri(payload, OC_RSRVD_ES_URI_DEVCONF);
+
+ OCRepPayload *rep_payload = NULL;
+ OCRepPayload *tempPayload = NULL;
+ if (interface != NULL && !strncmp(interface, OC_RSRVD_INTERFACE_BATCH, strlen(OC_RSRVD_INTERFACE_BATCH))) { // Temporary Code.
+ char *interfaces[1] = { NULL, };
+ char *resource_types[1] = { NULL, };
+ size_t interfacesDimensions[MAX_REP_ARRAY_DEPTH] = { 1, 0, 0 };
+ size_t resourceTypesDimensions[MAX_REP_ARRAY_DEPTH] = { 1, 0, 0 };
+
+ rep_payload = OCRepPayloadCreate();
+ if (!rep_payload) {
+ THINGS_LOG_ERROR(THINGS_ERROR, ES_RH_TAG, "Failed to allocate rep_payload");
+ goto GOTO_ERROR;
+ }
+ // Swap
+ tempPayload = payload;
+ payload = rep_payload;
+
+ interfaces[0] = OICStrdup(OC_RSRVD_INTERFACE_DEFAULT);
+ OCRepPayloadSetStringArray(payload, OC_RSRVD_INTERFACE, (const char **)interfaces, interfacesDimensions);
+
+ resource_types[0] = OICStrdup(OC_RSRVD_ES_RES_TYPE_DEVCONF);
+ OCRepPayloadSetStringArray(payload, OC_RSRVD_RESOURCE_TYPE, (const char **)resource_types, resourceTypesDimensions);
+ /*! Added by st_things for memory Leak fix
+ */
+ if (interfaces[0]) {
+ free(interfaces[0]);
+ }
+ if (resource_types[0]) {
+ free(resource_types[0]);
+ }
+ } else {
+ OCRepPayloadAddInterface(payload, OC_RSRVD_INTERFACE_DEFAULT);
+ OCRepPayloadAddResourceType(payload, OC_RSRVD_ES_RES_TYPE_DEVCONF);
+ }
+
+ OCRepPayloadSetPropString(payload, OC_RSRVD_ES_DEVNAME, g_dev_conf_resource.devName);
+ OCRepPayloadSetPropString(payload, OC_RSRVD_ES_LANGUAGE, g_dev_conf_resource.language);
+ OCRepPayloadSetPropString(payload, OC_RSRVD_ES_COUNTRY, g_dev_conf_resource.country);
+ OCRepPayloadSetPropString(payload, OC_RSRVD_ES_VENDOR_DEVTYPE, g_dev_conf_resource.device_type);
+ OCRepPayloadSetPropString(payload, OC_RSRVD_ES_VENDOR_DEVSUBTYPE, g_dev_conf_resource.device_sub_type);
+ OCRepPayloadSetPropString(payload, OC_RSRVD_ES_VENDOR_UTC_DATE_TIME, g_dev_conf_resource.datetime);
+
+ if (interface != NULL && !strncmp(interface, OC_RSRVD_INTERFACE_BATCH, strlen(OC_RSRVD_INTERFACE_BATCH))) {
+ payload = tempPayload;
+ OCRepPayloadSetPropObject(payload, OC_RSRVD_REPRESENTATION, rep_payload);
+ OCPayloadDestroy((OCPayload *) rep_payload);
+ rep_payload = NULL;
+ tempPayload = NULL;
+ }
+ /*! Added by st_things for memory Leak fix
+ */
+ if (tempPayload != NULL) {
+ OCPayloadDestroy((OCPayload *) tempPayload);
+ }
+
+ return payload;
+
+GOTO_ERROR:
+ if (payload != NULL) {
+ OCPayloadDestroy((OCPayload *) payload);
+ payload = NULL;
+ }
+
+ return NULL;
+}
+
+OCRepPayload *construct_response_of_prov(OCEntityHandlerRequest *eh_request)
+{
+ int childResCnt = 0;
+ const OCRepPayload *arrayPayload[3] = { NULL, };
+ OCRepPayload *payload = NULL;
+
+ if (g_wifi_resource.handle == NULL || g_dev_conf_resource.handle == NULL || g_cloud_resource.handle == NULL) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, ES_RH_TAG, "mandatory Resource handle is NULL.(WiFi=0x%X, dev_conf_s=0x%X, Cloud=0x%X)", g_wifi_resource.handle, g_dev_conf_resource.handle, g_cloud_resource.handle);
+ return NULL;
+ }
+
+ if ((payload = OCRepPayloadCreate()) == NULL) {
+ THINGS_LOG_ERROR(THINGS_ERROR, ES_RH_TAG, "Failed to allocate Payload");
+ return NULL;
+ }
+ // Requested interface is Link list interface
+ if (!eh_request->query || (eh_request->query && !strncmp(eh_request->query, "", strlen(""))) || (eh_request->query && compare_resource_interface(eh_request->query, OC_RSRVD_INTERFACE_LL)) || (eh_request->query && compare_resource_interface(eh_request->query, OC_RSRVD_INTERFACE_DEFAULT))) {
+ if ((arrayPayload[childResCnt] = make_rep_payload(g_wifi_resource.handle, &eh_request->devAddr)) == NULL) {
+ THINGS_LOG_ERROR(THINGS_ERROR, ES_RH_TAG, "It's failed making payload of wifi_resource_s-Representation");
+ goto GOTO_FAILED;
+ }
+ childResCnt++;
+
+ if ((arrayPayload[childResCnt] = make_rep_payload(g_dev_conf_resource.handle, &eh_request->devAddr)) == NULL) {
+ THINGS_LOG_ERROR(THINGS_ERROR, ES_RH_TAG, "It's failed making payload of dev_conf_resource_s-Representation");
+ goto GOTO_FAILED;
+ }
+ childResCnt++;
+
+ if ((arrayPayload[childResCnt] = make_rep_payload(g_cloud_resource.handle, &eh_request->devAddr)) == NULL) {
+ THINGS_LOG_ERROR(THINGS_ERROR, ES_RH_TAG, "It's failed making payload of cloud_resource_s-Representation");
+ goto GOTO_FAILED;
+ }
+ childResCnt++;
+
+ size_t dimensions[MAX_REP_ARRAY_DEPTH] = { childResCnt, 0, 0 };
+
+ if (!eh_request->query || !strncmp(eh_request->query, "", strlen("")) || compare_resource_interface(eh_request->query, OC_RSRVD_INTERFACE_LL) == false) {
+ THINGS_LOG(THINGS_INFO, ES_RH_TAG, "constructResponse prov res");
+ OCRepPayloadSetUri(payload, OC_RSRVD_ES_URI_PROV);
+ OCRepPayloadAddInterface(payload, OC_RSRVD_INTERFACE_DEFAULT);
+ OCRepPayloadAddInterface(payload, OC_RSRVD_INTERFACE_LL);
+ OCRepPayloadAddInterface(payload, OC_RSRVD_INTERFACE_BATCH);
+ OCRepPayloadAddResourceType(payload, OC_RSRVD_ES_RES_TYPE_PROV);
+ OCRepPayloadAddResourceType(payload, OC_RSRVD_RESOURCE_TYPE_COLLECTION);
+
+ OCRepPayloadSetPropInt(payload, OC_RSRVD_ES_PROVSTATUS, get_enrollee_state());
+ OCRepPayloadSetPropInt(payload, OC_RSRVD_ES_LAST_ERRORCODE, g_prov_resource.last_err_code);
+ OCRepPayloadSetPropInt(payload, OC_RSRVD_ES_VENDOR_ERRORCODE, g_prov_resource.vd_err_code);
+ }
+
+ OCRepPayloadSetPropObjectArray(payload, OC_RSRVD_ES_LINKS, arrayPayload, dimensions);
+
+ for (int i = 0; i < childResCnt; i++) {
+ OCPayloadDestroy((OCPayload *) arrayPayload[i]);
+ }
+
+ } else if (eh_request->query && compare_resource_interface(eh_request->query, OC_RSRVD_INTERFACE_BATCH)) {
+ THINGS_LOG(THINGS_INFO, ES_RH_TAG, "constructResponse prov res");
+ OCRepPayloadSetUri(payload, OC_RSRVD_ES_URI_PROV);
+
+ OCRepPayload *rep_payload = NULL;
+ char *interfaces[3] = { NULL, };
+ char *resource_types[2] = { NULL, };
+ size_t interfacesDimensions[MAX_REP_ARRAY_DEPTH] = { 3, 0, 0 };
+ size_t resourceTypesDimensions[MAX_REP_ARRAY_DEPTH] = { 2, 0, 0 };
+
+ rep_payload = OCRepPayloadCreate();
+ if (!rep_payload) {
+ THINGS_LOG_ERROR(THINGS_ERROR, ES_RH_TAG, "Failed to allocate rep_payload");
+ goto GOTO_FAILED;
+ }
+
+ interfaces[0] = OICStrdup(OC_RSRVD_INTERFACE_DEFAULT);
+ interfaces[1] = OICStrdup(OC_RSRVD_INTERFACE_LL);
+ interfaces[2] = OICStrdup(OC_RSRVD_INTERFACE_BATCH);
+ OCRepPayloadSetStringArray(rep_payload, OC_RSRVD_INTERFACE, (const char **)interfaces, interfacesDimensions);
+
+ resource_types[0] = OICStrdup(OC_RSRVD_ES_RES_TYPE_PROV);
+ resource_types[1] = OICStrdup(OC_RSRVD_RESOURCE_TYPE_COLLECTION);
+ OCRepPayloadSetStringArray(rep_payload, OC_RSRVD_RESOURCE_TYPE, (const char **)resource_types, resourceTypesDimensions);
+
+ OCRepPayloadSetPropInt(rep_payload, OC_RSRVD_ES_PROVSTATUS, get_enrollee_state());
+ OCRepPayloadSetPropInt(rep_payload, OC_RSRVD_ES_LAST_ERRORCODE, g_prov_resource.last_err_code);
+ OCRepPayloadSetPropInt(rep_payload, OC_RSRVD_ES_VENDOR_ERRORCODE, g_prov_resource.vd_err_code);
+
+ OCRepPayloadSetPropObject(payload, OC_RSRVD_REPRESENTATION, rep_payload);
+ OCPayloadDestroy((OCPayload *) rep_payload);
+ /*! Added by st_things for memory Leak fix
+ */
+ if (interfaces[0]) {
+ free(interfaces[0]);
+ }
+ if (interfaces[1]) {
+ free(interfaces[1]);
+ }
+ if (interfaces[2]) {
+ free(interfaces[2]);
+ }
+ if (resource_types[0]) {
+ free(resource_types[0]);
+ }
+ if (resource_types[1]) {
+ free(resource_types[1]);
+ }
+ }
+
+ if (eh_request->query) {
+ if (compare_resource_interface(eh_request->query, OC_RSRVD_INTERFACE_BATCH)) { // When Provisioning resource has a GET with BatchInterface
+ OCRepPayload *head = payload;
+
+ payload->next = construct_response_of_wifi(OC_RSRVD_INTERFACE_BATCH);
+ if (payload->next == NULL) {
+ goto GOTO_FAILED;
+ }
+
+ payload = payload->next;
+ payload->next = construct_response_of_cloud(OC_RSRVD_INTERFACE_BATCH);
+ if (payload->next == NULL) {
+ payload = head;
+ goto GOTO_FAILED;
+ }
+
+ payload = payload->next;
+ payload->next = construct_response_of_dev_conf(OC_RSRVD_INTERFACE_BATCH);
+ if (payload->next == NULL) {
+ payload = head;
+ goto GOTO_FAILED;
+ }
+
+ payload = head;
+ }
+ }
+
+ return payload;
+
+GOTO_FAILED:
+ for (int i = 0; i < childResCnt; i++) {
+ OCPayloadDestroy((OCPayload *) arrayPayload[i]);
+ }
+
+ delete_child_payload(payload);
+
+ return NULL;
+}
+
+OCStackResult create_easysetup_resources(bool is_secured, es_resource_mask_e resource_mask)
+{
+ OCStackResult res = OC_STACK_ERROR;
+ bool maskFlag = false;
+
+ res = initProvResource(is_secured);
+ if (res != OC_STACK_OK) {
+ // TODO: destroy logic will be added
+ THINGS_LOG_V_ERROR(THINGS_ERROR, ES_RH_TAG, "initProvResource result: %s", get_result(res));
+
+ return res;
+ }
+
+ if ((resource_mask & ES_WIFI_RESOURCE) == ES_WIFI_RESOURCE) {
+ maskFlag = true;
+ res = initWiFiResource(is_secured);
+ if (res != OC_STACK_OK) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, ES_RH_TAG, "initWiFiResource result: %s", get_result(res));
+ return res;
+ }
+
+ res = OCBindResource(g_prov_resource.handle, g_wifi_resource.handle);
+ if (res != OC_STACK_OK) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, ES_RH_TAG, "bind wifi_resource_s result: %s", get_result(res));
+ return res;
+ }
+
+ }
+
+ if ((resource_mask & ES_CLOUD_RESOURCE) == ES_CLOUD_RESOURCE) {
+ maskFlag = true;
+ res = initCloudServerResource(is_secured);
+ if (res != OC_STACK_OK) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, ES_RH_TAG, "initCloudResource result: %s", get_result(res));
+ return res;
+ }
+
+ res = OCBindResource(g_prov_resource.handle, g_cloud_resource.handle);
+ if (res != OC_STACK_OK) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, ES_RH_TAG, "bind cloud_resource_s result: %s", get_result(res));
+ return res;
+ }
+ }
+
+ if ((resource_mask & ES_DEVCONF_RESOURCE) == ES_DEVCONF_RESOURCE) {
+ maskFlag = true;
+ res = initDevConfResource(is_secured);
+ if (res != OC_STACK_OK) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, ES_RH_TAG, "initDevConf result: %s", get_result(res));
+ return res;
+ }
+
+ res = OCBindResource(g_prov_resource.handle, g_dev_conf_resource.handle);
+ if (res != OC_STACK_OK) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, ES_RH_TAG, "bind dev_conf_resource_s result: %s", get_result(res));
+ return res;
+ }
+ }
+
+ if (maskFlag == false) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, ES_RH_TAG, "Invalid ResourceMask");
+ return OC_STACK_ERROR;
+
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "Created all resources with result: %s", get_result(res));
+
+ return res;
+}
+
+OCStackResult delete_provisioning_resource()
+{
+ OCStackResult res = OCDeleteResource(g_prov_resource.handle);
+ if (res != OC_STACK_OK) {
+ THINGS_LOG_V(THINGS_INFO, ES_RH_TAG, "Deleting Prov resource error with result: %s", get_result(res));
+ }
+
+ return res;
+}
+
+OCStackResult delete_easysetup_resources()
+{
+ OCStackResult res = OC_STACK_ERROR;
+ if (g_wifi_resource.handle != NULL) {
+ res = OCUnBindResource(g_prov_resource.handle, g_wifi_resource.handle);
+ if (res != OC_STACK_OK) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, ES_RH_TAG, "Unbind wifi_resource_s error with result: %s", get_result(res));
+ }
+ }
+ if (g_cloud_resource.handle != NULL) {
+ res = OCUnBindResource(g_prov_resource.handle, g_cloud_resource.handle);
+ if (res != OC_STACK_OK) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, ES_RH_TAG, "Unbind cloud_resource_s error with result: %s", get_result(res));
+ }
+ }
+ if (g_dev_conf_resource.handle != NULL) {
+ res = OCUnBindResource(g_prov_resource.handle, g_dev_conf_resource.handle);
+ if (res != OC_STACK_OK) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, ES_RH_TAG, "Unbind dev_conf_resource_s error with result: %s", get_result(res));
+ }
+ }
+
+ if (g_wifi_resource.handle != NULL) {
+ res = OCDeleteResource(g_wifi_resource.handle);
+ if (res != OC_STACK_OK) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, ES_RH_TAG, "Deleting WiFi resource error with result: %s", get_result(res));
+ }
+ }
+
+ if (g_cloud_resource.handle != NULL) {
+ res = OCDeleteResource(g_cloud_resource.handle);
+ if (res != OC_STACK_OK) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, ES_RH_TAG, "Deleting CloudServer resource error with result: %s", get_result(res));
+ }
+ }
+
+ if (g_dev_conf_resource.handle != NULL) {
+ res = OCDeleteResource(g_dev_conf_resource.handle);
+ if (res != OC_STACK_OK) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, ES_RH_TAG, "Deleting dev_conf_s resource error with result: %s", get_result(res));
+ }
+ }
+
+ if (g_prov_resource.handle != NULL) {
+ res = OCDeleteResource(g_prov_resource.handle);
+ if (res != OC_STACK_OK) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, ES_RH_TAG, "Deleting Prov resource error with result: %s", get_result(res));
+ }
+ }
+
+ return res;
+}
+
+OCEntityHandlerResult process_get_request(OCEntityHandlerRequest *eh_request, OCRepPayload **payload)
+{
+ OCEntityHandlerResult eh_result = OC_EH_ERROR;
+ if (!eh_request) {
+ THINGS_LOG_ERROR(THINGS_ERROR, ES_RH_TAG, "Request is Null");
+ return eh_result;
+ }
+ if (eh_request->payload && eh_request->payload->type != PAYLOAD_TYPE_REPRESENTATION) {
+ THINGS_LOG_ERROR(THINGS_ERROR, ES_RH_TAG, "Incoming payload not a representation");
+ return eh_result;
+ }
+
+ OCRepPayload *getResp = NULL;
+
+ if (eh_request->resource == g_prov_resource.handle) {
+ getResp = construct_response_of_prov(eh_request);
+ } else if (eh_request->resource == g_wifi_resource.handle) {
+ getResp = construct_response_of_wifi(OC_RSRVD_INTERFACE_DEFAULT);
+ } else if (eh_request->resource == g_cloud_resource.handle) {
+ getResp = construct_response_of_cloud(OC_RSRVD_INTERFACE_DEFAULT);
+ } else if (eh_request->resource == g_dev_conf_resource.handle) {
+ getResp = construct_response_of_dev_conf(OC_RSRVD_INTERFACE_DEFAULT);
+ }
+
+ if (!getResp) {
+ THINGS_LOG_ERROR(THINGS_ERROR, ES_RH_TAG, "constructResponse failed");
+ return OC_EH_ERROR;
+ }
+
+ *payload = getResp;
+ eh_result = OC_EH_OK;
+ //eh_result = OC_EH_CONTENT;
+
+ return eh_result;
+}
+
+OCEntityHandlerResult process_post_request(OCEntityHandlerRequest *eh_request, OCRepPayload **payload)
+{
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "process_post_request enter");
+ OCEntityHandlerResult eh_result = OC_EH_ERROR;
+ if (eh_request->payload && eh_request->payload->type != PAYLOAD_TYPE_REPRESENTATION) {
+ THINGS_LOG_ERROR(THINGS_ERROR, ES_RH_TAG, "Incoming payload not a representation");
+ return eh_result;
+ }
+
+ OCRepPayload *input = (OCRepPayload *)(eh_request->payload);
+ if (!input) {
+ THINGS_LOG_ERROR(THINGS_ERROR, ES_RH_TAG, "Failed to parse");
+ return eh_result;
+ }
+ // TBD : Discuss about triggering flag (to be existed or not)
+ // ES_PS_PROVISIONING_COMPLETED state indicates that already provisioning is completed.
+ // A new request for provisioning means overriding existing network provisioning information.
+
+ if (eh_request->resource == g_prov_resource.handle) {
+ update_prov_resource(eh_request, input);
+ } else if (eh_request->resource == g_wifi_resource.handle) {
+ update_wifi_resource(input);
+ } else if (eh_request->resource == g_cloud_resource.handle) {
+ update_cloud_resource(input);
+ } else if (eh_request->resource == g_dev_conf_resource.handle) {
+ update_dev_conf_resource(input);
+ }
+
+ OCRepPayload *getResp = NULL;
+ if (eh_request->resource == g_prov_resource.handle) {
+ getResp = construct_response_of_prov(eh_request);
+ } else if (eh_request->resource == g_wifi_resource.handle) {
+ getResp = construct_response_of_wifi(OC_RSRVD_INTERFACE_DEFAULT);
+ } else if (eh_request->resource == g_cloud_resource.handle) {
+ getResp = construct_response_of_cloud(OC_RSRVD_INTERFACE_DEFAULT);
+ } else if (eh_request->resource == g_dev_conf_resource.handle) {
+ getResp = construct_response_of_dev_conf(OC_RSRVD_INTERFACE_DEFAULT);
+ }
+
+ if (!getResp) {
+ THINGS_LOG_ERROR(THINGS_ERROR, ES_RH_TAG, "constructResponse failed");
+ return OC_EH_ERROR;
+ }
+
+ *payload = getResp;
+ eh_result = OC_EH_OK;
+ //eh_result = OC_EH_CHANGED;
+
+ return eh_result;
+}
+
+OCEntityHandlerResult process_put_request(OCEntityHandlerRequest *eh_request, OCRepPayload **payload)
+{
+ (void)eh_request;
+ (void)payload;
+ OCEntityHandlerResult eh_result = OC_EH_ERROR;
+
+ return eh_result;
+}
+
+/**
+ * This is the entity handler for the registered resource.
+ * This is invoked by OCStack whenever it recevies a request for this resource.
+ */
+OCEntityHandlerResult things_entity_handler_cb(OCEntityHandlerFlag flag, OCEntityHandlerRequest *entity_handler_request, void *callback)
+{
+ (void)callback;
+ OCEntityHandlerResult eh_ret = OC_EH_ERROR;
+ OCEntityHandlerResponse response;
+ OCRepPayload *payload = NULL;
+
+ THINGS_LOG(THINGS_DEBUG, ES_RH_TAG, "Called OCEntityHandler.");
+
+ // Validate pointer
+ if (!entity_handler_request) {
+ THINGS_LOG_ERROR(THINGS_ERROR, ES_RH_TAG, "Invalid request pointer");
+ return OC_EH_ERROR;
+ }
+
+ if (flag & OC_REQUEST_FLAG) {
+ if (things_get_reset_mask(RST_EASY_SETUP_DISABLE) == true) {
+ THINGS_LOG(THINGS_INFO, ES_RH_TAG, "Easy Setup Disable.");
+ eh_ret = OC_EH_NOT_ACCEPTABLE;
+ } else if (g_prov_resource.handle != NULL) {
+ if (OC_REST_GET == entity_handler_request->method) {
+ THINGS_LOG(THINGS_INFO, ES_RH_TAG, "Received GET request");
+
+ eh_ret = process_get_request(entity_handler_request, &payload);
+
+ }
+// else if (OC_REST_PUT == entity_handler_request->method)
+// {
+// THINGS_LOG(THINGS_INFO, ES_RH_TAG, "Received PUT request");
+//
+// //PUT request will be handled in the internal implementation
+// if (g_prov_resource.handle != NULL)
+// {
+// eh_ret = process_put_request(entity_handler_request, &payload);
+// }
+// else
+// {
+// THINGS_LOG_ERROR(THINGS_ERROR, ES_RH_TAG, "Cannot process put");
+// eh_ret = OC_EH_ERROR;
+// }
+// }
+ else if (OC_REST_POST == entity_handler_request->method) {
+ THINGS_LOG(THINGS_INFO, ES_RH_TAG, "Received OC_REST_POST from client");
+
+ eh_ret = process_post_request(entity_handler_request, &payload);
+ } else {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, ES_RH_TAG, "Not yet Supported Request case(%d).", entity_handler_request->method);
+ eh_ret = OC_EH_ERROR;
+ }
+ } else {
+ THINGS_LOG_ERROR(THINGS_ERROR, ES_RH_TAG, "EZ-Setup Resource not Registered Yet~!!!!!");
+ }
+ // By default it is ==> eh_ret = OC_EH_ERROR;
+ //
+
+ // If the result isn't an error or forbidden, send response
+ //if (!((eh_ret == OC_EH_ERROR) || (eh_ret == OC_EH_FORBIDDEN)))
+ {
+ THINGS_LOG_V(THINGS_INFO, ES_RH_TAG, "\t\tRespone : (%d) ", (int)eh_ret);
+
+ response.numSendVendorSpecificHeaderOptions = 0;
+ memset(response.sendVendorSpecificHeaderOptions, 0, sizeof(response.sendVendorSpecificHeaderOptions));
+ memset(response.resourceUri, 0, sizeof(response.resourceUri));
+
+ // Format the response. Note this requires some info about the request
+ response.requestHandle = entity_handler_request->requestHandle;
+ response.resourceHandle = entity_handler_request->resource;
+ response.ehResult = eh_ret;
+ response.payload = (OCPayload *)(payload);
+ // Indicate that response is NOT in a persistent buffer
+ response.persistentBufferFlag = 0;
+
+ // Send the response
+ if (OCDoResponse(&response) != OC_STACK_OK) {
+ THINGS_LOG_ERROR(THINGS_ERROR, ES_RH_TAG, "Error sending response");
+ eh_ret = OC_EH_ERROR;
+ }
+ /*! Added by st_things for memory Leak fix
+ */
+ if (payload) {
+ OCPayloadDestroy((OCPayload *) payload);
+ }
+ payload = NULL;
+ }
+ // else
+ // {
+ // THINGS_LOG_D_ERROR(THINGS_ERROR, ES_RH_TAG, "Return value of Request Process has a error(%d).", eh_ret);
+ // }
+ }
+
+ if (flag & OC_OBSERVE_FLAG) {
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "Flag includes OC_OBSERVE_FLAG");
+ if (OC_OBSERVE_REGISTER == entity_handler_request->obsInfo.action) {
+ THINGS_LOG(THINGS_INFO, ES_RH_TAG, "Received OC_OBSERVE_REGISTER from client");
+ } else if (OC_OBSERVE_DEREGISTER == entity_handler_request->obsInfo.action) {
+ THINGS_LOG(THINGS_INFO, ES_RH_TAG, "Received OC_OBSERVE_DEREGISTER from client");
+ }
+ }
+
+ THINGS_LOG(THINGS_DEBUG, ES_RH_TAG, "Common Exit OCEntityHandler.");
+
+ set_wifi_prov_state(WIFI_RESPONSE);
+
+ return eh_ret;
+}
+
+OCStackResult prov_rsc_notify_all_observers(void)
+{
+ OCStackResult ret = OCNotifyAllObservers(g_prov_resource.handle, OC_HIGH_QOS);
+
+ switch (ret) {
+ case OC_STACK_OK:
+ THINGS_LOG(THINGS_INFO, ES_RH_TAG, "Sent notification to Cloud Resource Observers");
+ break;
+ case OC_STACK_NO_OBSERVERS:
+ THINGS_LOG(THINGS_INFO, ES_RH_TAG, "There is no exist registered Observer client.");
+ break;
+ default:
+ THINGS_LOG_V_ERROR(THINGS_ERROR, ES_RH_TAG, "Send notification Error : %d", ret);
+ break;
+ }
+
+ ret = OCNotifyAllObservers(g_cloud_resource.handle, OC_HIGH_QOS);
+
+ switch (ret) {
+ case OC_STACK_OK:
+ THINGS_LOG(THINGS_INFO, ES_RH_TAG, "Sent notification to Cloud Resource Observers");
+ break;
+ case OC_STACK_NO_OBSERVERS:
+ THINGS_LOG(THINGS_INFO, ES_RH_TAG, "There is no exist registered Observer client.");
+ break;
+ default:
+ THINGS_LOG_V_ERROR(THINGS_ERROR, ES_RH_TAG, "Send notification Error : %d", ret);
+ break;
+ }
+
+ return ret;
+}
+
+things_es_enrollee_state_e get_enrollee_state(void)
+{
+ things_es_enrollee_state_e Status = ES_STATE_INIT;
+
+ pthread_mutex_lock(&g_status_mutex);
+ Status = g_prov_resource.status;
+ pthread_mutex_unlock(&g_status_mutex);
+
+ return Status;
+}
+
+OCStackResult set_device_property(es_device_property *device_property)
+{
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "set_device_property IN");
+
+ g_wifi_resource.supported_freq = (device_property->WiFi).freq;
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "WiFi Freq : %d", g_wifi_resource.supported_freq);
+
+ int mode_idx = 0;
+ while ((device_property->WiFi).mode[mode_idx] != WiFi_EOF) {
+ g_wifi_resource.supported_mode[mode_idx] = (device_property->WiFi).mode[mode_idx];
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "WiFi Mode : %d", g_wifi_resource.supported_mode[mode_idx]);
+ mode_idx++;
+ }
+ g_wifi_resource.num_mode = mode_idx;
+
+ things_strncpy(g_dev_conf_resource.devName, (device_property->dev_conf_s).device_name, MAX_DEVICELEN);
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "Device Name : %s", g_dev_conf_resource.devName);
+
+ things_strncpy(g_dev_conf_resource.device_type, (device_property->dev_conf_s).device_type, THINGS_STRING_MAX_VALUE);
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "Device device_type : %s", g_dev_conf_resource.device_type);
+
+ things_strncpy(g_dev_conf_resource.device_sub_type, (device_property->dev_conf_s).device_sub_type, THINGS_STRING_MAX_VALUE);
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "Device device_sub_type : %s", g_dev_conf_resource.device_sub_type);
+
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "set_device_property OUT");
+ return OC_STACK_OK;
+}
+
+OCStackResult set_enrollee_state(things_es_enrollee_state_e es_state)
+{
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "set_enrollee_state IN");
+
+ pthread_mutex_lock(&g_status_mutex);
+ OCStackResult result = OC_STACK_ERROR;
+ things_es_enrollee_state_e preState = g_prov_resource.status;
+
+ if (g_prov_resource.last_err_code == ER_ERRCODE_SYSTEM_ERROR) {
+ g_prov_resource.status = ES_STATE_INIT;
+ THINGS_LOG_V_ERROR(THINGS_ERROR, ES_RH_TAG, "Please Check your System.(Status=%s , ErrCode=%s)", get_prov_status(g_prov_resource.status), get_prov_errcode(g_prov_resource.last_err_code));
+ goto GOTO_OUT;
+ }
+
+ switch (es_state) {
+ case ES_STATE_REGISTERING_TO_CLOUD:
+ if (preState != ES_STATE_CONNECTED_TO_ENROLLER && preState != es_state) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, ES_RH_TAG, "State(%s) is not allowed by Status Policy.(pre-status: %s)", get_prov_status(es_state), get_prov_status(g_prov_resource.status));
+ goto GOTO_OUT;
+ }
+ break;
+ case ES_STATE_REGISTERED_TO_CLOUD:
+ if (preState != ES_STATE_REGISTERING_TO_CLOUD && preState != es_state) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, ES_RH_TAG, "State(%s) is not allowed by Status Policy.(pre-status: %s)", get_prov_status(es_state), get_prov_status(g_prov_resource.status));
+ goto GOTO_OUT;
+ }
+ break;
+ case ES_STATE_PUBLISHING_RESOURCES_TO_CLOUD:
+ if (preState != ES_STATE_REGISTERED_TO_CLOUD && preState != ES_STATE_PUBLISHED_RESOURCES_TO_CLOUD && preState != es_state) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, ES_RH_TAG, "State(%s) is not allowed by Status Policy.(pre-status: %s)", get_prov_status(es_state), get_prov_status(g_prov_resource.status));
+ goto GOTO_OUT;
+ }
+ break;
+ case ES_STATE_PUBLISHED_RESOURCES_TO_CLOUD:
+ if (preState != ES_STATE_PUBLISHING_RESOURCES_TO_CLOUD && preState != es_state) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, ES_RH_TAG, "State(%s) is not allowed by Status Policy.(pre-status: %s)", get_prov_status(es_state), get_prov_status(g_prov_resource.status));
+ goto GOTO_OUT;
+ }
+ break;
+ }
+
+ if (g_prov_resource.status == es_state) {
+ result = OC_STACK_DUPLICATE_UUID;
+ } else {
+ g_prov_resource.status = es_state;
+ result = OC_STACK_OK;
+ }
+
+ THINGS_LOG_V(THINGS_INFO, ES_RH_TAG, "Enrollee Status : %s (%d)", get_prov_status(g_prov_resource.status), g_prov_resource.status);
+
+GOTO_OUT:
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "set_enrollee_state OUT");
+ pthread_mutex_unlock(&g_status_mutex);
+ return result;
+}
+
+OCStackResult set_cloud_err_code(ci_error_code_e es_err_code)
+{
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "set_cloud_err_code IN");
+
+ g_prov_resource.vd_err_code = es_err_code;
+ THINGS_LOG_V(THINGS_INFO, ES_RH_TAG, "Cloud ErrorCode : %d", g_prov_resource.vd_err_code);
+
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "set_cloud_err_code OUT");
+ return OC_STACK_OK;
+}
+
+OCStackResult set_enrollee_err_code(es_error_code_e es_err_code)
+{
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "set_enrollee_err_code IN");
+
+ if (g_prov_resource.last_err_code == ER_ERRCODE_SYSTEM_ERROR) {
+ es_set_state(ES_STATE_INIT);
+ THINGS_LOG_V_ERROR(THINGS_ERROR, ES_RH_TAG, "Please Check your System.(Status=%s , ErrCode=%s)", get_prov_status(get_enrollee_state()), get_prov_errcode(g_prov_resource.last_err_code));
+ return OC_STACK_ERROR;
+ }
+
+ g_prov_resource.last_err_code = es_err_code;
+ THINGS_LOG_V(THINGS_INFO, ES_RH_TAG, "Enrollee ErrorCode : %s(%d)", get_prov_errcode(g_prov_resource.last_err_code), g_prov_resource.last_err_code);
+
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "set_enrollee_err_code OUT");
+ return OC_STACK_OK;
+}
+
+const char *get_result(OCStackResult result)
+{
+ switch (result) {
+ case OC_STACK_OK:
+ return "OC_STACK_OK";
+ 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_RESOURCE_CHANGED:
+ return "OC_STACK_RESOURCE_CHANGED";
+ 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_NO_MEMORY:
+ return "OC_STACK_NO_MEMORY";
+ case OC_STACK_COMM_ERROR:
+ return "OC_STACK_COMM_ERROR";
+ case OC_STACK_INVALID_PARAM:
+ return "OC_STACK_INVALID_PARAM";
+ 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_NO_OBSERVERS:
+ return "OC_STACK_NO_OBSERVERS";
+ case OC_STACK_ERROR:
+ return "OC_STACK_ERROR";
+ case OC_STACK_UNAUTHORIZED_REQ:
+ return "OC_STACK_UNAUTHORIZED_REQ";
+ default:
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "Not Supported result value.(%d)", result);
+ return "Not defined OCResult.";
+ }
+}
+
+const char *get_prov_status(things_es_enrollee_state_e status)
+{
+ switch (status) {
+ case ES_STATE_INIT:
+ return "ES_STATE_INIT";
+ case ES_STATE_CONNECTING_TO_ENROLLER:
+ return "ES_STATE_CONNECTING_TO_ENROLLER";
+ case ES_STATE_CONNECTED_TO_ENROLLER:
+ return "ES_STATE_CONNECTED_TO_ENROLLER";
+ case ES_STATE_FAILED_TO_CONNECT_TO_ENROLLER:
+ return "ES_STATE_FAILED_TO_CONNECT_TO_ENROLLER";
+ case ES_STATE_REGISTERING_TO_CLOUD:
+ return "ES_STATE_REGISTERING_TO_CLOUD";
+ case ES_STATE_REGISTERED_TO_CLOUD:
+ return "ES_STATE_REGISTERED_TO_CLOUD";
+ case ES_STATE_FAILED_TO_REGISTER_TO_CLOUD:
+ return "ES_STATE_FAILED_TO_REGISTER_TO_CLOUD";
+ case ES_STATE_PUBLISHING_RESOURCES_TO_CLOUD:
+ return "ES_STATE_PUBLISHING_RESOURCES_TO_CLOUD";
+ case ES_STATE_PUBLISHED_RESOURCES_TO_CLOUD:
+ return "ES_STATE_PUBLISHED_RESOURCES_TO_CLOUD";
+ case ES_STATE_FAILED_TO_PUBLISH_RESOURCES_TO_CLOUD:
+ return "ES_STATE_FAILED_TO_PUBLISH_RESOURCES_TO_CLOUD";
+ case ES_STATE_LOGOUT_FROM_CLOUD:
+ return "ES_STATE_LOGOUT_FROM_CLOUD";
+ default:
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "Not Supported State value.(%d)", status);
+ return "Not defined State";
+ }
+}
+
+const char *get_prov_errcode(es_error_code_e lastErrcode)
+{
+ switch (lastErrcode) {
+ case ES_ERRCODE_NO_ERROR:
+ return "ES_ERRCODE_NO_ERROR";
+ case ES_ERRCODE_SSID_NOT_FOUND:
+ return "ES_ERRCODE_SSID_NOT_FOUND";
+ case ES_ERRCODE_PW_WRONG:
+ return "ES_ERRCODE_PW_WRONG";
+ case ES_ERRCODE_IP_NOT_ALLOCATED:
+ return "ES_ERRCODE_IP_NOT_ALLOCATED";
+ case ES_ERRCODE_NO_INTERNETCONNECTION:
+ return "ES_ERRCODE_NO_INTERNETCONNECTION";
+ case ES_ERRCODE_TIMEOUT:
+ return "ES_ERRCODE_TIMEOUT";
+ case ES_ERRCODE_FAILED_TO_ACCESS_CLOUD_SERVER:
+ return "ES_ERRCODE_FAILED_TO_ACCESS_CLOUD_SERVER";
+ case ES_ERRCODE_NO_RESPONSE_FROM_CLOUD_SERVER:
+ return "ES_ERRCODE_NO_RESPONSE_FROM_CLOUD_SERVER";
+ case ES_ERRCODE_INVALID_AUTHCODE:
+ return "ES_ERRCODE_INVALID_AUTHCODE";
+ case ES_ERRCODE_INVALID_ACCESSTOKEN:
+ return "ES_ERRCODE_INVALID_ACCESSTOKEN";
+ case ES_ERRCODE_FAILED_TO_REFRESH_ACCESSTOKEN:
+ return "ES_ERRCODE_FAILED_TO_REFRESH_ACCESSTOKEN";
+ case ES_ERRCODE_FAILED_TO_FIND_REGISTERED_DEVICE_IN_CLOUD:
+ return "ES_ERRCODE_FAILED_TO_FIND_REGISTERED_DEVICE_IN_CLOUD";
+ case ES_ERRCODE_FAILED_TO_FIND_REGISTERED_USER_IN_CLOUD:
+ return "ES_ERRCODE_FAILED_TO_FIND_REGISTERED_USER_IN_CLOUD";
+ case ER_ERRCODE_INVALID_PROV_PAYLOAD:
+ return "ER_ERRCODE_INVALID_PROV_PAYLOAD";
+ case ER_ERRCODE_SYSTEM_ERROR:
+ return "ER_ERRCODE_SYSTEM_ERROR";
+ case ES_ERRCODE_UNKNOWN:
+ return "ES_ERRCODE_VENDOR_ERROR";
+ default:
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "Not Supported Error value.(%d)", lastErrcode);
+ return "Not Defined last_err_code";
+ }
+}
+
+/*********************************************************************
+ *
+ * Support CI server format.
+ *
+ * - IP:Port
+ * - coaps+tcp://IP
+ * - coaps+tcp://IP:Port
+ * - coaps+tcp://HostName
+ * - coaps+tcp://HostName:Port
+ *
+ *********************************************************************/
+static int check_ci_server_ipv4(char *ci_server, es_cloud_prov_data_s *cloudData)
+{
+ int length = 0;
+ char *pContext = NULL;
+ char *originCIServer = ci_server;
+ char *port = NULL;
+ struct in_addr ip;
+ ip.s_addr = 0;
+
+ if (ci_server == NULL || cloudData == NULL) {
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "ci_server(0x%X)/cloudData(0x%X) is NULL", ci_server, cloudData);
+ return 0;
+ }
+
+ if (strlen(ci_server) == 0) {
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "ci_server's length is 0");
+ return 0;
+ }
+
+ if (strstr(ci_server, UNSUPPORT_COAP_TCP_HOST) != NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, ES_RH_TAG, "%s is not support Type", UNSUPPORT_COAP_TCP_HOST);
+ return -1;
+ }
+ // Port Number analysis.
+ if ((pContext = strstr(ci_server, DEFAULT_COAP_TCP_HOST)) != NULL) {
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "%s type format", DEFAULT_COAP_TCP_HOST);
+
+ ci_server = pContext + strlen(DEFAULT_COAP_TCP_HOST);
+ port = DEFAULT_COAP_PORT;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "[Port] ci_server = %s, port=%s", ci_server, port);
+
+ if ((pContext = strchr(ci_server, ':')) != NULL) {
+ if (*(pContext + 1) == 0 || strlen(pContext + 1) > 5) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, ES_RH_TAG, "Port Num is out of range.(%s)", pContext + 1);
+ return -1;
+ }
+
+ if (atoi(pContext + 1) == 0) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, ES_RH_TAG, "Invalid Port Num.(Port is not number : %s)", pContext + 1);
+ return -1;
+ }
+
+ port = pContext + 1;
+ *pContext = 0;
+ }
+
+ if (port == NULL || (length = strlen(ci_server)) == 0) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, ES_RH_TAG, "Unsupported CI-server format.(port-num is NULL)", originCIServer);
+ return -1;
+ }
+ // ci_server analysis (IP/HostName)
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "[IP] ci_server = %s", ci_server);
+
+ if (inet_aton(ci_server, &ip) == 0 || ip.s_addr == 0) {
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "ci_server is Host Name.(%s)", ci_server);
+ things_strncpy(cloudData->host_name, ci_server, sizeof(cloudData->host_name));
+ memset(cloudData->ip, 0, IP_PORT);
+ things_strncpy(cloudData->port, port, sizeof(cloudData->port));
+ } else {
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "ci_server is ip address.(%s)", ci_server);
+ things_strncpy(cloudData->ip, ci_server, sizeof(cloudData->ip));
+ memset(cloudData->host_name, 0, THINGS_STRING_MAX_VALUE);
+ things_strncpy(cloudData->port, port, sizeof(cloudData->port));
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "Host=%s, IP=%s, Port=%s", cloudData->host_name, cloudData->ip, cloudData->port);
+
+ things_strncpy(cloudData->ci_server, ci_server, sizeof(cloudData->ci_server));
+ cloudData->ci_server[length] = ':';
+ cloudData->ci_server[length + 1] = 0;
+ if (things_strcat(cloudData->ci_server, THINGS_STRING_MAX_VALUE, (const char *)cloudData->port) == NULL) {
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "things_strcat is failed.");
+ return -1;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "cloudData->ci_server = %s", cloudData->ci_server);
+
+ return 1;
+}
+
+bool start_cloud_provisioning(void *cloud_info)
+{
+ bool res = false;
+ int length = 0;
+ char *host = NULL;
+ char *CIServer = NULL;
+ things_cloud_info_s *CIinfo = (things_cloud_info_s *) cloud_info;
+ OCRepPayload *payload = NULL;
+
+ if (CIinfo == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, ES_RH_TAG, "Invalid arguments.");
+ return false;
+ }
+
+ if ((payload = OCRepPayloadCreate()) == NULL) {
+ THINGS_LOG_ERROR(THINGS_ERROR, ES_RH_TAG, "Failed to allocate Payload");
+ return false;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "Domain = %s, IP = %s", CIinfo->domain, CIinfo->ip);
+
+ if (CIinfo->domain) {
+ length = strlen(DEFAULT_COAP_TCP_HOST) + strlen(CIinfo->domain) + 2;
+ if (CIinfo->port != NULL) {
+ length += strlen(CIinfo->port);
+ }
+ host = CIinfo->domain;
+ if ((CIServer = (char *)things_malloc(sizeof(char) * length)) == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, ES_RH_TAG, "Memory allocation is failed.");
+ goto GOTO_OUT;
+ }
+ memset(CIServer, 0, sizeof(char) * length);
+ things_strcat(CIServer, length, DEFAULT_COAP_TCP_HOST);
+ } else if (CIinfo->ip) {
+ length = strlen(CIinfo->ip) + 2;
+ if (CIinfo->port != NULL) {
+ length += strlen(CIinfo->port);
+ }
+ host = CIinfo->ip;
+ if ((CIServer = (char *)things_malloc(sizeof(char) * length)) == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, ES_RH_TAG, "Memory allocation is failed.");
+ goto GOTO_OUT;
+ }
+ memset(CIServer, 0, sizeof(char) * length);
+ } else {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, ES_RH_TAG, "Invalid arguments.(domain = 0x%X, ip = 0x%X)", CIinfo->domain, CIinfo->ip);
+ goto GOTO_OUT;
+ }
+
+ things_strcat(CIServer, length, host);
+ if (CIinfo->port != NULL && strlen(CIinfo->port) > 0) {
+ int LCIserver = strlen(CIServer);
+ CIServer[LCIserver] = ':';
+ CIServer[LCIserver + 1] = NULL;
+ things_strcat(CIServer, length, CIinfo->port);
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "CIServer = %s", CIServer);
+
+ if (OCRepPayloadSetPropString(payload, OC_RSRVD_ES_VENDOR_ACCESS_TOKEN, CIinfo->access_token) == false) {
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "Inserting \"%s\" property is failed.(value=\"%s\")", OC_RSRVD_ES_VENDOR_ACCESS_TOKEN, CIinfo->access_token);
+ goto GOTO_OUT;
+ }
+
+ if (CIinfo->access_token_type != NULL) {
+ if (OCRepPayloadSetPropString(payload, OC_RSRVD_ES_VENDOR_ACCESS_TOKEN_TYPE, CIinfo->access_token_type) == false) {
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "Inserting \"%s\" property is failed.(value=\"%s\")", OC_RSRVD_ES_VENDOR_ACCESS_TOKEN_TYPE, CIinfo->access_token_type);
+ goto GOTO_OUT;
+ }
+ }
+
+ if (OCRepPayloadSetPropString(payload, SC_RSRVD_ES_VENDOR_REFRESH_TOKEN, CIinfo->refresh_token) == false) {
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "Inserting \"%s\" property is failed.(value=\"%s\")", SC_RSRVD_ES_VENDOR_REFRESH_TOKEN, CIinfo->refresh_token);
+ goto GOTO_OUT;
+ }
+
+ if (OCRepPayloadSetPropString(payload, OC_RSRVD_ES_VENDOR_USER_ID, CIinfo->user_id) == false) {
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "Inserting \"%s\" property is failed.(value=\"%s\")", OC_RSRVD_ES_VENDOR_USER_ID, CIinfo->user_id);
+ goto GOTO_OUT;
+ }
+
+ if (OCRepPayloadSetPropString(payload, OC_RSRVD_ES_AUTHPROVIDER, CIinfo->auth_provider) == false) {
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "Inserting \"%s\" property is failed.(value=\"%s\")", OC_RSRVD_ES_AUTHPROVIDER, CIinfo->auth_provider);
+ goto GOTO_OUT;
+ }
+
+ if (OCRepPayloadSetPropString(payload, OC_RSRVD_ES_CISERVER, CIServer) == false) {
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "Inserting \"%s\" property is failed.(value=\"%s\")", OC_RSRVD_ES_CISERVER, CIServer);
+ goto GOTO_OUT;
+ }
+
+ if (OCRepPayloadSetPropString(payload, OC_RSRVD_ES_VENDOR_CLIENTID, CIinfo->client_id) == false) {
+ THINGS_LOG_D(THINGS_DEBUG, ES_RH_TAG, "Inserting \"%s\" property is failed.(value=\"%s\")", OC_RSRVD_ES_VENDOR_CLIENTID, CIinfo->client_id);
+ goto GOTO_OUT;
+ }
+
+ res = update_cloud_resource(payload);
+
+GOTO_OUT:
+ if (CIServer) {
+ things_free(CIServer);
+ CIServer = NULL;
+ }
+
+ if (payload) {
+ OCRepPayloadDestroy(payload);
+ payload = NULL;
+ }
+
+ THINGS_LOG(THINGS_DEBUG, ES_RH_TAG, "Exit.");
+ return res;
+}
--- /dev/null
+###########################################################################
+#
+# Copyright 2017 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.
+#
+###########################################################################
+
+CSRCS += things_data_manager.c things_req_handler.c things_resource.c things_security_manager.c things_server_builder.c
+
+
+DEPPATH += --dep-path src/st_things/things_stack/src/common/framework
+VPATH += :src/st_things/things_stack/src/common/framework
\ No newline at end of file
--- /dev/null
+/* ****************************************************************
+ *
+ * Copyright 2017 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.
+ *
+ ******************************************************************/
+
+#ifndef _THINGS_COMMON_H_
+#define _THINGS_COMMON_H_
+
+#include "ocstack.h"
+
+typedef OCEntityHandlerResult(*request_handler_cb)(OCEntityHandlerFlag flag, OCEntityHandlerRequest *entity_handler_request, void *cb);
+
+typedef enum {
+ RST_COMPLETE = 0,
+ RST_EASY_SETUP_DISABLE = 1,
+ RST_CLOUD_MODULE_DISABLE = (1 << 1),
+ RST_CONTROL_MODULE_DISABLE = (1 << 2),
+ RST_CONTROL_QUEUE_EMPTY = (1 << 3),
+ RST_NOTI_MODULE_DISABLE = (1 << 4),
+ RST_DELETE_CLOUD_DEVICE_SUCCESS = (1 << 5),
+ RST_DELETE_CLOUD_DEVICE_FAILURE = (1 << 6),
+ RST_USER_CONFIRM_COMPLETED = (1 << 7),
+ RST_ALL_FLAG = 0xFFFFFFFF
+} rst_state_e;
+
+//-----------------------------------------------------------------------------
+// Function prototype
+//-----------------------------------------------------------------------------
+bool things_get_reset_mask(rst_state_e value);
+
+void things_control_queue_empty(void);
+
+#endif // _THINGS_COMMON_H_
--- /dev/null
+/* ****************************************************************
+ *
+ * Copyright 2017 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.
+ *
+ ******************************************************************/
+
+#ifndef _THINGS_DATA_MANAGER_H_
+#define _THINGS_DATA_MANAGER_H_
+
+#include "things_server_builder.h"
+#include "cloud_manager.h"
+#include "things_api.h"
+
+#include <wifi_manager/wifi_manager.h>
+
+#define MAX_DEVICE_TYPE_LENGTH (25)
+#define MAX_DEVICE_NAME_LENGTH (32)
+#define MAX_DEVICE_VER_P (32)
+#define MAX_DEVICE_VER_OS (32)
+#define MAX_DEVICE_VER_HW (32)
+#define MAX_DEVICE_VER_FW (32)
+#define MAX_DEVICE_ID_LENGTH (37)
+#define MAX_DEVICE_VENDER_ID (255)
+#define MAX_DEVICE_DESCRIPTION_LENGTH (255)
+#define MAX_DEVICE_CAPABILTY_CNT (50)
+#define MAX_DEVICE_MODEL_ID_LENGTH (64)
+#define MAX_FILE_ACCESS_CNT (10)
+#define MAX_URI_LENGTH_OCF (128)
+#define MAX_PROPERTY_CNT (20)
+#define MAX_FILE_PATH_LENGTH (250)
+#define MAX_PROPERTY_LENGTH_OCF (64)
+
+struct st_resource_type_s {
+ char rt[MAX_PROPERTY_LENGTH_OCF];
+ int prop_cnt;
+ struct things_attribute_info_s *prop[MAX_PROPERTY_CNT];
+} st_resource_type_s;
+
+struct col_resource_s {
+ char uri[MAX_URI_LENGTH_OCF];
+ char *interface_types[MAX_IT_CNT];
+ struct things_resource_info_s *links[MAX_DEVICE_CAPABILTY_CNT];
+ char *resource_types[MAX_RT_CNT];
+
+ int if_cnt;
+ int rt_cnt;
+ int link_cnt;
+ int policy;
+} col_resource_s;
+
+typedef struct st_device_s {
+ int no;
+ char type[MAX_DEVICE_TYPE_LENGTH];
+ char name[MAX_DEVICE_NAME_LENGTH];
+ char model_num[MAX_DEVICE_MODEL_ID_LENGTH];
+ char ver_p[MAX_DEVICE_VER_P]; // mnpv
+ char ver_os[MAX_DEVICE_VER_OS]; // mnhw
+ char ver_hw[MAX_DEVICE_VER_HW]; // mnhw
+ char ver_fw[MAX_DEVICE_VER_FW]; // mnfv
+ char device_id[MAX_DEVICE_ID_LENGTH]; // mnfv
+ char vender_id[MAX_DEVICE_VENDER_ID]; // mnfv
+ char description[MAX_DEVICE_DESCRIPTION_LENGTH];
+ struct col_resource_s collection[MAX_DEVICE_CAPABILTY_CNT];
+ struct things_resource_info_s single[MAX_DEVICE_CAPABILTY_CNT];
+
+ int capa_cnt;
+ int col_cnt;
+ int sig_cnt;
+ int is_physical;
+
+ struct things_resource_s *pchild_resources[MAX_DEVICE_CAPABILTY_CNT];
+} st_device_s;
+
+int dm_init_module(const char *info_Path);
+
+int dm_termiate_module(void);
+
+const char *dm_get_svrdb_file_path(void);
+const char *dm_get_certificate_file_path(void);
+const char *dm_get_privatekey_file_path(void);
+const char *dm_get_filename(int filenum);
+const char *dm_get_things_device_type(int device_id);
+const char *dm_get_resource_uri(int device_num, int index);
+const char *dm_get_things_cloud_address(char *customized_ci_server);
+
+const int dm_get_file_id(int filenum);
+const int dm_get_num_of_files(void);
+const int dm_get_num_of_children(int device_num);
+const int dm_get_wifi_property_interface();
+const int dm_get_ownership_transfer_method();
+const wifi_freq_e dm_get_wifi_property_freq();
+
+struct things_resource_s *dm_get_resource_instance(const char *uri, const int id);
+
+int dm_get_device_information(int *cnt, st_device_s ***list);
+
+long dm_get_num_of_dev_cnt(void);
+st_device_s *dm_get_info_of_dev(unsigned long number);
+bool dm_register_user_define_device_id(const int seq_thing_info, const char *dev_id);
+bool dm_register_device_id(void);
+int dm_register_resource(things_server_builder_s *builder);
+
+int save_acces_point_info(wifi_manager_ap_config_s *connect_config);
+int dm_update_things_cloud(es_cloud_signup_s *cl_data);
+int dm_load_legacy_cloud_data(es_cloud_signup_s **cl_data);
+
+bool dm_is_rsc_published(void);
+
+int dm_del_things_cloud_data(void);
+bool dm_is_there_things_cloud(void);
+
+int dm_validate_attribute_in_request(char *res_type, const void *payload);
+
+typedef enum {
+ es_conn_type_none = 0,
+ es_conn_type_softap = 1,
+ es_conn_type_ble = 2,
+} easysetup_connectivity_type_e;
+
+easysetup_connectivity_type_e dm_get_easysetup_connectivity_type(void);
+wifi_manager_softap_config_s *dm_get_softap_wifi_config(void);
+wifi_manager_ap_config_s *dm_get_homeap_wifi_config();
+
+#endif // _THINGS_DATA_MANAGER_H_
--- /dev/null
+/* ****************************************************************
+ *
+ * Copyright 2017 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.
+ *
+ ******************************************************************/
+
+#ifndef _THINGS_REQ_HANDLER_H_
+#define _THINGS_REQ_HANDLER_H_
+
+#include "ocstack.h"
+#include "things_common.h"
+#include "things_resource.h"
+#include "things_api.h"
+#include "octypes.h"
+
+typedef struct things_request_handler_s {
+ request_handler_cb entity_handler;
+
+ void (*init_module)(void);
+ void (*deinit_module)(void);
+ int (*notify_things_observers)(const char *uri);
+} things_request_handler_s;
+
+things_request_handler_s *get_handler_instance();
+
+typedef int (*stop_softap_func_type)(int value);
+typedef int (*handle_request_func_type)(struct things_resource_s *res);
+typedef char *(*get_notify_obs_uri_cb)(const char *Uri, const char *query);
+typedef OCEntityHandlerResult(*handle_request_interface_cb)(things_resource_s **ppst_target_resource);
+
+void release_handler_instance(things_request_handler_s *);
+int register_stop_softap_cb(stop_softap_func_type func);
+void notify_result_of_reset(things_resource_s *target_resource, bool result);
+int register_handle_request_func(handle_request_func_type get_func, handle_request_func_type set_func);
+
+#endif // _THINGS_REQ_HANDLER_H_
--- /dev/null
+/* ****************************************************************
+ *
+ * Copyright 2017 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.
+ *
+ ******************************************************************/
+
+#ifndef _THINGS_SECURITY_MANAGER_H_
+#define _THINGS_SECURITY_MANAGER_H_
+
+#include "srmutility.h"
+
+#ifdef __SECURED__
+/**
+ * @brief Authentication type for ownership transfer
+ * b00000001 (1): Just works authentication
+ * b00000010 (2): Random PIN based authentication
+ * b00000100 (4): Certificate based authentication
+ * b00001000 (8): Decentralized public key based authentication
+ * b00010000 (16): Preconfigured PIN based authentication
+ * b00100000 (32): Mutual Verification Just works authentication
+ */
+typedef enum things_auth_type_e {
+ AUTH_UNKNOW = (0x0),
+ AUTH_JUST_WORKS = (0x1 << 0),
+ AUTH_RANDOM_PIN = (0x1 << 1),
+ AUTH_CERTIFICATE = (0x1 << 2),
+ AUTH_DECENTRALIZED_PUB_KEY = (0x1 << 3),
+ AUTH_PRECONF_PIN = (0x1 << 4),
+ AUTH_JUST_WORKS_MUTUAL_VERIFIED = (0x1 << 5),
+ AUTH_CERTIFICATE_CONFIRM = (0x1 << 6),
+} things_auth_type_e;
+
+/**
+ * Access policy in least significant bits (from Spec):
+ * b00000001 (1): CREATE
+ * b00000010 (2): READ
+ * b00000100 (4): WRITE
+ * b00001000 (8): DELETE
+ * b00010000 (16): NOTIFY
+ * b00011111 (31) Full permission
+ */
+#define ACL_PERMISSION_CREATE (0x1 << 0)
+#define ACL_PERMISSION_READ (0x1 << 1)
+#define ACL_PERMISSION_WRITE (0x1 << 2)
+#define ACL_PERMISSION_DELETE (0x1 << 3)
+#define ACL_PERMISSION_NOTIFY (0x1 << 4)
+#define ACL_PERMISSION_FULL (ACL_PERMISSION_CREATE | \
+ ACL_PERMISSION_READ | \
+ ACL_PERMISSION_WRITE | \
+ ACL_PERMISSION_DELETE | \
+ ACL_PERMISSION_NOTIFY)
+
+/**
+ * Function to reset the SVR DB(security provisioning data)
+ *
+ * @param authTypes authentication type for ownership transfer
+ * @ret 0 is success, otherwise fail.
+ */
+extern int sm_init_things_security(int auth_type, const char *db_path);
+
+/**
+ * Function to init SVR DB(security provisioning data)
+ * If SVR DB not exist, SVR DB will be generated.
+ *
+ * @ret 0 is success, otherwise fail.
+ */
+extern int sm_init_svrdb();
+
+/**
+ * Function to reset SVR DB
+ *
+ * @ret 0 is success, otherwise fail.
+ */
+extern int sm_reset_svrdb();
+
+/**
+ * Function to generate MAC based UUID.
+ * NOTE : device uuid will be changed to the MD5 hash value of MAC address
+ *
+ * @param is_forced if true, Device UUID will be created forcibly.
+ * @ret 0 is success, otherwise fail.
+ */
+extern int sm_generate_mac_based_device_id(bool is_forced);
+
+/**
+ * Function to save the Cloud ACL
+ *
+ * @param cloud_uuid UUID for cloud
+ * @ret 0 is success, otherwise fail.
+ */
+extern int sm_save_cloud_acl(const char *cloud_uuid);
+
+/**
+ * Function to save the ACL
+ *
+ * @param uuid UUID of controller or wildcard("*")
+ * @param resourceUri resource URI to be added into access control list.
+ * @param resourceType Type name of resource
+ * @param interfaceName Interface name of resource
+ * @param permission Access permission value
+ * Access policy in least significant bits (from Spec):
+ * b00000001 (1): CREATE
+ * b00000010 (2): READ
+ * b00000100 (4): WRITE
+ * b00001000 (8): DELETE
+ * b00010000 (16): NOTIFY
+ * b00011111 (31) Full permission
+ * @ret 0 is success, otherwise fail.
+ */
+extern int sm_save_acl(const char *uuid, const char *resource_uri, const char *resource_type, const char *interface_name, uint16_t permission);
+
+/**
+ * API to register OTM event handler
+ *
+ * @param otmEventHandler implementation of OTM event handler (@ref OicSecOtmEventHandler_t)
+ */
+extern void sm_set_otm_event_handler(OicSecOtmEventHandler_t otm_event_handler);
+
+/**
+ * Function to set a MOT status
+ *
+ * @param enable whether the MOT is enabled. (true=enable, false=disable)
+ *
+ * @ret 0 is success, otherwise fail.
+ */
+extern int sm_set_mot_status(bool enable);
+
+#endif //__SECURED__
+
+#endif //_THINGS_SECURITY_MANAGER_H_
--- /dev/null
+/* ****************************************************************
+ *
+ * Copyright 2017 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.
+ *
+ ******************************************************************/
+
+#ifndef _THINGS_SERVER_BUILDER_H_
+#define _THINGS_SERVER_BUILDER_H_
+
+#include "things_resource.h"
+#include "things_common.h"
+#include "things_list.h"
+
+#define MAX_DEVICE_NUM 50
+#define MAX_RESOURCE_NUM (50 * MAX_DEVICE_NUM)
+
+typedef struct things_server_builder_s {
+ size_t res_num;
+ request_handler_cb handler;
+ struct things_resource_s *gres_arr[MAX_RESOURCE_NUM]; // this need to be linked list based stack..
+
+ void (*init_module)(struct things_server_builder_s *, request_handler_cb);
+ void (*deinit_module)(struct things_server_builder_s *);
+ void (*set_device_info)(struct things_server_builder_s *, char *, char *);
+ void (*set_platform_info)(struct things_server_builder_s *, char *, char *, char *, char *, char *, char *);
+ struct things_resource_s *(*create_resource)(struct things_server_builder_s *, char *, char *, char *, int, int, int);
+ struct things_resource_s *(*create_collection_resource)(struct things_server_builder_s *, char *, char *, char *);
+ struct things_resource_s *(*get_resource)(struct things_server_builder_s *, const char *);
+ void (*delete_resource)(struct things_server_builder_s *);
+
+ int (*add_interface_type)(struct things_resource_s *, char *);
+ int (*add_resource_type)(struct things_resource_s *, char *);
+
+ void (*bind)(struct things_resource_s *, struct things_resource_s *);
+ void (*bind_all)(struct things_resource_s *, struct things_resource_s *[], size_t);
+
+ int (*broadcast_presence)(struct things_server_builder_s *, int);
+} things_server_builder_s;
+
+extern struct things_server_builder_s *get_builder_instance();
+extern void release_builder_instance(struct things_server_builder_s *builder);
+
+#endif // _THINGS_SERVER_BUILDER_H_
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 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.
+ *
+ ****************************************************************************/
+
+#define _POSIX_C_SOURCE 200809L
+
+#include <string.h>
+#include <stdlib.h>
+#include <json/cJSON.h>
+
+#include "octypes.h"
+#include "ocpayload.h"
+#include "easysetup.h"
+#include "ocstackconfig.h"
+#include "ocrandom.h"
+#include "things_def.h"
+#include "things_logger.h"
+#include "things_malloc.h"
+#include "things_string_util.h"
+#include "things_hashmap.h"
+#include "things_resource.h"
+#include "things_data_manager.h"
+#include "things_server_builder.h"
+#include "cloud_manager.h"
+#include "cloud_connector.h"
+#include "things_types.h"
+
+#define TAG "[things_datamgr]"
+
+#define KEY_CLOUD "cloud"
+#define KEY_WIFI "wifi"
+
+#define KEY_WIFI_SSID "ssid"
+#define KEY_WIFI_PASSPHARASE "passphrase"
+#define KEY_WIFI_AUTH_TYPE "auth_type"
+#define KEY_WIFI_CRYPTO_TYPE "crypto_type"
+
+#define KEY_CLOUD_DOMAIN "domain"
+#define KEY_CLOUD_ADDRESS "address"
+#define KEY_CLOUD_PORT "port"
+#define KEY_FILE_PATH "fileRWpath"
+#define KEY_ATTR_PATH2 "path"
+
+#define KEY_DEVICE "device"
+#define KEY_DEVICE_SPECIFICATION "specification"
+#define KEY_DEVICE_SPECIFICATION_DEVICE "device"
+#define KEY_DEVICE_SPECIFICATION_DEVICE_DEVICETYPE "deviceType"
+#define KEY_DEVICE_SPECIFICATION_DEVICE_DEVICENAME "deviceName"
+#define KEY_DEVICE_SPECIFICATION_DEVICE_SPECVERSION "specVersion"
+#define KEY_DEVICE_SPECIFICATION_DEVICE_DATAMODELVERSION "dataModelVersion"
+#define KEY_DEVICE_SPECIFICATION_PLATFORM "platform"
+#define KEY_DEVICE_SPECIFICATION_PLATFORM_MANUFACTURERNAME "manufacturerName"
+#define KEY_DEVICE_SPECIFICATION_PLATFORM_MANUFACTURERURI "manufacturerUrl"
+#define KEY_DEVICE_SPECIFICATION_PLATFORM_MANUFACTURINGDATE "manufacturingDate"
+#define KEY_DEVICE_SPECIFICATION_PLATFORM_MODELNUMBER "modelNumber"
+#define KEY_DEVICE_SPECIFICATION_PLATFORM_PLATFORMVERSION "platformVersion"
+#define KEY_DEVICE_SPECIFICATION_PLATFORM_OSVERSION "osVersion"
+#define KEY_DEVICE_SPECIFICATION_PLATFORM_HARDWAREVERSION "hardwareVersion"
+#define KEY_DEVICE_SPECIFICATION_PLATFORM_FIRMWAREVERSION "v"
+#define KEY_DEVICE_SPECIFICATION_PLATFORM_VENDORID "vendorId"
+
+#define KEY_RESOURCES "resources"
+#define KEY_RESOURCES_TYPE "resourceTypes"
+
+#define KEY_RESOURCES_COL "collection"
+#define KEY_RESOURCES_SIG "single"
+
+#define KEY_CONFIGURATION "configuration"
+#define KEY_CONFIGURATION_EASYSETUP "easySetup"
+#define KEY_CONFIGURATION_EASYSETUP_CONNECTIVITY "connectivity"
+#define KEY_CONFIGURATION_EASYSETUP_CONNECTIVITY_TYPE "type"
+
+#define KEY_CONFIGURATION_EASYSETUP_CONNECTIVITY_SOFTAP "softAP"
+#define KEY_CONFIGURATION_EASYSETUP_CONNECTIVITY_SOFTAP_MANUFACTUREID "manufacturerId"
+#define KEY_CONFIGURATION_EASYSETUP_CONNECTIVITY_SOFTAP_SETUPID "setupId"
+#define KEY_CONFIGURATION_EASYSETUP_CONNECTIVITY_SOFTAP_ARTIK "artik"
+#define KEY_CONFIGURATION_EASYSETUP_OWNERSHIP "ownershipTransferMethod"
+
+#define KEY_CONFIGURATION_WIFI "wifi"
+#define KEY_CONFIGURATION_WIFI_INTERFACES "interfaces"
+#define KEY_CONFIGURATION_WIFI_FREQUENCY "frequency"
+
+#define KEY_CONFIGURATION_FILEPATH "filePath"
+#define KEY_CONFIGURATION_FILEPATH_SVRDB "svrdb"
+#define KEY_CONFIGURATION_FILEPATH_PROVISIONING "provisioning"
+#define KEY_CONFIGURATION_FILEPATH_CERTIFICATE "certificate"
+#define KEY_CONFIGURATION_FILEPATH_PRIVATEKEY "privateKey"
+
+#define KEY_DEVICE_RESOURCE_URI "uri"
+#define KEY_DEVICE_RESOURCE_TYPES "types"
+#define KEY_DEVICE_RESOURCE_INTERFACES "interfaces"
+#define KEY_DEVICE_RESOURCE_POLICY "policy"
+#define KEY_DEVICE_RESOURCE_COLLECTION_LINKS "links"
+
+#define KEY_DEVICE_RESOURCETYPE_TYPE "type"
+#define KEY_DEVICE_RESOURCETYPE_PROPERTIES "properties"
+#define KEY_DEVICE_RESOURCETYPE_PROPERTIES_KEY "key"
+#define KEY_DEVICE_RESOURCETYPE_PROPERTIES_TYPE "type"
+#define KEY_DEVICE_RESOURCETYPE_PROPERTIES_MANDATORY "mandatory"
+#define KEY_DEVICE_RESOURCETYPE_PROPERTIES_RW "rw"
+
+#define KEY_ATTR_DEVICE_DEVICEID "devid"
+
+#define CHECK_BIT(var, pos) (((var)>>(pos)) & 1)
+
+#define CHECK_READABLE(var) CHECK_BIT(var, 0)
+#define CHECK_WRITABLE(var) CHECK_BIT(var, 1)
+
+#define CHECK_DISCOVERABLE(var) CHECK_BIT(var, 0)
+#define CHECK_OBSERVABLE(var) CHECK_BIT(var, 1)
+#define CHECK_SECURE(var) CHECK_BIT(var, 2)
+
+#define MAX_FILE_ACCESS_CNT (10)
+#define MAX_KEY_LENGTH (50)
+
+#define MAX_URI_LENGTH (128)
+#define MAX_IT_CNT (5)
+#define MAX_RT_CNT (10)
+
+#define MAX_ATTRIBUTE_LENGTH (64)
+
+#define MAX_CLOUD_ADDRESS (256) // Need to match with the Cloud Spec.
+#define MAX_CLOUD_SESSIONKEY (128) // Need to match with the Cloud Spec.
+
+#define MAX_FILE_PATH_LENGTH (250)
+
+#define MAX_SUBDEVICE_EA (100)
+
+static bool is_support_user_def_dev_list = true; // It's allow to apply user-defined device-ID only when start Stack.
+static char *user_def_dev_list[MAX_SUBDEVICE_EA + 1] = { 0, };
+
+static volatile int resource_type_cnt = 0;
+
+static char g_things_cloud_file_path[MAX_FILE_PATH_LENGTH] = { 0 };
+static char g_things_info_file_path[MAX_FILE_PATH_LENGTH] = { 0 };
+static char g_svrdb_file_path[MAX_FILE_PATH_LENGTH] = { 0 };
+static char g_certificate_file_path[MAX_FILE_PATH_LENGTH] = { 0 };
+static char g_private_key_file_path[MAX_FILE_PATH_LENGTH] = { 0 };
+
+static char g_cloud_address[MAX_CLOUD_ADDRESS] = { 0 };
+
+static char *g_manufacturer_name;
+static char *g_setup_id;
+static bool is_artik;
+
+static int g_wifi_interface;
+static wifi_freq_e g_wifi_freq;
+
+static int g_ownership_transfer_method = 0;
+
+static struct hashmap_s *g_resource_type_hmap = NULL; // map for resource types
+static struct hashmap_s *g_device_hmap = NULL;
+
+static bool is_there_cloud_data = false;
+static const char *origin_cloud_json_str = "{\n\
+ \"cloud\": {\n\
+ \"address\": \"52.40.216.160:5683\"\n\
+ },\n\
+ \"wifi\": {\n\
+ \"ssid\": \"unknown\"\n\
+ }\n\
+}";
+
+static wifi_manager_softap_config_s ap_config;
+static easysetup_connectivity_type_e es_conn_type = es_conn_type_none;
+static wifi_manager_ap_config_s g_homeap_info;
+
+typedef int8_t INT8;
+
+#define STD_CI_CLOUD_ADDRESS "52.40.216.160:5683"
+#define MAX_CI_CLOUD_ADDRESS 256
+static es_cloud_signup_s *gpst_cloud_data = NULL;
+static char g_ci_cloud_address[MAX_CI_CLOUD_ADDRESS] = { 0 };
+
+struct things_attribute_info_s const gstAttr_x_com_samsung_provisioninginfo[] = {
+ {
+ .key = "x.com.samsung.provisioning.targets",
+ .type = 9,
+ .mandatory = false,
+ .rw = 1
+ },
+ {
+ .key = "x.com.samsung.provisioning.owned",
+ .type = 0,
+ .mandatory = false,
+ .rw = 1
+ },
+ {
+ .key = "x.com.samsung.provisioning.easysetupdi",
+ .type = 3,
+ .mandatory = false,
+ .rw = 1
+ },
+ {
+ .key = "x.com.samsung.provisioning.reset",
+ .type = 0,
+ .mandatory = false,
+ .rw = 3
+ },
+ {
+ .key = "x.com.samsung.provisioning.stopAP",
+ .type = 0,
+ .mandatory = false,
+ .rw = 3
+ }
+};
+
+const struct things_attribute_info_s const gstAttr_x_com_samsung_accesspointlist[] = {
+ {
+ .key = "x.com.samsung.accesspoint.items",
+ .type = 9,
+ .mandatory = true,
+ .rw = 1
+ }
+};
+
+static const struct st_resource_type_s const gst_resource_types[] = {
+ {
+ .rt = "x.com.samsung.provisioninginfo",
+ .prop_cnt = 5,
+ .prop[0] = &gstAttr_x_com_samsung_provisioninginfo[0],
+ .prop[1] = &gstAttr_x_com_samsung_provisioninginfo[1],
+ .prop[2] = &gstAttr_x_com_samsung_provisioninginfo[2],
+ .prop[3] = &gstAttr_x_com_samsung_provisioninginfo[3],
+ .prop[4] = &gstAttr_x_com_samsung_provisioninginfo[4]
+ },
+ {
+ .rt = "x.com.samsung.accesspointlist",
+ .prop_cnt = 1,
+ .prop[0] = &gstAttr_x_com_samsung_accesspointlist[0]
+ }
+};
+
+static const struct things_resource_info_s const gstResources[] = {
+ {
+ .uri = "/sec/provisioninginfo",
+ .interface_types = {"oic.if.a"},
+ .resource_types = {"x.com.samsung.provisioninginfo"},
+ .if_cnt = 1,
+ .rt_cnt = 1,
+ .policy = 3
+ },
+ {
+ .uri = "/sec/accesspointlist",
+ .interface_types = {"oic.if.s"},
+ .resource_types = {"x.com.samsung.accesspointlist"},
+ .if_cnt = 1,
+ .rt_cnt = 1,
+ .policy = 3
+ }
+};
+
+bool update_and_save_device_info(st_device_s **dev_list, int dev_cnt)
+{
+ assert(1);
+ return false;
+}
+
+/**
+ * @fn get_cloud_server_address
+ * @brief Function to get cloud server address
+ * @param pch_current_server
+ * @return
+ */
+char *get_cloud_server_address(char *pch_current_server)
+{
+ if (gpst_cloud_data != NULL) {
+ memset(g_ci_cloud_address, 0, MAX_CI_CLOUD_ADDRESS);
+ memcpy(g_ci_cloud_address, gpst_cloud_data->address, strlen(gpst_cloud_data->address) + 1);
+ } else {
+ memcpy(g_ci_cloud_address, STD_CI_CLOUD_ADDRESS, strlen(STD_CI_CLOUD_ADDRESS));
+ }
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "CLOUD CI Address : %s", g_ci_cloud_address);
+
+ return g_ci_cloud_address;
+}
+
+static struct things_attribute_info_s *create_property()
+{
+ struct things_attribute_info_s *property = things_malloc(sizeof(things_attribute_info_s));
+
+ memset(property->key, 0, (size_t) MAX_KEY_LENGTH);
+ property->type = 0;
+ property->mandatory = false;
+ property->rw = 0;
+
+ return property;
+}
+
+static struct st_resource_type_s *create_resource_type()
+{
+ struct st_resource_type_s *type = things_malloc(sizeof(st_resource_type_s));
+
+ memset(type->rt, 0, (size_t) MAX_ATTRIBUTE_LENGTH);
+ memset(type->prop, 0, (size_t) MAX_PROPERTY_CNT);
+ type->prop_cnt = 0;
+
+ return type;
+}
+
+static struct things_resource_info_s *create_resource()
+{
+ struct things_resource_info_s *resource = things_malloc(sizeof(things_resource_info_s));
+
+ memset(resource->uri, 0, sizeof(resource->uri));
+ memset(resource->interface_types, 0, sizeof(resource->interface_types));
+ memset(resource->resource_types, 0, sizeof(resource->resource_types));
+ resource->policy = 0;
+ resource->if_cnt = 0;
+ resource->rt_cnt = 0;
+
+ return resource;
+}
+
+static st_device_s *create_device()
+{
+ st_device_s *device = things_malloc(sizeof(st_device_s));
+
+ memset(device->type, 0, (size_t) MAX_DEVICE_TYPE_LENGTH);
+ memset(device->name, 0, (size_t) MAX_DEVICE_NAME_LENGTH);
+ memset(device->model_num, 0, (size_t) MAX_DEVICE_MODEL_ID_LENGTH);
+ memset(device->ver_p, 0, (size_t) MAX_DEVICE_VER_P);
+ memset(device->ver_os, 0, (size_t) MAX_DEVICE_VER_OS);
+ memset(device->ver_hw, 0, (size_t) MAX_DEVICE_VER_HW);
+ memset(device->ver_fw, 0, (size_t) MAX_DEVICE_VER_FW);
+ memset(device->device_id, 0, (size_t) MAX_DEVICE_ID_LENGTH);
+ memset(device->vender_id, 0, (size_t) MAX_DEVICE_VENDER_ID);
+ memset(device->description, 0, (size_t) MAX_DEVICE_DESCRIPTION_LENGTH);
+
+ device->no = -1;
+ device->capa_cnt = 0;
+ device->col_cnt = 0;
+ device->sig_cnt = 0;
+ device->is_physical = 0;
+
+ for (int index = 0; index < MAX_DEVICE_CAPABILTY_CNT; index++) {
+ device->pchild_resources[index] = NULL;
+ }
+
+ return device;
+}
+
+static size_t get_json_file_size(const char *filename)
+{
+ size_t size = 0;
+ FILE *fp = fopen(filename, "r");
+
+ if (fp) {
+ if (0 == fseek(fp, 0L, SEEK_END)) {
+ size = ftell(fp);
+ rewind(fp);
+ }
+ fclose(fp);
+ }
+ return size;
+}
+
+static char *get_json_string_from_file(const char *filename)
+{
+ FILE *fp = NULL;
+ char *json_str = NULL;
+ size_t size = get_json_file_size(filename);
+ size_t readed = 0;
+ int fp_acess_cnt = 0;
+
+ if (size <= 0) {
+ THINGS_LOG_D(THINGS_ERROR, TAG, "Failed converting to JSON");
+ return NULL;
+ } else {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "File size: %d ", size);
+ }
+
+ json_str = (char *)things_malloc(size + 1);
+
+ // 1. File Read
+ fp = fopen(filename, "r");
+ if (NULL == fp) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Failed to open %s", filename);
+ things_free(json_str);
+ return NULL;
+ }
+ // 2. Json String read from the given file.
+ size_t bytes_read = 0;
+ while (readed < size && fp_acess_cnt < MAX_FILE_ACCESS_CNT) {
+ bytes_read = fread(&(json_str[readed]), 1, size - readed, fp);
+ readed += bytes_read;
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Read Size: %d, total Size =%d", readed, size);
+ fp_acess_cnt++;
+ }
+
+ if (fp_acess_cnt >= MAX_FILE_ACCESS_CNT) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Access-Times is Over for File Read. (Readed Size: %d, total Size =%d)", readed, size);
+ things_free(json_str);
+ fclose(fp);
+ return NULL;
+ }
+
+ json_str[readed] = '\0';
+
+ fclose(fp);
+ fp = NULL;
+
+ return json_str;
+}
+
+static int set_json_string_into_file(const char *filename, const char *json_str)
+{
+ FILE *fp = NULL;
+ // 1. File Read
+ fp = fopen(filename, "w");
+ if (NULL == fp) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Failed to open \"%s\" with Write permission.", filename);
+ return 0;
+ }
+ // 2. Json String read from the given file.
+ fwrite(json_str, 1, strlen(json_str), fp);
+
+ fclose(fp);
+ fp = NULL;
+ return 1;
+}
+
+static int init_things_info_file(cJSON *cjson, char *origin_json_str)
+{
+ int res = 1;
+
+ if (g_things_info_file_path[0] == 0) {
+ int length = 0;
+ cJSON *file_rw_path = cJSON_GetObjectItem(cjson, KEY_FILE_PATH);
+ if (NULL == file_rw_path || (length = strlen(file_rw_path->valuestring)) <= 0) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "\"%s\" key is not exist in info file. or value is empty.", KEY_FILE_PATH);
+ return 0;
+ }
+
+ memset(g_things_info_file_path, 0, MAX_FILE_PATH_LENGTH);
+ memcpy(g_things_info_file_path, file_rw_path->valuestring, length + 1);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Info file path : %s", g_things_info_file_path);
+ }
+
+ int is_valid = 1;
+
+ char *json_str = get_json_string_from_file(g_things_info_file_path);
+ if (json_str != NULL) {
+ cJSON *root = cJSON_Parse((const char *)json_str);
+ if (root == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "%s fail to parsed.", g_things_info_file_path);
+ is_valid = 0;
+ }
+ } else {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "%s is empty.", g_things_info_file_path);
+ is_valid = 0;
+ }
+
+ if (is_valid == 0) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Try to reset the info file.");
+ if (set_json_string_into_file(g_things_info_file_path, origin_json_str) == 0) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "original info file copy failed.");
+ res = 0;
+ }
+ }
+
+ return res;
+}
+
+static int get_json_int(cJSON *json, int64_t *variable)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Enter");
+
+ int res = 1;
+
+ if (json == NULL || variable == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "json = %d, variable = %d", json, variable);
+ return 0;
+ }
+
+ if (json->type != cJSON_Number) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "json-value Type is Not String value.");
+ return 0;
+ }
+
+ *variable = json->valueint;
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Exit");
+
+ return res;
+}
+
+static int get_json_string(cJSON *json, char **variable)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Enter");
+
+ int res = 1;
+ int length = 0;
+
+ if (json == NULL || variable == NULL || *variable != NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "There is NULL value.(json = %d, variable = %d)", json, variable);
+ if (variable != NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "variable value is not NULL.(*variable = %d)", *variable);
+ }
+ return 0;
+ }
+
+ if (json->type != json->type) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "json-value Type is Not String value.");
+ return 0;
+ }
+
+ if ((length = strlen(json->valuestring)) == 0) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "length is NULL");
+ return 0;
+ }
+
+ *variable = (char *)things_malloc(sizeof(char) * (length + 1));
+ if (*variable == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "memory allocation is failed.");
+ return 0;
+ }
+
+ memset(*variable, 0, length + 1);
+ memcpy(*variable, json->valuestring, length + 1);
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Exit");
+
+ return res;
+}
+
+static int load_cloud_signup_data(cJSON *json, es_cloud_signup_s **cl_data)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Enter");
+
+ int res = 1;
+
+ if (json == NULL || cl_data == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "json = %d, cl_data = %d", json, cl_data);
+ return -1;
+ }
+
+ cJSON *domain = cJSON_GetObjectItem(json, KEY_CLOUD_DOMAIN);
+ cJSON *address = cJSON_GetObjectItem(json, KEY_CLOUD_ADDRESS);
+ cJSON *port = cJSON_GetObjectItem(json, KEY_CLOUD_PORT);
+ cJSON *accesstoken = cJSON_GetObjectItem(json, KEY_TOKEN_ACCESS);
+ cJSON *refresh_accesstoken = cJSON_GetObjectItem(json, KEY_TOKEN_ACCESS_REFRESH);
+ cJSON *token_type = cJSON_GetObjectItem(json, KEY_TOKEN_TYPE);
+ cJSON *expire_time = cJSON_GetObjectItem(json, KEY_EXPIRE_TIME);
+ cJSON *user_id = cJSON_GetObjectItem(json, KEY_ID_USER);
+ cJSON *redirect_uri = cJSON_GetObjectItem(json, KEY_SERVER_REDIRECT_URI);
+ cJSON *certificate = cJSON_GetObjectItem(json, KEY_CERTIFICATE_FILE);
+ cJSON *server_id = cJSON_GetObjectItem(json, KEY_SERVER_ID);
+
+ if (address == NULL || accesstoken == NULL || refresh_accesstoken == NULL || user_id == NULL || expire_time == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "address = %d, accesstoken = %d, refresh_accesstoken = %d, user_id = %d, expire_time = %d", address, accesstoken, refresh_accesstoken, user_id, expire_time);
+ return -2;
+ }
+
+ if (es_cloud_signup_init(cl_data) == false) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "ESCloud data initialization is failed.");
+ return -1;
+ }
+
+ if (get_json_string(address, &((*cl_data)->address)) == 0) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Load JSON String address is failed");
+ res = -1;
+ }
+
+ if (get_json_string(accesstoken, &((*cl_data)->access_token)) == 0) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Load JSON String accesstoken is failed");
+ res = -1;
+ }
+
+ if (get_json_string(refresh_accesstoken, &((*cl_data)->refresh_token)) == 0) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Load JSON String refresh_accesstoken is failed");
+ res = -1;
+ }
+
+ if (get_json_string(user_id, &((*cl_data)->uid)) == 0) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Load JSON String user_id is failed");
+ res = -1;
+ }
+
+ if (get_json_int(expire_time, &((*cl_data)->expire_time)) == 0) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Load JSON String expire_time is failed");
+ res = -1;
+ }
+
+ get_json_string(token_type, &((*cl_data)->token_type));
+ get_json_string(redirect_uri, &((*cl_data)->redirect_uri));
+ get_json_string(certificate, &((*cl_data)->certificate));
+ get_json_string(server_id, &((*cl_data)->sid));
+ get_json_string(domain, &((*cl_data)->domain));
+ get_json_string(port, &((*cl_data)->port));
+
+ if (res == -1) {
+ es_cloud_signup_clear(*cl_data);
+ *cl_data = NULL;
+ } else {
+ memcpy(g_cloud_address, (*cl_data)->address, strlen((*cl_data)->address) + 1);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "CLOUD CI Address : %s", g_cloud_address);
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Exit");
+
+ return res;
+}
+
+static int if_need_init_things_cloud_file(const char *filename)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+
+ int res = 0;
+
+ FILE *fp = fopen(filename, "r");
+ if (fp) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Already Exist : provisioning file.");
+ fclose(fp);
+ } else {
+ if (set_json_string_into_file(filename, origin_cloud_json_str) == 0) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Creating privisioning file is failed.");
+ res = -1;
+ } else {
+ THINGS_LOG_D(THINGS_INFO, TAG, "Creating privisioning file is Success.");
+ res = 1;
+ }
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_EXIT);
+ return res;
+}
+
+easysetup_connectivity_type_e dm_get_easysetup_connectivity_type(void)
+{
+ return es_conn_type;
+}
+
+wifi_manager_softap_config_s *dm_get_softap_wifi_config(void)
+{
+ // TO DO : need to make softap SSID by security
+ char *temp_ssid = "samsung_E1";
+ char *temp_passphrase = "1111122222";
+ int temp_channel = 1;
+
+ strncpy(ap_config.ssid, temp_ssid, strlen(temp_ssid) + 1);
+ strncpy(ap_config.passphrase, temp_passphrase, strlen(temp_passphrase) + 1);
+ ap_config.channel = temp_channel;
+
+ return &ap_config;
+}
+
+wifi_manager_ap_config_s *dm_get_homeap_wifi_config(void)
+{
+ return &g_homeap_info;
+}
+
+int parse_things_cloud_json(const char *filename)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+
+ int ret = 0;
+ char *json_str = NULL;
+
+ if (if_need_init_things_cloud_file(filename) == -1) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "RW CloudFile-loading is failed. please check your \"%s\"", filename);
+ return 0;
+ }
+
+RETRY_JSON:
+ json_str = get_json_string_from_file(filename);
+
+ if (json_str == NULL) {
+ THINGS_LOG_V(THINGS_INFO, TAG, "cloud file initialization.");
+ if (set_json_string_into_file(filename, origin_cloud_json_str) == 0) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "[Error] Creating cloud file is failed.");
+ return 0;
+ }
+ goto RETRY_JSON;
+ }
+
+ if (strlen(json_str) > 0) {
+ // 3. Parse the Json string
+ cJSON *root = cJSON_Parse((const char *)json_str);
+
+ if (root == NULL) {
+ THINGS_LOG_V(THINGS_INFO, TAG, "cloud file context has a error about json-format.");
+ things_free(json_str);
+ json_str = NULL;
+
+ THINGS_LOG_V(THINGS_INFO, TAG, "cloud file initialization.");
+ if (set_json_string_into_file(filename, origin_cloud_json_str) == 0) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "[Error] Creating colud file is failed.");
+ return 0;
+ }
+ goto RETRY_JSON;
+ }
+
+ cJSON *cloud = cJSON_GetObjectItem(root, KEY_CLOUD);
+ cJSON *wifi = cJSON_GetObjectItem(root, KEY_WIFI);
+
+ if (NULL != wifi && NULL != cloud) {
+ /***** Cloud *****/
+ cJSON *address = cJSON_GetObjectItem(cloud, KEY_CLOUD_ADDRESS);
+ if (NULL != address) {
+ memset(g_cloud_address, 0, (size_t) MAX_CLOUD_ADDRESS);
+ memcpy(g_cloud_address, address->valuestring, strlen(address->valuestring) + 1);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[CLOUD] CI Address : %s", g_cloud_address);
+ ret = 1;
+ }
+
+ cJSON *accesstoken = cJSON_GetObjectItem(cloud, KEY_TOKEN_ACCESS);
+ cJSON *refresh_accesstoken = cJSON_GetObjectItem(cloud, KEY_TOKEN_ACCESS_REFRESH);
+ cJSON *user_id = cJSON_GetObjectItem(cloud, KEY_ID_USER);
+ cJSON *expire_time = cJSON_GetObjectItem(cloud, KEY_EXPIRE_TIME);
+
+ /***** Wifi *****/
+ cJSON *ssid = cJSON_GetObjectItem(wifi, KEY_WIFI_SSID);
+ if (NULL != ssid) {
+ memcpy(g_homeap_info.ssid, ssid->valuestring, strlen(ssid->valuestring) + 1);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[WIFI] SSID Address : %s", g_homeap_info.ssid);
+ ret = 1;
+ g_homeap_info.ssid_length = strlen(g_homeap_info.ssid);
+ }
+
+ cJSON *passphrase = cJSON_GetObjectItem(wifi, KEY_WIFI_PASSPHARASE);
+ if (NULL != passphrase) {
+ memcpy(g_homeap_info.passphrase, passphrase->valuestring, strlen(passphrase->valuestring) + 1);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[WIFI] PASSPHRASE Address : %s", g_homeap_info.passphrase);
+ ret = 1;
+ g_homeap_info.passphrase_length = strlen(g_homeap_info.passphrase);
+ }
+
+ cJSON *auth_type = cJSON_GetObjectItem(wifi, KEY_WIFI_AUTH_TYPE);
+
+ if (NULL != auth_type) {
+ g_homeap_info.ap_auth_type = auth_type->valueint;
+ }
+
+ cJSON *crypto_type = cJSON_GetObjectItem(wifi, KEY_WIFI_CRYPTO_TYPE);
+ if (NULL != crypto_type) {
+ g_homeap_info.ap_crypto_type = crypto_type->valueint;
+ }
+
+ if (address == NULL || accesstoken == NULL || refresh_accesstoken == NULL || user_id == NULL || expire_time == NULL || ssid == NULL || passphrase == NULL || auth_type == NULL || crypto_type == NULL) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[ProvisionInfo] address = %d, accesstoken = %d, refresh_accesstoken = %d, user_id = %d, expire_time = %d", address, accesstoken, refresh_accesstoken, user_id, expire_time);
+ is_there_cloud_data = false;
+ } else {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[ProvisionInfo] There is mandatory elements in cloud file.");
+ is_there_cloud_data = true;
+ }
+ }
+
+ if (NULL != root) {
+ cJSON_Delete(root);
+ }
+ } else {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Can not Read \"%s\" file.", filename);
+ }
+
+ if (json_str != NULL) {
+ things_free(json_str);
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_EXIT);
+ return ret;
+}
+
+static int parse_things_info_json(const char *filename)
+{
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+
+ int ret = 1;
+ char *json_str = get_json_string_from_file(filename);
+
+ if (json_str != NULL && strlen(json_str) > 0) {
+ // 3. Parse the Json string
+ cJSON *root = cJSON_Parse((const char *)json_str);
+ assert(root != NULL);
+
+ st_device_s *node = NULL;
+
+ // Device Items
+ cJSON *device = cJSON_GetObjectItem(root, KEY_DEVICE);
+ int device_cnt = cJSON_GetArraySize(device);
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "device_cnt = %d", device_cnt);
+ if (g_device_hmap == NULL) {
+ g_device_hmap = hashmap_create(device_cnt);
+ }
+
+ if (g_device_hmap == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "g_device_hmap is NULL");
+ cJSON_Delete(root);
+
+ if (json_str != NULL) {
+ things_free(json_str);
+ }
+ return 0;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "device_cnt of hashmap = %d", hashmap_count(g_device_hmap));
+
+ for (int device_num = 0; device_num < device_cnt; device_num++) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[DEVICE] ============================================");
+
+ node = create_device();
+ node->no = device_num;
+ node->is_physical = 1;
+
+ cJSON *device_item = cJSON_GetArrayItem(device, device_num);
+ cJSON *specification = cJSON_GetObjectItem(device_item, KEY_DEVICE_SPECIFICATION);
+ if (NULL != specification) {
+ cJSON *spec_device = cJSON_GetObjectItem(specification, KEY_DEVICE_SPECIFICATION_DEVICE);
+ if (NULL != spec_device) {
+ cJSON *device_type = cJSON_GetObjectItem(spec_device, KEY_DEVICE_SPECIFICATION_DEVICE_DEVICETYPE);
+ cJSON *device_name = cJSON_GetObjectItem(spec_device, KEY_DEVICE_SPECIFICATION_DEVICE_DEVICENAME);
+ cJSON *spec_version = cJSON_GetObjectItem(spec_device, KEY_DEVICE_SPECIFICATION_DEVICE_SPECVERSION);
+ cJSON *data_model_version = cJSON_GetObjectItem(spec_device, KEY_DEVICE_SPECIFICATION_DEVICE_DATAMODELVERSION);
+
+ if (NULL != device_type) {
+ memcpy(node->type, device_type->valuestring, strlen(device_type->valuestring) + 1);
+ }
+
+ if (NULL != device_name) {
+ memcpy(node->name, device_name->valuestring, strlen(device_name->valuestring) + 1);
+ }
+ }
+
+ cJSON *spec_platform = cJSON_GetObjectItem(specification, KEY_DEVICE_SPECIFICATION_PLATFORM);
+ if (NULL != spec_platform) {
+ cJSON *manufacturer_name = cJSON_GetObjectItem(spec_platform, KEY_DEVICE_SPECIFICATION_PLATFORM_MANUFACTURERNAME);
+ cJSON *manufacturer_uri = cJSON_GetObjectItem(spec_platform, KEY_DEVICE_SPECIFICATION_PLATFORM_MANUFACTURERURI);
+ cJSON *manufacturing_date = cJSON_GetObjectItem(spec_platform, KEY_DEVICE_SPECIFICATION_PLATFORM_MANUFACTURINGDATE);
+ cJSON *model_number = cJSON_GetObjectItem(spec_platform, KEY_DEVICE_SPECIFICATION_PLATFORM_MODELNUMBER);
+ cJSON *platform_version = cJSON_GetObjectItem(spec_platform, KEY_DEVICE_SPECIFICATION_PLATFORM_PLATFORMVERSION);
+ cJSON *os_version = cJSON_GetObjectItem(spec_platform, KEY_DEVICE_SPECIFICATION_PLATFORM_OSVERSION);
+ cJSON *hardware_version = cJSON_GetObjectItem(spec_platform, KEY_DEVICE_SPECIFICATION_PLATFORM_HARDWAREVERSION);
+ cJSON *firmware_version = cJSON_GetObjectItem(spec_platform, KEY_DEVICE_SPECIFICATION_PLATFORM_FIRMWAREVERSION);
+ cJSON *vendor_id = cJSON_GetObjectItem(spec_platform, KEY_DEVICE_SPECIFICATION_PLATFORM_VENDORID);
+
+ if (NULL != model_number) {
+ memcpy(node->model_num, model_number->valuestring, strlen(model_number->valuestring) + 1);
+ }
+ if (NULL != platform_version) {
+ memcpy(node->ver_p, platform_version->valuestring, strlen(platform_version->valuestring) + 1);
+ }
+ if (NULL != os_version) {
+ memcpy(node->ver_os, os_version->valuestring, strlen(os_version->valuestring) + 1);
+ }
+ if (NULL != hardware_version) {
+ memcpy(node->ver_hw, hardware_version->valuestring, strlen(hardware_version->valuestring) + 1);
+ }
+ if (NULL != firmware_version) {
+ memcpy(node->ver_fw, firmware_version->valuestring, strlen(firmware_version->valuestring) + 1);
+ }
+ if (NULL != vendor_id) {
+ memcpy(node->vender_id, vendor_id->valuestring, strlen(vendor_id->valuestring) + 1);
+ }
+ }
+ }
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[DEVICE] type : %s", (node->type));
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[DEVICE] name : %s", (node->name));
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[DEVICE] model num : %s", (node->model_num));
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[DEVICE] plat. ver : %s", (node->ver_p));
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[DEVICE] os version : %s", (node->ver_os));
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[DEVICE] hw version : %s", (node->ver_hw));
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[DEVICE] fw version : %s", (node->ver_fw));
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[DEVICE] vender id : %s", (node->vender_id));
+
+ cJSON *resources = cJSON_GetObjectItem(device_item, KEY_RESOURCES);
+ if (resources != NULL) {
+ // 1. Read thsoe resource(s) which will be binded into the Collection resource(/device/#)
+ cJSON *collection = cJSON_GetObjectItem(resources, KEY_RESOURCES_COL);
+
+ if (collection) {
+ node->col_cnt = cJSON_GetArraySize(collection);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[DEVICE] Resources for Collection Cnt : %d", node->col_cnt);
+
+ for (int iter = 0; iter < node->col_cnt; iter++) {
+ cJSON *res = cJSON_GetArrayItem(collection, iter);
+ if (res->type != NULL) {
+ cJSON *uri = cJSON_GetObjectItem(res, KEY_DEVICE_RESOURCE_URI);
+ memcpy(node->collection[iter].uri, uri->valuestring, strlen(uri->valuestring) + 1);
+ THINGS_LOG_D(THINGS_INFO, TAG, "[COLLECTION] collection[0].uri : %s", (node->collection[iter].uri));
+
+ cJSON *types = cJSON_GetObjectItem(res, KEY_DEVICE_RESOURCE_TYPES);
+ if (types) {
+ int type_cnt = cJSON_GetArraySize(types);
+ node->collection[iter].rt_cnt = type_cnt;
+ for (int typeiter = 0; typeiter < type_cnt; typeiter++) {
+ cJSON *type = cJSON_GetArrayItem(types, typeiter);
+ node->collection[iter].resource_types[typeiter] = things_malloc(sizeof(char *) *strlen(type->valuestring) + 1);
+ memcpy(node->collection[iter].resource_types[typeiter], type->valuestring, strlen(type->valuestring) + 1);
+ THINGS_LOG_D(THINGS_INFO, TAG, "[COLLECTION] collection[iter].resource_types[typeiter] : %s", (node->collection[iter].resource_types[typeiter]));
+ }
+ } else {
+ return 0;
+ }
+
+ cJSON *interfaces = cJSON_GetObjectItem(res, KEY_DEVICE_RESOURCE_INTERFACES);
+ if (interfaces) {
+ int if_cnt = cJSON_GetArraySize(interfaces);
+ node->collection[iter].if_cnt = if_cnt;
+ for (int ifiter = 0; ifiter < if_cnt; ifiter++) {
+ cJSON *interface = cJSON_GetArrayItem(interfaces, ifiter);
+ node->collection[iter].interface_types[ifiter] = things_malloc(sizeof(char *) *strlen(interface->valuestring) + 1);
+ memcpy(node->collection[iter].interface_types[ifiter], interface->valuestring, strlen(interface->valuestring) + 1);
+ }
+ } else {
+ return 0;
+ }
+
+ cJSON *policy = cJSON_GetObjectItem(res, KEY_DEVICE_RESOURCE_POLICY);
+ node->collection[iter].policy = policy->valueint;
+ THINGS_LOG_D(THINGS_INFO, TAG, "[COLLECTION] collection[iter].policy : %d", (node->collection[iter].policy));
+
+ cJSON *links = cJSON_GetObjectItem(res, KEY_DEVICE_RESOURCE_COLLECTION_LINKS);
+ if (links) {
+ int linkCnt = cJSON_GetArraySize(links);
+ node->collection[iter].link_cnt = linkCnt;
+ THINGS_LOG_D(THINGS_INFO, TAG, "[COLLECTION] collection[iter].link_cnt : %d", (node->collection[iter].link_cnt));
+ for (int linkiter = 0; linkiter < linkCnt; linkiter++) {
+ cJSON *link = cJSON_GetArrayItem(links, linkiter);
+
+ struct things_resource_info_s *link_resource = create_resource();
+
+ cJSON *uri = cJSON_GetObjectItem(link, KEY_DEVICE_RESOURCE_URI);
+ memcpy(link_resource->uri, uri->valuestring, strlen(uri->valuestring) + 1);
+ THINGS_LOG_D(THINGS_INFO, TAG, "[COLLECTION] link_resource->uri : %s", (link_resource->uri));
+
+ cJSON *types = cJSON_GetObjectItem(link, KEY_DEVICE_RESOURCE_TYPES);
+ if (types) {
+ int type_cnt = cJSON_GetArraySize(types);
+ link_resource->rt_cnt = type_cnt;
+ for (int typeiter = 0; typeiter < type_cnt; typeiter++) {
+ cJSON *type = cJSON_GetArrayItem(types, typeiter);
+ link_resource->resource_types[typeiter] = things_malloc(sizeof(char *) *strlen(type->valuestring) + 1);
+ memcpy(link_resource->resource_types[typeiter], type->valuestring, strlen(type->valuestring) + 1);
+ }
+ } else {
+ return 0;
+ }
+ cJSON *interfaces = cJSON_GetObjectItem(link, KEY_DEVICE_RESOURCE_INTERFACES);
+ if (interfaces) {
+ int if_cnt = cJSON_GetArraySize(interfaces);
+ link_resource->if_cnt = if_cnt;
+ for (int ifiter = 0; ifiter < if_cnt; ifiter++) {
+ cJSON *interface = cJSON_GetArrayItem(interfaces, ifiter);
+ link_resource->interface_types[ifiter] = things_malloc(sizeof(char *) *strlen(interface->valuestring) + 1);
+ memcpy(link_resource->interface_types[ifiter], interface->valuestring, strlen(interface->valuestring) + 1);
+ }
+ } else {
+ return 0;
+ }
+ cJSON *policy = cJSON_GetObjectItem(link, KEY_DEVICE_RESOURCE_POLICY);
+ link_resource->policy = policy->valueint;
+ node->collection[iter].links[linkiter] = link_resource;
+ }
+ } else {
+ return 0;
+ }
+ }
+
+ }
+ ret = 1;
+
+ THINGS_LOG_D(THINGS_INFO, TAG, "[COLLECTION] URI. : %s", node->collection[0].uri);
+ THINGS_LOG_D(THINGS_INFO, TAG, "[COLLECTION] interface_type. : %s", node->collection[0].interface_types[0]);
+ THINGS_LOG_D(THINGS_INFO, TAG, "[COLLECTION] resource_types. : %s", node->collection[0].resource_types[0]);
+ THINGS_LOG_D(THINGS_INFO, TAG, "[COLLECTION] if_cnt. : %d", node->collection[0].if_cnt);
+ THINGS_LOG_D(THINGS_INFO, TAG, "[COLLECTION] rt_cnt. : %d", node->collection[0].rt_cnt);
+ THINGS_LOG_D(THINGS_INFO, TAG, "[COLLECTION] link_cnt. : %d", node->collection[0].link_cnt);
+ THINGS_LOG_D(THINGS_INFO, TAG, "[COLLECTION] policy. : %d", node->collection[0].policy);
+ } else {
+ THINGS_LOG_D(THINGS_INFO, TAG, "Children Reosurces Not Exist");
+ //ret = 0;
+ }
+
+ // 2. Read thsoe resource(s) which will not be binded into the Collection resource
+ cJSON *single = cJSON_GetObjectItem(resources, KEY_RESOURCES_SIG);
+
+ if (single) {
+ node->sig_cnt = cJSON_GetArraySize(single);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[DEVICE] Resources for Single Usage Cnt : %d", node->sig_cnt);
+
+ for (int iter = 0; iter < node->sig_cnt; iter++) {
+ cJSON *res = cJSON_GetArrayItem(single, iter);
+ if (res->type != NULL) {
+ cJSON *uri = cJSON_GetObjectItem(res, KEY_DEVICE_RESOURCE_URI);
+ memcpy(node->single[iter].uri, uri->valuestring, strlen(uri->valuestring) + 1);
+
+ cJSON *types = cJSON_GetObjectItem(res, KEY_DEVICE_RESOURCE_TYPES);
+ if (types) {
+ int type_cnt = cJSON_GetArraySize(types);
+ node->single[iter].rt_cnt = type_cnt;
+ for (int typeiter = 0; typeiter < type_cnt; typeiter++) {
+ cJSON *type = cJSON_GetArrayItem(types, typeiter);
+ node->single[iter].resource_types[typeiter] = things_malloc(sizeof(char *) *strlen(type->valuestring) + 1);
+ memcpy(node->single[iter].resource_types[typeiter], type->valuestring, strlen(type->valuestring) + 1);
+ }
+ } else {
+ return 0;
+ }
+ cJSON *interfaces = cJSON_GetObjectItem(res, KEY_DEVICE_RESOURCE_INTERFACES);
+ if (interfaces) {
+ int if_cnt = cJSON_GetArraySize(interfaces);
+ node->single[iter].if_cnt = if_cnt;
+ for (int ifiter = 0; ifiter < if_cnt; ifiter++) {
+ cJSON *interface = cJSON_GetArrayItem(interfaces, ifiter);
+ node->single[iter].interface_types[ifiter] = things_malloc(sizeof(char *) *strlen(interface->valuestring) + 1);
+ memcpy(node->single[iter].interface_types[ifiter], interface->valuestring, strlen(interface->valuestring) + 1);
+ }
+ } else {
+ return 0;
+ }
+ cJSON *policy = cJSON_GetObjectItem(res, KEY_DEVICE_RESOURCE_POLICY);
+ if (policy) {
+ node->single[iter].policy = policy->valueint;
+ } else {
+ return 0;
+ }
+
+ }
+ }
+
+ /***** register additional resource(provisininginfo / accesspointlist) *****/
+ int resCnt = sizeof(gstResources) / sizeof(things_resource_info_s);
+ for (int itr = 0; itr < resCnt; itr++) {
+ memcpy(node->single[node->sig_cnt].uri, gstResources[itr].uri, strlen(gstResources[itr].uri) + 1);
+ int type_cnt = gstResources[itr].rt_cnt;
+ node->single[node->sig_cnt].rt_cnt = type_cnt;
+ for (int typeiter = 0; typeiter < type_cnt; typeiter++) {
+ node->single[node->sig_cnt].resource_types[typeiter] = gstResources[itr].resource_types[typeiter];
+ }
+
+ int if_cnt = gstResources[itr].if_cnt;
+ node->single[node->sig_cnt].if_cnt = if_cnt;
+ for (int ifiter = 0; ifiter < if_cnt; ifiter++) {
+ node->single[node->sig_cnt].interface_types[ifiter] = gstResources[itr].interface_types[ifiter];
+ }
+ node->single[node->sig_cnt].policy = gstResources[itr].policy;
+ node->sig_cnt++;
+ }
+
+ THINGS_LOG_D(THINGS_INFO, TAG, "Resources for Single Usage Cnt : %d", node->sig_cnt);
+ } else {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Single Reosurces Not Exist");
+ }
+ } else {
+ THINGS_LOG_D(THINGS_INFO, TAG, "Reosurces Not Exist");
+ ret = 0;
+ }
+ hashmap_insert(g_device_hmap, node, (unsigned long)device_num);
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[DEVICE] ============================================");
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[DEVICE] Total Device Num : %d", (int)hashmap_count(g_device_hmap));
+
+ // for resourceType
+ struct st_resource_type_s *restype = NULL;
+ cJSON *resource_types = cJSON_GetObjectItem(root, KEY_RESOURCES_TYPE);
+ resource_type_cnt = cJSON_GetArraySize(resource_types);
+ g_resource_type_hmap = hashmap_create(resource_type_cnt);
+
+ THINGS_LOG_D(THINGS_INFO, TAG, "Resource Types Cnt : %d", resource_type_cnt);
+ for (int i = 0; i < resource_type_cnt; i++) {
+ int index = 0;
+
+ restype = create_resource_type();
+
+ cJSON *cj_rt = cJSON_GetArrayItem(resource_types, i);
+ cJSON *rtype = cJSON_GetObjectItem(cj_rt, KEY_DEVICE_RESOURCETYPE_TYPE);
+ cJSON *properties = cJSON_GetObjectItem(cj_rt, KEY_DEVICE_RESOURCETYPE_PROPERTIES);
+
+ if (NULL != rtype) {
+ index = hashmap_get_hashval((unsigned char *)rtype->valuestring);
+ memcpy(restype->rt, rtype->valuestring, strlen(rtype->valuestring) + 1);
+
+ if (NULL != properties) {
+ restype->prop_cnt = cJSON_GetArraySize(properties);
+
+ for (int iter2 = 0; iter2 < (restype->prop_cnt); iter2++) {
+ cJSON *attr = cJSON_GetArrayItem(properties, iter2);
+ cJSON *key = cJSON_GetObjectItem(attr, KEY_DEVICE_RESOURCETYPE_PROPERTIES_KEY);
+ cJSON *type = cJSON_GetObjectItem(attr, KEY_DEVICE_RESOURCETYPE_PROPERTIES_TYPE);
+ cJSON *mandatory = cJSON_GetObjectItem(attr, KEY_DEVICE_RESOURCETYPE_PROPERTIES_MANDATORY);
+ cJSON *rw = cJSON_GetObjectItem(attr, KEY_DEVICE_RESOURCETYPE_PROPERTIES_RW);
+ restype->prop[iter2] = create_property();
+ if (key->valuestring != NULL) {
+ memcpy(restype->prop[iter2]->key, key->valuestring, strlen(key->valuestring) + 1);
+ }
+ if (type->valueint != NULL) {
+ restype->prop[iter2]->type = type->valueint;
+ }
+
+ if (mandatory->type == cJSON_True) {
+ restype->prop[iter2]->mandatory = true;
+ } else {
+ restype->prop[iter2]->mandatory = false;
+ }
+
+ restype->prop[iter2]->rw = rw->valueint;
+ }
+ } else {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "Not Attribute Exist~!!!! ");
+ }
+ hashmap_insert(g_resource_type_hmap, restype, index);
+ }
+ }
+
+ /***** register additional resourcetype(provisininginfo / accesspointlist) *****/
+ int res_type_cnt = sizeof(gst_resource_types) / sizeof(st_resource_type_s);
+ for (int rtItr = 0; rtItr < res_type_cnt; rtItr++) {
+ int idx = hashmap_get_hashval((unsigned char *)gst_resource_types[rtItr].rt);
+ hashmap_insert(g_resource_type_hmap, &gst_resource_types[rtItr], idx);
+ resource_type_cnt++;
+ }
+
+ //for configuration
+ cJSON *configuration = cJSON_GetObjectItem(root, KEY_CONFIGURATION);
+ if (NULL != configuration) {
+ int connectivity_type = 0;
+
+ cJSON *easysetup = cJSON_GetObjectItem(configuration, KEY_CONFIGURATION_EASYSETUP);
+ if (NULL != easysetup) {
+ cJSON *connectivity = cJSON_GetObjectItem(easysetup, KEY_CONFIGURATION_EASYSETUP_CONNECTIVITY);
+ if (NULL != connectivity) {
+ cJSON *type = cJSON_GetObjectItem(connectivity, KEY_CONFIGURATION_EASYSETUP_CONNECTIVITY_TYPE);
+ connectivity_type = type->valueint;
+ THINGS_LOG_D(THINGS_INFO, TAG, "[configuration] type : %d", connectivity_type);
+ if (connectivity_type == 1) {
+ es_conn_type = es_conn_type_softap;
+ cJSON *softap = cJSON_GetObjectItem(connectivity, KEY_CONFIGURATION_EASYSETUP_CONNECTIVITY_SOFTAP);
+ if (NULL != softap) {
+ cJSON *manufature_id = cJSON_GetObjectItem(softap, KEY_CONFIGURATION_EASYSETUP_CONNECTIVITY_SOFTAP_MANUFACTUREID);
+ cJSON *setup_id = cJSON_GetObjectItem(softap, KEY_CONFIGURATION_EASYSETUP_CONNECTIVITY_SOFTAP_SETUPID);
+ cJSON *artik = cJSON_GetObjectItem(softap, KEY_CONFIGURATION_EASYSETUP_CONNECTIVITY_SOFTAP_ARTIK);
+
+ if (NULL != manufature_id && NULL != setup_id) {
+ bool is_artik = false;
+ if (artik->type == cJSON_True) {
+ is_artik = true;
+ } else {
+ is_artik = false;
+ }
+
+ THINGS_LOG_D(THINGS_INFO, TAG, "[configuration] manufature_id : %s / setup_id : %s / artik : %d", manufature_id->valuestring, setup_id->valuestring, is_artik);
+
+ g_manufacturer_name = things_malloc(sizeof(char *) *strlen(manufature_id->valuestring) + 1);
+ strncpy(g_manufacturer_name, manufature_id->valuestring, strlen(manufature_id->valuestring) + 1);
+
+ g_setup_id = things_malloc(sizeof(char *) *strlen(setup_id->valuestring) + 1);
+ strncpy(g_setup_id, setup_id->valuestring, strlen(setup_id->valuestring) + 1);
+ } else {
+ return 0;
+ }
+ }
+ } else if (connectivity_type == 2) {
+ //TO DO
+ es_conn_type = es_conn_type_ble;
+ } else {
+ return 0;
+ }
+ } else {
+ return 0;
+ }
+
+ cJSON *ownership_transfer_method = cJSON_GetObjectItem(easysetup, KEY_CONFIGURATION_EASYSETUP_OWNERSHIP);
+ if (NULL != ownership_transfer_method) {
+ g_ownership_transfer_method = ownership_transfer_method->valueint;
+ THINGS_LOG_D(THINGS_INFO, TAG, "[configuration] ownership_transfer_method : %d", g_ownership_transfer_method);
+ } else {
+ return 0;
+ }
+
+ }
+ cJSON *wifi = cJSON_GetObjectItem(configuration, KEY_CONFIGURATION_WIFI);
+ if (NULL != wifi) {
+ cJSON *wifi_interfaces = cJSON_GetObjectItem(wifi, KEY_CONFIGURATION_WIFI_INTERFACES);
+ cJSON *wifi_frequency = cJSON_GetObjectItem(wifi, KEY_CONFIGURATION_WIFI_FREQUENCY);
+ if (NULL != wifi_interfaces && NULL != wifi_frequency) {
+ THINGS_LOG_D(THINGS_INFO, TAG, "[configuration] wifi_interfaces : %d / wifi_frequency : %d", wifi_interfaces->valueint, wifi_frequency->valueint);
+ g_wifi_interface = wifi_interfaces->valueint;
+
+ if (wifi_frequency->valueint == 1) {
+ g_wifi_freq = WiFi_24G;
+ } else if (wifi_frequency->valueint == 2) {
+ g_wifi_freq = WiFi_5G;
+ } else if (wifi_frequency->valueint == 3) {
+ g_wifi_freq = WiFi_BOTH;
+ } else {
+ THINGS_LOG_D(THINGS_INFO, TAG, "unknown wifi freq value");
+ }
+ } else {
+ return 0;
+ }
+ } else {
+ return 0;
+ }
+
+ cJSON *file_path = cJSON_GetObjectItem(configuration, KEY_CONFIGURATION_FILEPATH);
+ if (NULL != file_path) {
+ cJSON *svrdb = cJSON_GetObjectItem(file_path, KEY_CONFIGURATION_FILEPATH_SVRDB);
+ cJSON *provisioning = cJSON_GetObjectItem(file_path, KEY_CONFIGURATION_FILEPATH_PROVISIONING);
+ cJSON *certificate = cJSON_GetObjectItem(file_path, KEY_CONFIGURATION_FILEPATH_CERTIFICATE);
+ cJSON *privateKey = cJSON_GetObjectItem(file_path, KEY_CONFIGURATION_FILEPATH_PRIVATEKEY);
+
+ if (NULL != svrdb && NULL != provisioning && NULL != certificate && NULL != privateKey) {
+ memset(g_svrdb_file_path, 0, (size_t) MAX_FILE_PATH_LENGTH);
+ memset(g_certificate_file_path, 0, (size_t) MAX_FILE_PATH_LENGTH);
+ memset(g_private_key_file_path, 0, (size_t) MAX_FILE_PATH_LENGTH);
+ memcpy(g_svrdb_file_path, svrdb->valuestring, strlen(svrdb->valuestring) + 1);
+ memcpy(g_certificate_file_path, certificate->valuestring, strlen(certificate->valuestring) + 1);
+ memcpy(g_private_key_file_path, privateKey->valuestring, strlen(privateKey->valuestring) + 1);
+ memcpy(g_things_cloud_file_path, provisioning->valuestring, strlen(provisioning->valuestring) + 1);
+
+ THINGS_LOG_D(THINGS_INFO, TAG, "Security SVR DB file path : %s", g_svrdb_file_path);
+ THINGS_LOG_D(THINGS_INFO, TAG, "[configuration] svrdb : %s / provisioning : %s", svrdb->valuestring, provisioning->valuestring);
+ THINGS_LOG_D(THINGS_INFO, TAG, "[configuration] certificate : %s / privateKey : %s", certificate->valuestring, privateKey->valuestring);
+
+ ret = 1;
+ } else {
+ return 0;
+ }
+ } else {
+ return 0;
+ }
+ }
+ if (NULL != root) {
+ cJSON_Delete(root);
+ }
+
+ }
+
+ if (json_str != NULL) {
+ things_free(json_str);
+ }
+
+ parse_things_cloud_json(g_things_cloud_file_path);
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_EXIT);
+ return ret;
+}
+
+static int get_signup_data_from_json(const char *filename, es_cloud_signup_s **cl_data)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+
+ int ret = 1;
+ char *json_str = get_json_string_from_file(filename);
+
+ if (json_str != NULL && strlen(json_str) > 0) {
+ // 3. Parse the Json string
+ cJSON *root = cJSON_Parse((const char *)json_str);
+ cJSON *cloud = cJSON_GetObjectItem(root, KEY_CLOUD);
+ if (cloud == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "cloud cJSON is NULL.");
+ ret = 0;
+ } else if ((ret = load_cloud_signup_data(cloud, cl_data)) != 1) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Load Cloud SignUp Data Failed.");
+ }
+
+ cJSON_Delete(root);
+ } else {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "cloud file Reading is failed.");
+ ret = 0;
+ }
+
+ if (json_str != NULL) {
+ things_free(json_str);
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_EXIT);
+ return ret;
+}
+
+int save_acces_point_info(wifi_manager_ap_config_s *connect_config)
+{
+ THINGS_LOG_D(THINGS_INFO, TAG, THINGS_FUNC_ENTRY);
+
+ char *filename = g_things_cloud_file_path;
+
+ int ret = 0;
+ cJSON *root = NULL;
+ char *json_update = NULL;
+ char *json_str = get_json_string_from_file(filename);
+
+ if (json_str != NULL && strlen(json_str) > 0) {
+ root = cJSON_Parse((const char *)json_str);
+
+ cJSON *wifi = cJSON_GetObjectItem(root, KEY_WIFI);
+ if (wifi == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "cloud cJSON is NULL.");
+ goto GOTO_OUT;
+ }
+
+ cJSON_DeleteItemFromObject(wifi, KEY_WIFI_SSID);
+ cJSON_DeleteItemFromObject(wifi, KEY_WIFI_PASSPHARASE);
+ cJSON_DeleteItemFromObject(wifi, KEY_WIFI_AUTH_TYPE);
+ cJSON_DeleteItemFromObject(wifi, KEY_WIFI_CRYPTO_TYPE);
+
+ if (strlen(connect_config->ssid) > 0) {
+ cJSON_AddStringToObject(wifi, KEY_WIFI_SSID, connect_config->ssid);
+ }
+ if (strlen(connect_config->passphrase) > 0) {
+ cJSON_AddStringToObject(wifi, KEY_WIFI_PASSPHARASE, connect_config->passphrase);
+ }
+ cJSON_AddNumberToObject(wifi, KEY_WIFI_AUTH_TYPE, connect_config->ap_auth_type);
+ cJSON_AddNumberToObject(wifi, KEY_WIFI_CRYPTO_TYPE, connect_config->ap_crypto_type);
+
+ json_update = cJSON_Print(root);
+
+ if (set_json_string_into_file(filename, json_update) == 0) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Fail : Store data to info file.");
+ goto GOTO_OUT;
+ }
+
+ ret = 1;
+ } // End of if
+
+ THINGS_LOG_D(THINGS_INFO, TAG, "Update Success in \"%s\" file.", filename);
+
+GOTO_OUT:
+ if (root) {
+ cJSON_Delete(root);
+ root = NULL;
+ }
+
+ if (json_str != NULL) {
+ things_free(json_str);
+ }
+
+ if (json_update != NULL) {
+ things_free(json_update);
+ }
+
+ THINGS_LOG_D(THINGS_INFO, TAG, THINGS_FUNC_EXIT);
+ return ret;
+}
+
+static int update_things_cloud_json_by_cloud_signup(const char *filename, es_cloud_signup_s *cl_data)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+
+ int ret = 0;
+ cJSON *root = NULL;
+ char *json_update = NULL;
+ char *json_str = get_json_string_from_file(filename);
+
+ if (json_str != NULL && strlen(json_str) > 0) {
+ // 3. Parse the Json string
+ root = cJSON_Parse((const char *)json_str);
+
+ // Cloud Items
+ cJSON *cloud = cJSON_GetObjectItem(root, KEY_CLOUD);
+ if (cloud == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "cloud cJSON is NULL.");
+ goto GOTO_OUT;
+ }
+
+ if (cl_data != NULL) {
+ cJSON_DeleteItemFromObject(cloud, KEY_CLOUD_ADDRESS);
+ }
+ cJSON_DeleteItemFromObject(cloud, KEY_CLOUD_DOMAIN);
+ cJSON_DeleteItemFromObject(cloud, KEY_CLOUD_PORT);
+ cJSON_DeleteItemFromObject(cloud, KEY_TOKEN_ACCESS);
+ cJSON_DeleteItemFromObject(cloud, KEY_TOKEN_ACCESS_REFRESH);
+ cJSON_DeleteItemFromObject(cloud, KEY_TOKEN_TYPE);
+ cJSON_DeleteItemFromObject(cloud, KEY_EXPIRE_TIME);
+ cJSON_DeleteItemFromObject(cloud, KEY_ID_USER);
+ cJSON_DeleteItemFromObject(cloud, KEY_SERVER_REDIRECT_URI);
+ cJSON_DeleteItemFromObject(cloud, KEY_CERTIFICATE_FILE);
+ cJSON_DeleteItemFromObject(cloud, KEY_SERVER_ID);
+
+ memset(g_cloud_address, 0, MAX_CLOUD_ADDRESS);
+ if (cl_data != NULL) {
+ if (things_strcat(g_cloud_address, MAX_CLOUD_ADDRESS, cl_data->address) == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Fail : Copy to g_cloud_address.");
+ goto GOTO_OUT;
+ }
+ if (cl_data->domain != NULL && strlen(cl_data->domain) > 0) {
+ cJSON_AddStringToObject(cloud, KEY_CLOUD_DOMAIN, cl_data->domain);
+ }
+ if (cl_data->address != NULL && strlen(cl_data->address) > 0) {
+ cJSON_AddStringToObject(cloud, KEY_CLOUD_ADDRESS, cl_data->address);
+ }
+ if (cl_data->port != NULL && strlen(cl_data->port) > 0) {
+ cJSON_AddStringToObject(cloud, KEY_CLOUD_PORT, cl_data->port);
+ }
+ if (cl_data->access_token != NULL && strlen(cl_data->access_token) > 0) {
+ cJSON_AddStringToObject(cloud, KEY_TOKEN_ACCESS, cl_data->access_token);
+ }
+ if (cl_data->refresh_token != NULL && strlen(cl_data->refresh_token) > 0) {
+ cJSON_AddStringToObject(cloud, KEY_TOKEN_ACCESS_REFRESH, cl_data->refresh_token);
+ }
+ if (cl_data->token_type != NULL && strlen(cl_data->token_type) > 0) {
+ cJSON_AddStringToObject(cloud, KEY_TOKEN_TYPE, cl_data->token_type);
+ }
+ if (cl_data->expire_time != CLOUD_EXPIRESIN_INVALID) {
+ cJSON_AddNumberToObject(cloud, KEY_EXPIRE_TIME, cl_data->expire_time);
+ }
+ if (cl_data->uid != NULL && strlen(cl_data->uid) > 0) {
+ cJSON_AddStringToObject(cloud, KEY_ID_USER, cl_data->uid);
+ }
+ if (cl_data->redirect_uri != NULL && strlen(cl_data->redirect_uri) > 0) {
+ cJSON_AddStringToObject(cloud, KEY_SERVER_REDIRECT_URI, cl_data->redirect_uri);
+ }
+ if (cl_data->certificate != NULL && strlen(cl_data->certificate) > 0) {
+ cJSON_AddStringToObject(cloud, KEY_CERTIFICATE_FILE, cl_data->certificate);
+ }
+ if (cl_data->sid != NULL && strlen(cl_data->sid) > 0) {
+ cJSON_AddStringToObject(cloud, KEY_SERVER_ID, cl_data->sid);
+ }
+ }
+
+ json_update = cJSON_Print(root);
+
+ if (set_json_string_into_file(filename, json_update) == 0) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Fail : Store data to info file.");
+ goto GOTO_OUT;
+ }
+
+ ret = 1;
+ } // End of if
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Update Success in \"%s\" file.", filename);
+
+GOTO_OUT:
+ if (root) {
+ cJSON_Delete(root);
+ root = NULL;
+ }
+
+ if (json_str != NULL) {
+ things_free(json_str);
+ }
+
+ if (json_update != NULL) {
+ things_free(json_update);
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_EXIT);
+ return ret;
+}
+
+static int Parse_things_files(const char *info_Path)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+ int res = 1;
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "orginal info file path = %s", info_Path);
+ if (!parse_things_info_json(info_Path)) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Info file parsing Failed");
+ res = 0;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_EXIT);
+ return res;
+}
+
+int dm_load_legacy_cloud_data(es_cloud_signup_s **cl_data)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+
+ int ret = 1;
+
+ if (g_things_cloud_file_path[0] == 0 || cl_data == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Provisioning file path is NULL.(%s) or Invalid argument.(0x%X)", g_things_cloud_file_path, cl_data);
+ return 0;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "g_things_cloud_file_path = %s", g_things_cloud_file_path);
+
+ if ((ret = get_signup_data_from_json(g_things_cloud_file_path, cl_data)) != 1) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Not Get sign-up data failed from Provisioning file.");
+ }
+
+ usleep(500000);
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_EXIT);
+
+ return ret;
+}
+
+const char *dm_get_things_device_type(int device_id)
+{
+ //THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+ st_device_s *device = NULL;
+
+ device = (st_device_s *) hashmap_get(g_device_hmap, (unsigned long)device_id);
+ if (device == NULL) {
+
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Device Not Exist");
+ return NULL;
+ }
+
+ return device->type;
+}
+
+const char *dm_get_svrdb_file_path(void)
+{
+ return g_svrdb_file_path;
+}
+
+const char *dm_get_certificate_file_path(void)
+{
+ return g_certificate_file_path;
+}
+
+const char *dm_get_privatekey_file_path(void)
+{
+ return g_private_key_file_path;
+}
+
+const char *dm_get_things_cloud_address(char *customized_ci_server)
+{
+ if (customized_ci_server && customized_ci_server[0] != 0) {
+ return customized_ci_server;
+ }
+ return get_cloud_server_address(customized_ci_server);
+}
+
+bool dm_is_rsc_published(void)
+{
+ return (es_get_state() == ES_STATE_PUBLISHED_RESOURCES_TO_CLOUD ? true : false);
+}
+
+static things_resource_s *register_resource(things_server_builder_s *p_builder, struct things_resource_info_s *resource, const char *id)
+{
+ things_resource_s *ret = NULL;
+ char res_uri[MAX_URI_LENGTH] = { 0 };
+
+ if (NULL != resource) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "RESOURCE TO REGISTER : %s", resource->uri);
+
+ memset(res_uri, 0, (size_t) MAX_URI_LENGTH);
+ /*SVACE warning fix */
+ strncat(res_uri, resource->uri, MAX_URI_LENGTH);
+
+ ret = p_builder->create_resource(p_builder, res_uri, resource->resource_types[0], resource->interface_types[0], CHECK_DISCOVERABLE(resource->policy), CHECK_OBSERVABLE(resource->policy), CHECK_SECURE(resource->policy));
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "add_resource_type : %s", resource->resource_types[0]);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "add_interface_type : %s", resource->interface_types[0]);
+ for (int rt_num = 1; rt_num < resource->rt_cnt; rt_num++) {
+ p_builder->add_resource_type(ret, resource->resource_types[rt_num]);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "add_resource_type : %s", resource->resource_types[rt_num]);
+ }
+
+ for (int it_num = 1; it_num < resource->if_cnt; it_num++) {
+ p_builder->add_interface_type(ret, resource->interface_types[it_num]);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "add_interface_type : %s", resource->interface_types[it_num]);
+ }
+ } else {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Invalid Input Param ");
+ }
+
+ return ret;
+}
+
+static things_resource_s *register_device_resource(things_server_builder_s *p_builder, st_device_s *device, const char *id)
+{
+ things_resource_s *ret = NULL;
+ char res_uri[MAX_URI_LENGTH] = { 0 };
+
+ if (NULL != device) {
+ memset(res_uri, 0, (size_t) MAX_URI_LENGTH);
+ strncat(res_uri, OC_RSRVD_DEVICE_URI, MAX_URI_LENGTH);
+
+ ret = p_builder->create_resource(p_builder, res_uri, OC_RSRVD_RESOURCE_TYPE_DEVICE, OC_RSRVD_INTERFACE_READ, 0, 0, 1);
+
+ p_builder->add_resource_type(ret, device->type);
+
+ ret->rep = things_create_representation_inst(NULL);
+ if (ret->rep) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[/oic/d] name :%s", device->name);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[/oic/d] type :%s", device->type);
+
+ ret->rep->things_set_value(ret->rep, OC_RSRVD_DEVICE_NAME, device->name);
+
+ ret->rep->things_set_value(ret->rep, OC_RSRVD_DEVICE_ID, device->device_id);
+
+ ret->rep->things_set_value(ret->rep, OC_RSRVD_SPEC_VERSION, OC_SPEC_VERSION);
+
+ ret->rep->things_set_value(ret->rep, OC_RSRVD_DATA_MODEL_VERSION, OC_DATA_MODEL_VERSION);
+ } else {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Not able to create representation");
+ }
+ } else {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Invalid Input Param ");
+ }
+
+ return ret;
+}
+
+static things_resource_s *register_platform_resource(things_server_builder_s *p_builder, st_device_s *device, const char *id)
+{
+ things_resource_s *ret = NULL;
+ char res_uri[MAX_URI_LENGTH] = { 0 };
+
+ if (NULL != device) {
+ memset(res_uri, 0, (size_t) MAX_URI_LENGTH);
+ strncat(res_uri, OC_RSRVD_PLATFORM_URI, MAX_URI_LENGTH);
+
+ ret = p_builder->create_resource(p_builder, res_uri, OC_RSRVD_RESOURCE_TYPE_PLATFORM, OC_RSRVD_INTERFACE_READ, 0, 0, 1);
+
+ ret->rep = things_create_representation_inst(NULL);
+ if (ret->rep) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[/oic/p] Manufacturer :%s", MANUFACTURER_NAME);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[/oic/p] Model Name :%s", device->model_num);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[/oic/p] Ver. Plaform :%s", device->ver_p);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[/oic/p] Ver. OS :%s", device->ver_os);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[/oic/p] Ver. HW :%s", device->ver_hw);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[/oic/p] Ver. FW :%s", device->ver_fw);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[/oic/p] Ver. vid :%s", device->vender_id);
+
+ ret->rep->things_set_value(ret->rep, OC_RSRVD_PLATFORM_ID, device->device_id);
+
+ ret->rep->things_set_value(ret->rep, OC_RSRVD_MFG_NAME, MANUFACTURER_NAME);
+
+ ret->rep->things_set_value(ret->rep, OC_RSRVD_MODEL_NUM, device->model_num);
+
+ ret->rep->things_set_value(ret->rep, OC_RSRVD_PLATFORM_VERSION, device->ver_p);
+
+ ret->rep->things_set_value(ret->rep, OC_RSRVD_OS_VERSION, device->ver_os);
+
+ ret->rep->things_set_value(ret->rep, OC_RSRVD_HARDWARE_VERSION, device->ver_hw);
+
+ ret->rep->things_set_value(ret->rep, OC_RSRVD_FIRMWARE_VERSION, device->ver_fw);
+
+ ret->rep->things_set_value(ret->rep, OC_RSRVD_MFG_URL, MANUFACTURER_URL);
+
+ ret->rep->things_set_value(ret->rep, OC_RSRVD_VID, device->vender_id);
+ } else {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Not able to create representation");
+ }
+
+ } else {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Invalid Input Param ");
+ }
+
+ return ret;
+}
+
+long dm_get_num_of_dev_cnt(void)
+{
+ return hashmap_count(g_device_hmap);
+}
+
+st_device_s *dm_get_info_of_dev(unsigned long number)
+{
+ return (st_device_s *) hashmap_get(g_device_hmap, number);
+}
+
+bool dm_register_user_define_device_id(const int seq_thing_info, const char *dev_id)
+{
+ if (is_support_user_def_dev_list == false) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "No More Support User define Device ID.");
+ return false;
+ }
+
+ if (seq_thing_info < 1 || seq_thing_info > MAX_SUBDEVICE_EA || dev_id == NULL || strlen(dev_id) == 0) {
+ THINGS_LOG_V(THINGS_INFO, TAG, "It Support Max %d EA for device ID", MAX_SUBDEVICE_EA);
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Invalid arguments.(seq_thing_info=%d, dev_id=0x%X)", seq_thing_info, dev_id);
+ return false;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "seq_thing_info=%d, dev_id=%s", seq_thing_info, dev_id);
+
+ if (strlen(dev_id) >= MAX_DEVICE_ID_LENGTH) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Overflow device ID length.(It Support Max length: %d)", MAX_DEVICE_ID_LENGTH);
+ return false;
+ }
+ user_def_dev_list[seq_thing_info] = strdup(dev_id);
+
+ return true;
+}
+
+static void dm_delete_user_define_device_id(void)
+{
+ int i = 0;
+
+ for (i = 0; i < MAX_SUBDEVICE_EA; i++) {
+ things_free(user_def_dev_list[i]);
+ user_def_dev_list[i] = NULL;
+ }
+}
+
+bool dm_register_device_id(void)
+{
+ int i = 0;
+ char *id = NULL;
+ st_device_s **dev_list = NULL;
+ int device_cnt = (int)hashmap_count(g_device_hmap);
+ if (device_cnt < 1) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "No Device Information to Register");
+ return false;
+ }
+
+ if ((dev_list = (st_device_s **) things_malloc(sizeof(st_device_s *) *device_cnt)) == NULL) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "st_device_s mem allocation is failed.");
+ return false;
+ }
+ // Set Main-Device ID
+ id = OCGetServerInstanceIDString();
+ dev_list[0] = (st_device_s *) hashmap_get(g_device_hmap, (unsigned long)0);
+
+ if (id == NULL || dev_list[0] == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Error : id = %s, Main-device =0x%X", id, dev_list[0]);
+ goto GOTO_ERROR;
+ }
+ memcpy(dev_list[0]->device_id, id, strlen(id) + 1);
+
+ // Set Sub-Device ID
+ for (i = 1; i < device_cnt; i++) {
+ dev_list[i] = (st_device_s *) hashmap_get(g_device_hmap, (unsigned long)i);
+ if (dev_list[i] == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Error : device[%d] =0x%X", i, dev_list[i]);
+ goto GOTO_ERROR;
+ }
+
+ if (user_def_dev_list[i] != NULL || strlen(dev_list[i]->device_id) == 0) {
+ // a. If logical device is in a hosting(physical) device.
+ if (dev_list[i]->is_physical == 1) {
+ OCRandomUuidResult idGenRet = RAND_UUID_CONVERT_ERROR;
+
+ if (user_def_dev_list[i]) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Set Sub-device ID with user-defined device ID.");
+ memcpy(dev_list[i]->device_id, user_def_dev_list[i], strlen(user_def_dev_list[i]) + 1);
+ idGenRet = RAND_UUID_OK;
+ } else {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Set Sub-device ID with Auto-Generated device ID.");
+ idGenRet = OCGenerateUuidString(dev_list[i]->device_id);
+ }
+
+ if (idGenRet != RAND_UUID_OK) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "[DEVICE] Device ID Creation Failed : %d", idGenRet);
+ } else {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[DEVICE] ID Created : %s", (dev_list[i]->device_id));
+ }
+ }
+ // b. If logical device is in the other physical device
+ else {
+ THINGS_LOG_D(THINGS_INFO, TAG, "[DEVICE] Not Physically Separated Device ");
+ }
+ }
+ }
+
+ is_support_user_def_dev_list = false; // It's allow permission to apply user defined device-ID only when start THINGS_STACK.
+
+ dm_delete_user_define_device_id();
+ things_free(dev_list);
+ dev_list = NULL;
+ return true;
+
+GOTO_ERROR:
+ things_free(dev_list);
+ dev_list = NULL;
+ return false;
+}
+
+int dm_register_resource(things_server_builder_s *p_builder)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+
+ if (p_builder == NULL) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Builder instance is NULL");
+
+ return 0;
+ }
+
+ int device_cnt = (int)hashmap_count(g_device_hmap);
+ if (device_cnt < 1) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "No Device Information to Register");
+
+ return 0;
+ }
+
+ for (int device_num = 0; device_num < device_cnt; device_num++) {
+ char id[11] = { 0 };
+ char res_uri[MAX_URI_LENGTH] = { 0 };
+ int key = 0;
+ int n_count_of_children = 0;
+
+ st_device_s *device = NULL;
+ struct things_resource_info_s *resource = NULL;
+ struct col_resource_s *col_resource_s = NULL;
+ struct things_resource_s *p_collection_resource = NULL;
+
+ // 2. Device Capability Resources Registration
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "BEFORE SEARCHING THE DEVICE ITEM FROM HASH TABLE");
+
+ device = (st_device_s *) hashmap_get(g_device_hmap, (unsigned long)device_num);
+
+ if (NULL != device) {
+ /*SVACE warning fix */
+ snprintf(id, sizeof(id), "%d", device->no);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "==================== Device (%s) ====================", id);
+
+ if (device->col_cnt < 1) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "NO COLLECTION & ITS CHILDREN RESOURCE(S)");
+ } else {
+ THINGS_LOG_D(THINGS_INFO, TAG, "COLLECTION CHILDREN RESOURCE(S) CNT : %d", device->col_cnt);
+
+ memset(res_uri, 0, (size_t) MAX_URI_LENGTH);
+ strncat(res_uri, device->collection[0].uri, MAX_URI_LENGTH);
+
+ p_collection_resource = p_builder->create_collection_resource(p_builder, res_uri, device->collection[0].resource_types[0], device->collection[0].interface_types[0]);
+
+ for (int rt_num = 1; rt_num < device->collection[0].rt_cnt; rt_num++) {
+ OCBindResourceTypeToResource(p_builder, device->collection[0].resource_types[rt_num]);
+ }
+
+ // THINGS_LOG_D(THINGS_DEBUG, TAG, "IT TO BIND : %d", resource->if_cnt);
+ for (int it_num = 1; it_num < device->collection[0].if_cnt; it_num++) {
+ OCBindResourceInterfaceToResource(p_builder, device->collection[0].interface_types[it_num]);
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "AFTER REGISTERGING DEVICE RESOURCE");
+
+ if (p_collection_resource != NULL) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "DEVICE RESOURCE(S) CNT : %d", device->col_cnt);
+ for (int capa_num = 0; capa_num < device->collection[0].link_cnt; capa_num++) {
+ resource = device->collection[0].links[capa_num];
+ device->pchild_resources[n_count_of_children++] = register_resource(p_builder, resource, id);
+ } // End of for children resource(s) registration loop
+ } // End of single device
+
+ p_builder->bind_all(p_collection_resource, device->pchild_resources, n_count_of_children);
+
+ device->pchild_resources[n_count_of_children++] = p_collection_resource;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "SINGLE RESOURCE(S) CNT : %d", device->sig_cnt);
+
+ for (int capa_num = 0; capa_num < device->sig_cnt; capa_num++) {
+ resource = &device->single[capa_num];
+ device->pchild_resources[n_count_of_children++] = register_resource(p_builder, resource, id);
+ } // End of for single resource registration loop
+
+ // Create the Device(/oic/d) and Platform (/oic/p)
+ // ex) Aircon Multi-Model
+ if (device_num < 1) {
+ // for hosting device
+ p_builder->set_device_info(p_builder, device->name, device->type);
+ p_builder->set_platform_info(p_builder, device->model_num, // gDeviceModel,
+ device->ver_p, // gPlatformVersion,
+ device->ver_os, // gOSVersion,
+ device->ver_hw, // gHWVersions,
+ device->ver_fw, // gFWVersions,
+ device->vender_id); // gVenderId);
+ } else {
+ if (device->is_physical == 1) {
+ THINGS_LOG_V(THINGS_INFO, TAG, "It's Physically Separated Device : %s", device->device_id);
+ // for those physically separated devices
+ // a. /oic/d/# resource
+ device->pchild_resources[n_count_of_children++] = register_device_resource(p_builder, device, id);
+ // b. /oic/p/# resource
+ device->pchild_resources[n_count_of_children++] = register_platform_resource(p_builder, device, id);
+ } else {
+ THINGS_LOG_V(THINGS_INFO, TAG, "It's Logical Device in One Physical Device : [%d]", device_num);
+ }
+ }
+
+ // Total Size of the device->pChildresources : col_cnt + sig_cnt + 1(/device) + a(/oic/d & /oic/p)
+ device->capa_cnt = n_count_of_children;
+ } // End of device NULL Check
+ } // End of for device loop
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "=====================================================");
+
+ if (p_builder->broadcast_presence(p_builder, 20) == 1) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Broadcast Presence Failed.");
+ return 0;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_EXIT);
+
+ return 1;
+}
+
+struct things_resource_s *dm_get_resource_instance(const char *uri, const int id)
+{
+ things_resource_s *ret = NULL;
+
+ int device_cnt = (int)hashmap_count(g_device_hmap);
+ if (device_cnt > 0 && device_cnt > id) {
+ st_device_s *device = (st_device_s *) hashmap_get(g_device_hmap, (unsigned long)(id));
+
+ if (device) {
+ for (int index = 0; index < MAX_DEVICE_CAPABILTY_CNT; index++) {
+ if (device->pchild_resources[index] == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Resource with URI : %s not exist !!!!", uri);
+ break;
+ } else if (strncmp(device->pchild_resources[index]->uri, uri, strlen(uri)) == 0) {
+ THINGS_LOG_V(THINGS_DEBUG, TAG, "Found %s from device[%d] : %s!!!!", uri, id, device->device_id);
+
+ char *sValue = NULL;
+
+ device->pchild_resources[index]->rep->things_get_value(device->pchild_resources[index]->rep, OC_RSRVD_DEVICE_ID, &sValue);
+ ret = device->pchild_resources[index];
+ break;
+ } else {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[%d] Resource URI : %s", index, device->pchild_resources[index]->uri);
+ }
+ }
+ }
+ }
+ return ret;
+}
+
+int dm_get_device_information(int *cnt, st_device_s ***list)
+{
+ int ret = 0;
+
+ int device_cnt = (int)hashmap_count(g_device_hmap);
+ if (device_cnt > 0) {
+ st_device_s **devices = NULL;
+ if ((devices = (st_device_s **) things_malloc(sizeof(st_device_s *) *device_cnt)) == NULL) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "st_device_s memory allocation is failed.");
+ return ret;
+ }
+
+ for (int index = 0; index < device_cnt; index++) {
+ devices[index] = (st_device_s *) hashmap_get(g_device_hmap, (unsigned long)index);
+ }
+
+ (*list) = devices;
+ (*cnt) = device_cnt;
+ ret = 1;
+ }
+
+ return ret;
+}
+
+const int dm_get_num_of_children(int device_num)
+{
+ int ret = 0;
+
+ st_device_s *device = (st_device_s *) hashmap_get(g_device_hmap, (unsigned long)device_num);
+ if (NULL != device) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "DEVICE CHILDREN RESOURCE(S) : %d", device->col_cnt);
+ ret = device->col_cnt;
+ }
+
+ return ret;
+}
+
+const char *dm_get_resource_uri(int device_num, int index)
+{
+ st_device_s *device = (st_device_s *) hashmap_get(g_device_hmap, (unsigned long)device_num);
+ if (NULL != device) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "DEVICE CHILDREN RESOURCE(S) : %d", device->col_cnt);
+ if ((index) >= device->col_cnt) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Invalid Index : %d", index);
+ } else {
+
+ return device->collection[0].links[index]->uri;
+ }
+ } else {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Invalid Device Num to Search : %d", device_num);
+ }
+
+ return NULL;
+}
+
+int dm_update_device_iInfo_list(st_device_s **dev_list, int devCnt)
+{
+ int ret = 1;
+ update_and_save_device_info(dev_list, devCnt);
+ return ret;
+}
+
+int dm_update_things_cloud(es_cloud_signup_s *cl_data)
+{
+ int ret = 1;
+
+ THINGS_LOG_V(THINGS_INFO, TAG, "RTOS Recived Signup Data domain[%s], address[%s], port [%s], access_token[%s], refresh_token[%s], token_type[%s], " "uid[%s]", cl_data->domain, cl_data->address, cl_data->port, cl_data->access_token, cl_data->refresh_token, cl_data->token_type, cl_data->uid);
+ THINGS_LOG_V(THINGS_INFO, TAG, "RTOS Recived Signup Data redirect_uri[%s], certificate[%s], sid[%s]", cl_data->redirect_uri, cl_data->certificate, cl_data->sid);
+
+ if (g_things_cloud_file_path[0] == 0 || cl_data == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "cloud file path is NULL(%s). or Invalid argument.(0x%X)", g_things_cloud_file_path, cl_data);
+ ret = 0;
+ return ret;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "g_things_cloud_file_path = %s", g_things_cloud_file_path);
+
+ if (update_things_cloud_json_by_cloud_signup(g_things_cloud_file_path, cl_data) == 0) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Provisioning file update failed.");
+ ret = 0;
+ }
+
+ if (ret == 1) {
+ int res = 0;
+ es_cloud_signup_s *confirmData = NULL;
+
+ if ((res = dm_load_legacy_cloud_data(&confirmData)) == 1) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Update Success.");
+ is_there_cloud_data = true;
+ es_cloud_signup_clear(confirmData);
+ confirmData = NULL;
+ } else {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Update Failed.(%d)", res); // 1 : Success , 0/-1 : system error. , -2 : saved invalid Cloud-Data.
+ is_there_cloud_data = false;
+ }
+ }
+
+ return ret;
+}
+
+int dm_del_things_cloud_data(void)
+{
+ THINGS_LOG(THINGS_DEBUG, TAG, "Enter.");
+
+ int ret = 1;
+ if (g_things_cloud_file_path[0] == 0) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "cloud file path is NULL.");
+ ret = 0;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "g_things_cloud_file_path = %s", g_things_cloud_file_path);
+
+ if (update_things_cloud_json_by_cloud_signup(g_things_cloud_file_path, NULL) == 0) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "It's failed to delete Cloud-Data in cloud file.");
+ ret = 0;
+ }
+
+ if (ret == 1) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Delete Success.");
+ is_there_cloud_data = false;
+ }
+
+ THINGS_LOG(THINGS_DEBUG, TAG, "Exit.");
+ return ret;
+}
+
+bool dm_is_there_things_cloud(void)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "is_there_cloud_data = %d", is_there_cloud_data);
+ return is_there_cloud_data;
+}
+
+int dm_validate_attribute_in_request(char *rt, const void *payload)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+ int ret = 0;
+
+ if (rt != NULL && payload != NULL) {
+ // 1. Get index with resource type
+ unsigned long index = hashmap_get_hashval((unsigned char *)rt);
+ OCRepPayload *r_payload = (OCRepPayload *) payload;
+
+ // 2. Get resource type instance
+ THINGS_LOG_D(THINGS_INFO, TAG, "Index : %u rt : %s", index, rt);
+ struct st_resource_type_s *res_type = (struct st_resource_type_s *)hashmap_get(g_resource_type_hmap, index);
+
+ if (NULL != res_type) {
+ int iter = 0;
+ // 3. Get attributes & check
+ // POLICY
+ // a. Check exsitence of read-only attributes in the payload which should not be..
+ for (iter = 0; iter < res_type->prop_cnt; iter++) {
+ if (NULL != res_type->prop[iter]
+ && (1 == CHECK_READABLE(res_type->prop[iter]->rw)
+ && 1 != CHECK_WRITABLE(res_type->prop[iter]->rw))
+ ) {
+ THINGS_LOG_D(THINGS_INFO, TAG, "\tCHECKING READ-ONLY ATTR : %s", res_type->prop[iter]->key);
+ if (!OCRepPayloadIsNull(r_payload, res_type->prop[iter]->key)) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "\t==> EXIST");
+ goto VALIDATION_EXIT;
+ } else {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "\t==> NOT EXIST");
+ }
+ }
+ }
+ // b. Check existence of rw attribute in the payload which should exist at least 1
+ for (iter = 0; iter < res_type->prop_cnt; iter++) {
+ if (NULL != res_type->prop[iter]
+ && 1 == CHECK_WRITABLE(res_type->prop[iter]->rw)) {
+ THINGS_LOG_D(THINGS_INFO, TAG, "\tCHECKING WRITE-ABLE ATTR : %s", res_type->prop[iter]->key);
+ if (!OCRepPayloadIsNull(r_payload, res_type->prop[iter]->key)) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "\t==> EXIST");
+
+ ret = 1;
+ break;
+ } else {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "\t==> NOT EXIST");
+ }
+ }
+ }
+ // c. Make it pass if it's collection resource
+ if (0 == strncmp(rt, OC_RSRVD_RESOURCE_TYPE_COLLECTION, strlen(OC_RSRVD_RESOURCE_TYPE_COLLECTION))
+ || 0 == strncmp(rt, SEC_RTYPE_THINGS_DEVICE, strlen(SEC_RTYPE_THINGS_DEVICE))) {
+ // TODO : Need to check whether there an array delivered or not..
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "\t==> Child %s", (r_payload->next != NULL ? "EXIST" : "NOT EXIST"));
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "\t==> Request On Collection Resource. Making it PASS");
+ ret = 1;
+ }
+ } else {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "Not Supporting rt : %s", rt);
+ }
+ } else {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "Invalid Input - rt : %s, payload %d", rt, payload);
+ }
+
+VALIDATION_EXIT:
+
+ if (ret == 0) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "\t==> INVALID REQUEST~!!!");
+ }
+ return ret;
+}
+
+int things_get_resource_type(const char *resource_uri, int *count, char ***resource_types)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "things_get_resource_type : %s", resource_uri);
+ int device_cnt = (int)hashmap_count(g_device_hmap);
+ if (device_cnt > 0) {
+ st_device_s *device = (st_device_s *) hashmap_get(g_device_hmap, (unsigned long)0);
+
+ if (device != NULL) {
+ if (device->sig_cnt > 0) {
+ for (int index = 0; index < device->sig_cnt; index++) {
+ if (strncmp(device->single[index].uri, resource_uri, strlen(resource_uri)) == 0) {
+ (*count) = device->single[index].rt_cnt;
+ (*resource_types) = device->single[index].resource_types;
+ return 1;
+ }
+ }
+ }
+ if (device->col_cnt > 0) {
+ for (int index = 0; index < device->col_cnt; index++) {
+ if (strncmp(device->collection[index].uri, resource_uri, strlen(resource_uri)) == 0) {
+ (*count) = device->collection[index].rt_cnt;
+ (*resource_types) = device->collection[index].resource_types;
+ return 1;
+ } else {
+ for (int index_links = 0; index_links < device->collection[index].link_cnt; index_links++) {
+ if (strncmp(device->collection[index].links[index_links]->uri, resource_uri, strlen(resource_uri)) == 0) {
+ (*count) = device->collection[index].links[index_links]->rt_cnt;
+ (*resource_types) = device->collection[index].links[index_links]->resource_types;
+ return 1;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+const int dm_get_wifi_property_interface()
+{
+ return g_wifi_interface;
+}
+
+const wifi_freq_e dm_get_wifi_property_freq()
+{
+ return g_wifi_freq;
+}
+
+const int dm_get_ownership_transfer_method()
+{
+ THINGS_LOG_V(THINGS_INFO, TAG, "ownership_transfer_method : %d", g_ownership_transfer_method);
+ return g_ownership_transfer_method;
+}
+
+int things_get_attributes_by_resource_type(const char *res_type, int *count, things_attribute_info_s ***attributes)
+{
+ int resource_type_cnt = (int)hashmap_count(g_resource_type_hmap);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "things_get_attributes_by_resource_type : %s, resource_type_cnt : %d", res_type, resource_type_cnt);
+
+ if (resource_type_cnt > 0) {
+
+ int index = hashmap_get_hashval(res_type);
+ struct st_resource_type_s *res_type = (struct st_resource_type_s *)hashmap_get(g_resource_type_hmap, index);
+ if (res_type == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "res_type Not Exist");
+ return 0;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "res_type : %s, res_type : %s", res_type->rt, res_type);
+ if (strncmp(res_type->rt, res_type, strlen(res_type)) == 0) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "res_type->prop_cnt : %d", res_type->prop_cnt);
+ (*count) = res_type->prop_cnt;
+ (*attributes) = res_type->prop;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+bool things_is_collection_resource(const char *res_uri)
+{
+ int device_cnt = (int)hashmap_count(g_device_hmap);
+ if (device_cnt > 0) {
+ st_device_s *device = NULL;
+
+ device = (st_device_s *) hashmap_get(g_device_hmap, (unsigned long)0);
+ if (device == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Device Not Exist");
+ return NULL;
+ }
+
+ if (device->col_cnt > 0) {
+ for (int index = 0; index < device->col_cnt; index++) {
+ if (strncmp(device->collection[index].uri, res_uri, strlen(res_uri)) == 0) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+int things_get_child_resources(const char *col_res_uri, int *count, things_resource_info_s ***child_resources)
+{
+ st_device_s *device = NULL;
+
+ device = (st_device_s *) hashmap_get(g_device_hmap, (unsigned long)0);
+ if (device == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Device Not Exist");
+ return NULL;
+ }
+
+ if (device->col_cnt > 0) {
+ for (int index = 0; index < device->col_cnt; index++) {
+ if (strncmp(device->collection[index].uri, col_res_uri, strlen(col_res_uri)) == 0) {
+ (*count) = device->collection[index].link_cnt;
+ (*child_resources) = device->collection[index].links;
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+int dm_init_module(const char *devJsonPath)
+{
+ if (devJsonPath == NULL) {
+ THINGS_LOG_D(THINGS_ERROR, TAG, "devJsonPath is NULL");
+ return 0;
+ }
+
+ memset(g_svrdb_file_path, 0, (size_t) MAX_FILE_PATH_LENGTH);
+ memset(g_things_cloud_file_path, 0, (size_t) MAX_FILE_PATH_LENGTH);
+ memset(g_cloud_address, 0, (size_t) MAX_CLOUD_ADDRESS);
+
+ return Parse_things_files(devJsonPath);
+}
+
+//
+
+int dm_termiate_module()
+{
+ // Need to backup all the keys in order to delete from the map.
+ hashmap_delete(g_device_hmap);
+ hashmap_delete(g_resource_type_hmap);
+ return 1;
+}
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 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.
+ *
+ ****************************************************************************/
+
+#define _POSIX_C_SOURCE 200809L
+#define _BSD_SOURCE // for the usleep
+#include <string.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <pthread.h>
+
+#include "ocpayload.h"
+
+#include "things_def.h"
+#include "things_common.h"
+#include "things_queue.h"
+#include "things_logger.h"
+#include "things_malloc.h"
+#include "cacommon.h"
+#include "things_string_util.h"
+#include "things_resource.h"
+#include "../utils/inc/things_network.h"
+#include "things_api.h"
+#include "things_types.h"
+#include "things_server_builder.h"
+#include "things_data_manager.h"
+
+#include "things_req_handler.h"
+#include "things_hashmap.h"
+
+#include "things_thread.h"
+#ifdef __ST_THINGS_RTOS__
+#include "ctype.h"
+#include "things_rtos_util.h"
+#endif
+
+#define TAG "[things_reqhdlr]"
+
+static handle_request_func_type g_handle_request_get_cb = NULL;
+static handle_request_func_type g_handle_request_set_cb = NULL;
+
+extern things_server_builder_s *g_builder;
+
+static queue_s *gp_oic_req_queue;
+static int g_handle_res_cnt = 0;
+static char **g_handle_res_list = NULL;
+static handle_request_func_type g_handle_req_cb = NULL;
+static get_notify_obs_uri_cb g_get_notify_obs_uri = NULL;
+
+static handle_request_interface_cb g_handle_request_interface_cb = NULL;
+
+static stop_softap_func_type g_stop_soft_ap_cb = NULL;
+
+static pthread_t g_req_handle;
+
+static int g_quit_flag = 0;
+
+OCEntityHandlerResult things_abort(pthread_t *h_thread_abort, things_es_enrollee_abort_e level);
+
+/**
+ * Return : 0 (Invalid Request), 1 (Resource Supporting Interface)
+ * Need refactoring later...
+ */
+static int verify_request(OCEntityHandlerRequest *eh_request, const char *uri, int req_type)
+{
+ int result = 0;
+
+ if (g_builder == NULL) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Server Builder is not registered..");
+ goto EXIT_VALIDATION;
+ }
+
+ things_resource_s *resource = things_create_resource_inst(eh_request->requestHandle,
+ eh_request->resource,
+ eh_request->query,
+ eh_request->payload); //g_builder->get_resource(g_builder, uri);
+ things_resource_s *child = NULL;
+ /*! Added by st_things for memory Leak fix
+ */
+ things_resource_s *pst_temp_resource = resource;
+ if (resource == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Resource Not found : %s ", uri);
+ goto EXIT_VALIDATION;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Query in the Request : %s", eh_request->query);
+
+ // Verify received request in valid or not..
+ // 1. If there's no interface type in the request ..
+ if ((strstr(eh_request->query, "if=") == NULL)
+ || (strstr(eh_request->query, OIC_INTERFACE_BASELINE) != NULL)
+ || (true == resource->things_is_supporting_interface_type(resource, eh_request->query))) {
+ result = 1;
+ }
+ // 2. If request type == POST(OC_REST_POST == 4),
+ // then validate the attributes kyes in the request
+ if (result == 1 && req_type == OC_REST_POST) {
+ // Reseting the result value to apply
+ // the result of additional verification
+ result = 0;
+
+ // if(gValidator == NULL )
+ // {s
+ // THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Validator not registered");
+ // goto EXIT_VALIDATION;
+ // }
+
+ // If the given resource does not have sensor nor read interface type..
+ if (!(resource->things_is_supporting_interface_type(resource, OIC_INTERFACE_SENSOR))
+ && !(resource->things_is_supporting_interface_type(resource, OC_RSRVD_INTERFACE_READ))) {
+ // If no query or..
+ // query with "supporting interface types" then...
+ if ((strstr(eh_request->query, "if=") == NULL)
+ || ((strstr(eh_request->query, "if=") != NULL)
+ && (resource->things_is_supporting_interface_type(resource, eh_request->query))
+ )
+ ) {
+ // Verify request(Attributes.) with Validator func implemented
+ const int num = resource->things_get_num_of_res_types(resource);
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "# of RT :%d", num);
+
+ if (resource->size > 1) {
+ // Remove "rep" wrapper
+ things_resource_s *res = resource;
+ things_representation_s *tRep = NULL;
+ things_representation_s *tchild_rep = NULL;
+
+ for (int iter = 0; iter < resource->size; ++iter) {
+ tchild_rep = things_create_representation_inst(NULL);
+ res->things_get_representation(res, &tRep);
+ tRep->things_get_object_value(tRep, OC_RSRVD_REPRESENTATION, tchild_rep);
+ res->things_set_representation(res, tchild_rep);
+
+ res = res->things_get_next(res);
+ }
+
+ for (int iter = 0; iter < resource->size; ++iter) {
+ child = NULL;
+
+ if (resource->uri == NULL) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Resource URI is NULL.");
+ result = OC_EH_ERROR;
+ goto EXIT_VALIDATION;
+ }
+
+ child = g_builder->get_resource(g_builder, resource->uri);
+
+ if (NULL == child) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Not Existing Child Resource.");
+ result = OC_EH_ERROR;
+ goto EXIT_VALIDATION;
+ }
+ if (NULL == resource->rep) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "things_representation_s is NULL.");
+ result = OC_EH_ERROR;
+ goto EXIT_VALIDATION;
+
+ }
+
+ if (num > 0) {
+ for (int i = 0; i < num; i++) {
+
+ result |= dm_validate_attribute_in_request(resource->things_get_res_type(child, i), (const void *) /*eh_request->payload */resource->rep->payload);
+ if (!result) {
+ goto EXIT_VALIDATION;
+ }
+ }
+ }
+
+ resource = resource->things_get_next(resource);
+
+ // if(targetUri != NULL) things_free(targetUri);
+ }
+ } else {
+ if (num > 0) {
+ for (int iter = 0; iter < num; iter++) {
+ // if it's okey in any case then....it's valid..
+ result |= dm_validate_attribute_in_request(resource->things_get_res_type(resource, iter), (const void *)eh_request->payload);
+ }
+ }
+ }
+ }
+ }
+ }
+
+EXIT_VALIDATION:
+
+ /*! Added by st_things for memory Leak fix
+ */
+ things_release_resource_inst(pst_temp_resource);
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Validation Result.(%d)", result);
+
+ return result;
+}
+
+OCEntityHandlerResult send_response(OCRequestHandle request_handle, OCResourceHandle resource, OCEntityHandlerResult result, const char *uri, void *payload)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+ OCEntityHandlerResult eh_result = OC_EH_OK;
+ OCEntityHandlerResponse response = { 0, 0, OC_EH_ERROR, 0, 0, {}, {0}, false };
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Creating Response with Request Handle : %x,Resource Handle : %x", request_handle, resource);
+
+ response.numSendVendorSpecificHeaderOptions = 0;
+ memset(response.sendVendorSpecificHeaderOptions, 0, sizeof response.sendVendorSpecificHeaderOptions);
+ memset(response.resourceUri, 0, sizeof(response.resourceUri));
+
+ if (NULL != request_handle && NULL != resource) {
+ response.requestHandle = request_handle; //eh_request->request_handle;
+ response.resourceHandle = resource; //eh_request->resource;
+ response.persistentBufferFlag = 0;
+ response.ehResult = result;
+ if (payload != NULL) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Payload is Not NULL");
+ response.payload = (OCPayload *) payload;
+ } else {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "No Payload");
+ response.payload = NULL;
+ }
+
+ THINGS_LOG_V(THINGS_INFO, TAG, "\t\t\tRes. : %s ( %d )", (response.ehResult == OC_EH_OK ? "NORMAL" : "ERROR"), response.ehResult);
+
+ OCStackResult ret = OCDoResponse(&response);
+ THINGS_LOG_V(THINGS_INFO, TAG, "\t\t\tMsg. Out? : (%s)", (ret == OC_STACK_OK) ? "SUCCESS" : "FAIL");
+ if (ret != OC_STACK_OK) {
+ eh_result = OC_EH_ERROR;
+ }
+ } else {
+ eh_result = OC_EH_ERROR;
+ }
+
+ // THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_EXIT);
+ return eh_result;
+}
+
+static bool is_number(char *str)
+{
+ int len = strlen(str);
+ for (int index = 0; index < len; index++) {
+ if (!isdigit(str[index])) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "It's NOT NUMBER : %s", str);
+ return false;
+ }
+ }
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "It is NUMBER : %s", str);
+ return true;
+}
+
+/**
+ * This functions will replace thie ConverAPInfo(~~ )
+ */
+static OCEntityHandlerResult convert_ap_infor(things_resource_s *target_resource, access_point_info_s **p_list, int list_cnt)
+{
+
+ OCEntityHandlerResult eh_result = OC_EH_ERROR;
+
+ things_representation_s *rep = NULL;
+
+ if (!(list_cnt == 0 || p_list == NULL)) {
+
+ if (target_resource->rep == NULL) {
+ rep = things_create_representation_inst(NULL);
+ target_resource->things_set_representation(target_resource, rep);
+ } else {
+ rep = target_resource->rep;
+ }
+
+ things_representation_s **child_rep = (things_representation_s **) things_malloc(list_cnt * sizeof(things_representation_s *));
+
+ for (int iter = 0; iter < list_cnt; iter++) {
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "e_ssid : %s", p_list[iter]->e_ssid);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "security_key : %s", p_list[iter]->security_key);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "auth_type : %s", p_list[iter]->auth_type);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "enc_type : %s", p_list[iter]->enc_type);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "channel : %s", p_list[iter]->channel);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "signal_level : %s", p_list[iter]->signal_level);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "bss_id : %s", p_list[iter]->bss_id);
+
+ child_rep[iter] = things_create_representation_inst(NULL);
+ child_rep[iter]->things_set_value(child_rep[iter], SEC_ATTRIBUTE_AP_CHANNAL, p_list[iter]->channel);
+ child_rep[iter]->things_set_value(child_rep[iter], SEC_ATTRIBUTE_AP_ENCTYPE, p_list[iter]->enc_type);
+ child_rep[iter]->things_set_value(child_rep[iter], SEC_ATTRIBUTE_AP_MACADDR, p_list[iter]->bss_id);
+ child_rep[iter]->things_set_value(child_rep[iter], SEC_ATTRIBUTE_AP_MAXRATE, "MAX_RATE");
+ child_rep[iter]->things_set_value(child_rep[iter], SEC_ATTRIBUTE_AP_RSSI, p_list[iter]->signal_level);
+ child_rep[iter]->things_set_value(child_rep[iter], SEC_ATTRIBUTE_AP_SECTYPE, p_list[iter]->auth_type);
+ child_rep[iter]->things_set_value(child_rep[iter], SEC_ATTRIBUTE_AP_SSID, p_list[iter]->e_ssid);
+ }
+
+ rep->things_set_arrayvalue(rep, SEC_ATTRIBUTE_AP_ITEMS, list_cnt, child_rep);
+
+ for (int iter = 0; iter < list_cnt; iter++) {
+ /*! Changed by st_things for memory Leak fix
+ */
+ things_release_representation_inst(child_rep[iter]);
+ child_rep[iter] = NULL;
+ }
+ things_free(child_rep);
+ child_rep = NULL;
+
+ eh_result = OC_EH_OK;
+ }
+
+ return eh_result;
+}
+
+/**
+ * This functions will be deprecated~!!!
+ */
+static OCEntityHandlerResult get_ap_scan_result(things_resource_s *target_resource)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+
+ OCEntityHandlerResult eh_result = OC_EH_ERROR;
+
+ access_point_info_s **p_list = NULL;
+ int list_cnt = 0;
+ int result = 0;
+
+ // p_list = (access_point_info_s**)things_malloc(sizeof(access_point_info_s*) *MAX_NUM_AP);
+
+ result = things_get_ap_list(&p_list, &list_cnt);
+ if (result) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Get Access points list!!! %d ", list_cnt);
+ if (list_cnt > 0) {
+ //eh_result = ConvertAPInfo(target_resource, p_list, list_cnt);
+ eh_result = convert_ap_infor(target_resource, p_list, list_cnt);
+ } else if (list_cnt == 0) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "0 Access points!!!! %d ", list_cnt);
+ eh_result = OC_EH_OK;
+ } else {
+ eh_result = OC_EH_ERROR;
+ }
+ } else {
+ THINGS_LOG_V(THINGS_ERROR, TAG, "GET AP Searching List FUNC Failed!!!!");
+ }
+
+ if (p_list != NULL) {
+ for (int i = 0; i < list_cnt; i++) {
+ things_free(p_list[i]);
+ }
+ things_free(p_list);
+ }
+
+ return eh_result;
+}
+
+/**
+ * This functions will replace the get_ap_scan_result(~~)
+ */
+static OCEntityHandlerResult get_provisioning_info(things_resource_s *target_resource)
+{
+ OCEntityHandlerResult eh_result = OC_EH_ERROR;
+
+ // if(eh_result == OC_EH_OK)
+ {
+
+ const char *deviceID = OCGetServerInstanceIDString();
+ const char *deviceRT = dm_get_things_device_type(0);
+ bool isOwned = false;
+ bool isReset = things_get_reset_mask(RST_ALL_FLAG);
+ /* if(!isReset) { */
+ /* isReset = 1; */
+ /* } */
+
+ if (OC_STACK_OK != OCGetDeviceOwnedState(&isOwned)) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Failed to get device owned state, Informing as UNOWNED~!!!!");
+ isOwned = false;
+ }
+ if (target_resource->rep == NULL) {
+ /*! Added by st_things for memory Leak fix
+ */
+ things_representation_s *pstRep = NULL;
+ pstRep = things_create_representation_inst(NULL);
+ target_resource->things_set_representation(target_resource, pstRep);
+ }
+
+ things_representation_s *child_rep[1] = { NULL };
+
+ child_rep[0] = things_create_representation_inst(NULL);
+ child_rep[0]->things_set_value(child_rep[0], SEC_ATTRIBUTE_PROV_TARGET_ID, deviceID);
+ child_rep[0]->things_set_value(child_rep[0], SEC_ATTRIBUTE_PROV_TARGET_RT, deviceRT);
+
+ // child_rep[0]->things_set_bool_value(child_rep[0], SEC_ATTRIBUTE_PROV_TARGET_OWNED, isOwned);
+ child_rep[0]->things_set_bool_value(child_rep[0], SEC_ATTRIBUTE_PROV_TARGET_PUBED, dm_is_rsc_published());
+
+ target_resource->rep->things_set_arrayvalue(target_resource->rep, SEC_ATTRIBUTE_PROV_TARGETS, 1, child_rep);
+
+ target_resource->rep->things_set_bool_value(target_resource->rep, SEC_ATTRIBUTE_PROV_TARGET_OWNED, isOwned);
+
+ target_resource->rep->things_set_value(target_resource->rep, SEC_ATTRIBUTE_PROV_EZSETDI, deviceID);
+
+ target_resource->rep->things_set_bool_value(target_resource->rep, SEC_ATTRIBUTE_PROV_RESET, isReset);
+
+ target_resource->rep->things_set_int_value(target_resource->rep, SEC_ATTRIBUTE_PROV_ABORT, 0);
+ /*! Added by st_things for memory Leak fix
+ */
+ if (NULL != child_rep[0]) {
+ things_release_representation_inst(child_rep[0]);
+ }
+
+ eh_result = OC_EH_OK;
+ }
+
+ return eh_result;
+}
+
+static OCEntityHandlerResult trigger_reset_request(things_resource_s *target_resource, bool reset)
+{
+ OCEntityHandlerResult eh_result = OC_EH_ERROR;
+ things_resource_s *clone_resource = NULL;
+ bool isOwned;
+
+ OCGetDeviceOwnedState(&isOwned);
+ if (isOwned == false) {
+ return OC_EH_NOT_ACCEPTABLE;
+ }
+
+ THINGS_LOG_V(THINGS_DEBUG, TAG, "==> RESET : %s", (reset == true ? "YES" : "NO"));
+
+ if (reset == true) {
+ int res = -1;
+
+ clone_resource = clone_resource_inst(target_resource);
+ res = things_reset((void *)clone_resource, RST_NEED_CONFIRM);
+
+ switch (res) {
+ case 1:
+ THINGS_LOG(THINGS_DEBUG, TAG, "Reset Thread create is success.");
+ eh_result = OC_EH_SLOW;
+ break;
+ case 0:
+ THINGS_LOG(THINGS_INFO, TAG, "Already Run Reset-Process.");
+ eh_result = OC_EH_NOT_ACCEPTABLE;
+ default:
+ things_release_resource_inst(clone_resource);
+ clone_resource = NULL;
+ break;
+ }
+ } else {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "reset = %d, So, can not reset start.", reset);
+ eh_result = OC_EH_OK;
+ }
+
+ return eh_result;
+}
+
+static OCEntityHandlerResult trigger_stop_ap_request(things_resource_s *target_resource, bool stop_ap)
+{
+ OCEntityHandlerResult eh_result = OC_EH_ERROR;
+
+ THINGS_LOG_V(THINGS_DEBUG, TAG, "==> STOP SOFT AP : %s", (stop_ap == true ? "YES" : "NO"));
+
+ if (stop_ap == true) {
+ if (NULL != g_stop_soft_ap_cb) {
+ if (1 == g_stop_soft_ap_cb(stop_ap)) {
+ THINGS_LOG_V(THINGS_DEBUG, TAG, "Stop Soft AP notified Successfully");
+ eh_result = OC_EH_OK;
+ } else {
+ THINGS_LOG_V(THINGS_DEBUG, TAG, "Stop Soft AP notified, BUT DENIED");
+ eh_result = OC_EH_ERROR;
+ }
+ }
+ } else {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "stop_ap = %d, So, can not stop AP.", stop_ap);
+ eh_result = OC_EH_OK;
+ }
+
+ return eh_result;
+}
+
+static OCEntityHandlerResult trigger_abort_request(things_resource_s *target_resource, things_es_enrollee_abort_e abort_es)
+{
+ OCEntityHandlerResult eh_result = OC_EH_ERROR;
+ static pthread_t h_thread_abort = NULL;
+// static pthread_t h_thread_abort[4] = {NULL, };
+
+ THINGS_LOG_V(THINGS_DEBUG, TAG, "==> ABORT Easy Setup : %d", abort_es);
+
+ switch (abort_es) {
+ case ABORT_BEFORE_RESET_CONFIRM: // before Reset Confirm.
+ case ABORT_BEFORE_SEC_CONFIRM: // After Reset Confirm & before Security Confirm.
+ case ABORT_BEFORE_DATA_PROVISIONING: // After Security Confirm
+ THINGS_LOG_V(THINGS_DEBUG, TAG, "Forwarding abort-level to st_things App.(Level: %d)", abort_es);
+ eh_result = things_abort(&h_thread_abort, abort_es);
+// eh_result = things_abort(&h_thread_abort[abort_es], abort_es);
+ break;
+ default:
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "abort_es = %d, So, Don't need any-process", abort_es);
+ eh_result = OC_EH_OK;
+ break;
+ }
+
+ return eh_result;
+}
+
+static OCEntityHandlerResult set_provisioning_info(things_resource_s *target_resource)
+{
+ OCEntityHandlerResult eh_result = OC_EH_ERROR;
+
+ bool reset = false;
+ bool stop_ap = false;
+ int64_t abort_es = 0;
+
+ if (target_resource->rep->things_get_bool_value(target_resource->rep, SEC_ATTRIBUTE_PROV_RESET, &reset) == true) {
+ eh_result = trigger_reset_request(target_resource, reset);
+ } else if (target_resource->rep->things_get_bool_value(target_resource->rep, SEC_ATTRIBUTE_PROV_TERMINATE_AP, &stop_ap) == true) {
+ eh_result = trigger_stop_ap_request(target_resource, stop_ap);
+ } else if (target_resource->rep->things_get_int_value(target_resource->rep, SEC_ATTRIBUTE_PROV_ABORT, &abort_es) == true) {
+ eh_result = trigger_abort_request(target_resource, (things_es_enrollee_abort_e) abort_es);
+ } else {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Get Value is failed.(RESET NOR TERMINATE NOR ABORT)");
+ return eh_result;
+ }
+
+ return eh_result;
+}
+
+static OCEntityHandlerResult get_device_or_platform_info_result(things_resource_s *target_resource, char *device_id)
+{
+ OCEntityHandlerResult eh_result = OC_EH_ERROR;
+
+ if (strlen(device_id) > 0 && is_number(device_id)) {
+ int num = atoi(device_id);
+
+ // 1. Get the resource with uri
+ things_resource_s *resource = dm_get_resource_instance(target_resource->uri, num);
+ if (resource) {
+ // 2. Clone the Payload of the resource
+ OCPayloadDestroy((OCPayload *) target_resource->rep->payload);
+ target_resource->rep->payload = NULL;
+ target_resource->rep->payload = OCRepPayloadClone(resource->rep->payload);
+
+ eh_result = OC_EH_OK;
+ }
+ } else {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Invalid Device ID : %s", device_id);
+ }
+
+ return eh_result;
+}
+
+static OCEntityHandlerResult process_post_request(things_resource_s **target_res)
+{
+ OCEntityHandlerResult eh_result = OC_EH_ERROR;
+
+ things_resource_s *target_resource = *target_res;
+
+ if (strstr(target_resource->uri, URI_SEC) != NULL && strstr(target_resource->uri, URI_PROVINFO) != NULL) {
+ // 1. Post request for the Easy-Setup reset
+ eh_result = set_provisioning_info(target_resource);
+ }
+#ifndef __ST_THINGS_RTOS__
+ else if (strstr(target_resource->uri, URI_INFORMATION) != NULL) {
+ // X. Get request for the Access point list(Will be deprecated!!!!)
+ eh_result = SetDeviceInfoResult(target_resource);
+ } else if (strstr(target_resource->uri, URI_ACTIONS) != NULL) {
+ // 2. Post request on the schedule resource
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "#####00 IN process_post_request pQuery : %s", target_resource->query);
+ eh_result = SetActionResource(target_resource);
+ } else if (strstr(target_resource->uri, URI_FILE) != NULL && strstr(target_resource->uri, URI_TRANSFER) != NULL) {
+ // 3. Post request on the sharable file(s) to update the blob data
+ eh_result = SetFileTransferResource(target_resource);
+ } else if (strstr(target_resource->uri, URI_CONTENTS) != NULL && strstr(target_resource->uri, URI_RENDERER) != NULL) {
+ // 4. Post request for the storing Blob data of files
+ eh_result = SetContentsRendererMetadataResult(target_resource);
+ } else if (strstr(target_resource->uri, URI_OIC) != NULL && strstr(target_resource->uri, URI_WK_MAINTENANCE) != NULL) {
+ // 5. Post request for the trigger device maintenance functions
+ eh_result = SetDeviceMaintenanceResult(target_resource);
+ } else if (strstr(target_resource->uri, URI_BIXBY) != NULL) {
+ // 6. Post request for handling bixby request
+ eh_result = SetBixbyRequestResult(target_resource);
+ }
+#endif
+ else {
+#ifndef __ST_THINGS_RTOS__
+ // 7. Post request on the other reosurce(s)
+ int handled = 0;
+ if (NULL != g_handle_res_list) {
+ int iter = 0;
+ for (iter = 0; iter < g_handle_res_cnt; iter++) {
+ if (strstr(target_resource->uri, g_handle_res_list[iter])) {
+ THINGS_LOG_D(THINGS_INFO, TAG, "Handling %s with things_resource_s Based CB", target_resource->uri);
+
+ int ret = g_handle_req_cb(target_resource->req_type, target_resource);
+ if (1 == ret) {
+ eh_result = OC_EH_OK;
+ handled = 1;
+ } else {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "Handled as ERROR from App.");
+ }
+
+ break;
+ }
+ }
+ }
+ if (handled == 0) {
+ THINGS_LOG_D(THINGS_INFO, TAG, "Handling %s with things_info_s Converting Based CB", target_resource->uri);
+
+ eh_result = PostResourceData(target_res);
+ }
+#else
+
+ // Post request for application resources
+ if (g_handle_request_set_cb != NULL) {
+ int ret = g_handle_request_set_cb(target_resource);
+ if (1 == ret) {
+ eh_result = OC_EH_OK;
+ } else {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "Handled as ERROR from App.");
+ }
+ } else {
+ THINGS_LOG_V(THINGS_ERROR, TAG, "g_handle_request_set_cb is not registered");
+ }
+#endif
+ }
+
+ return eh_result;
+}
+
+static OCEntityHandlerResult process_get_request(things_resource_s *target_resource)
+{
+
+ OCEntityHandlerResult eh_result = OC_EH_ERROR;
+
+ char *device_id = NULL;
+
+ device_id = strrchr(target_resource->uri, '/') + 1;
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Get Device ID in Resources URI = %s", device_id);
+
+ things_representation_s *rep = things_create_representation_inst(NULL);
+ target_resource->things_set_representation(target_resource, rep);
+
+ if (strstr(target_resource->uri, URI_SEC) != NULL && strstr(target_resource->uri, URI_PROVINFO) != NULL) {
+ // 1. Get request for the Access point list
+ eh_result = get_provisioning_info(target_resource);
+ }
+#ifndef __ST_THINGS_RTOS__
+ else if (strstr(target_resource->uri, URI_INFORMATION) != NULL) {
+ // X. Get request for the Access point list(Will be deprecated!!!!)
+ eh_result = GetDeviceInfoResult(target_resource);
+ } else if (strstr(target_resource->uri, URI_SEC) != NULL && strstr(target_resource->uri, URI_ACCESSPOINTLIST) != NULL) {
+ // X. Get request for the Access point list(Will be deprecated!!!!)
+ eh_result = get_ap_scan_result(target_resource);
+ } else if (strstr(target_resource->uri, URI_FILE) != NULL && strstr(target_resource->uri, URI_LIST) != NULL) {
+ // 3. Get request for the list of files which can be transfered to the Client
+ eh_result = GetFileListResult(target_resource);
+ } else if (strstr(target_resource->uri, URI_FILE) != NULL && strstr(target_resource->uri, URI_TRANSFER) != NULL) {
+ // 4. Get request for the Blob data of files
+ eh_result = GetFileBlobValueResult(target_resource);
+ } else if (strstr(target_resource->uri, URI_ACTIONS) != NULL) {
+ // 5. Get request for the list of schedules
+ eh_result = GetActionResource(target_resource);
+ } else if ((strstr(target_resource->uri, URI_CONTENTS) != NULL && strstr(target_resource->uri, URI_PROVIDER) != NULL)
+ || (strstr(target_resource->uri, URI_CONTENTS) != NULL && strstr(target_resource->uri, URI_RENDERER) != NULL)
+ ) {
+ // 7. Get request for the Blob data of files
+ eh_result = GetContentsMetadataResult(target_resource);
+ } else if (strstr(target_resource->uri, URI_OIC) != NULL && strstr(target_resource->uri, URI_WK_MAINTENANCE) != NULL) {
+ // 8. Get request for the device maintenance information
+ eh_result = GetDeviceMaintenanceResult(target_resource);
+ }
+#endif
+ else if (strstr(target_resource->uri, URI_SEC) != NULL && strstr(target_resource->uri, URI_ACCESSPOINTLIST) != NULL) {
+ // X. Get request for the Access point list(Will be deprecated!!!!)
+ eh_result = get_ap_scan_result(target_resource);
+ } else if (strstr(target_resource->uri, OC_RSRVD_DEVICE_URI) != NULL || strstr(target_resource->uri, OC_RSRVD_PLATFORM_URI) != NULL) {
+ // 9. Get request for the device maintenance information
+ eh_result = get_device_or_platform_info_result(target_resource, device_id);
+ } else {
+#ifndef __ST_THINGS_RTOS__
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "HELLO WORLD");
+ // 10. Get request on the other resources
+ int handled = 0;
+ if (NULL != g_handle_res_list) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "HELLO WORLD");
+ int iter = 0;
+ for (iter = 0; iter < g_handle_res_cnt; iter++) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "%s : %s ", target_resource->uri, g_handle_res_list[iter]);
+ if (strstr(target_resource->uri, g_handle_res_list[iter])) {
+ THINGS_LOG_D(THINGS_INFO, TAG, "Handling %s with things_resource_s Based CB", target_resource->uri);
+ int ret = g_handle_req_cb(target_resource->req_type, target_resource);
+ if (1 == ret) {
+ eh_result = OC_EH_OK;
+ handled = 1;
+ } else {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "Handled as ERROR from App.");
+ }
+
+ break;
+ }
+ }
+ }
+ if (handled == 0) {
+ THINGS_LOG_D(THINGS_INFO, TAG, "Handling %s with things_info_s Converting Based CB", target_resource->uri);
+
+ eh_result = GetResourceData(target_resource);
+ }
+#else
+ // Post request for application resources
+ if (g_handle_request_get_cb != NULL) {
+ int ret = g_handle_request_get_cb(target_resource);
+ if (1 == ret) {
+ eh_result = OC_EH_OK;
+ } else {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "Handled as ERROR from App.");
+ }
+ } else {
+ THINGS_LOG_V(THINGS_ERROR, TAG, "g_handle_request_get_cb is not registered");
+ }
+#endif
+ }
+
+ return eh_result;
+}
+
+static bool is_can_not_response_case(things_resource_s *target_resource, OCMethod req_type, OCEntityHandlerResult eh_result)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+
+ bool res = false;
+
+ if (target_resource == NULL) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Invalid argument.(target_resource=NULL)");
+ return true;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "target_resource->uri=%s", target_resource->uri);
+ if (strstr(target_resource->uri, URI_SEC) != NULL && strstr(target_resource->uri, URI_PROVINFO) != NULL) {
+ if (req_type == OC_REST_POST && eh_result == OC_EH_SLOW) {
+ res = true;
+ }
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "result = %d", res);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_EXIT);
+ return res;
+}
+
+static void *message_handling_loop(void *param)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+
+ int req_type = -1;
+ // char* uri = NULL;
+ things_resource_s *target_resource = NULL;
+ OCEntityHandlerResult eh_result = OC_EH_ERROR;
+
+ while (!g_quit_flag) {
+ //THINGS_LOG_D(THINGS_INFO, TAG, "[Req.HDLoop] Looping.");
+
+ //while(gOicReqQueue.length(&gOicReqQueue) > 0)
+ while (gp_oic_req_queue->length(gp_oic_req_queue) > 0) {
+ eh_result = OC_EH_ERROR;
+
+ //target_resource = gOicReqQueue.pop(&gOicReqQueue, &req_type);
+ target_resource = gp_oic_req_queue->pop(gp_oic_req_queue, &req_type);
+ if (NULL == target_resource) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Request Item is NULL.");
+ continue;
+ }
+ // RequestInfo* info = CreateRequestInfo(req_type, 0,
+ // target_resource->request_handle,
+ // target_resource->resource_handle);
+
+ // duplicate_string (info->frameId, &target_resource->cmd_id);
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Request Handle : %x, Resource Handle : %x", target_resource->request_handle, target_resource->resource_handle);
+
+ // THINGS_LOG_D(THINGS_DEBUG, TAG, "Request on cmd_id. %s",
+ // target_resource->cmd_id);
+ target_resource->req_type = req_type;
+
+ if (req_type == OC_REST_GET) {
+ THINGS_LOG_V(THINGS_INFO, TAG, "\t\tReq. : GET on %s", target_resource->uri);
+ THINGS_LOG_V(THINGS_INFO, TAG, "\t\tQuery: %s", target_resource->query);
+ eh_result = process_get_request(target_resource);
+
+ } else if (req_type == OC_REST_POST) {
+ THINGS_LOG_V(THINGS_INFO, TAG, "\t\tReq. : POST on %s", target_resource->uri);
+ THINGS_LOG_V(THINGS_INFO, TAG, "\t\tQuery: %s", target_resource->query);
+ eh_result = process_post_request(&target_resource);
+ } else {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, " Invalid Request Received : %d", req_type);
+ }
+ THINGS_LOG_D(THINGS_DEBUG, TAG, " @@@@@ target_resource ->size : %d", target_resource->size);
+ // THINGS_LOG_D(THINGS_DEBUG, TAG, " @@@@@ target_resource ->cmd_id : %s", target_resource->cmd_id);
+
+ if (is_can_not_response_case(target_resource, req_type, eh_result) == false) {
+ if (eh_result != OC_EH_OK && eh_result != OC_EH_SLOW) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Handing Request Failed, Sending ERROR Response");
+
+ things_resource_s *temp = g_builder->get_resource(g_builder, target_resource->uri);
+ const char *rt = temp->things_get_res_type(temp, 0);
+ if (0 == strncmp(rt, SEC_RTYPE_TEMPERATURE, strlen(SEC_RTYPE_TEMPERATURE)) || 0 == strncmp(rt, OIC_RTYPE_TEMPERATURE, strlen(OIC_RTYPE_TEMPERATURE))) {
+ OCRepPayload *rep_payload = target_resource->things_get_rep_payload(target_resource);
+ send_response(target_resource->request_handle, target_resource->resource_handle, OC_EH_ERROR, target_resource->uri, rep_payload);
+ } else {
+ send_response(target_resource->request_handle, target_resource->resource_handle, eh_result, target_resource->uri, NULL);
+ }
+ } else {
+ OCRepPayload *rep_payload = target_resource->things_get_rep_payload(target_resource);
+
+ eh_result = send_response(target_resource->request_handle, // reqInfo->reqHandle,
+ target_resource->resource_handle, // reqInfo->resHandle,
+ target_resource->error, target_resource->uri, rep_payload);
+
+ /*! Added by st_things for memory Leak fix
+ */
+ //if(OC_EH_ERROR == eh_result)
+ //{
+ OCPayloadDestroy((OCPayload *) rep_payload);
+ rep_payload = NULL;
+ //}
+ }
+ }
+ // Need to design How to release memory allocated for the things_resource_s list.
+ things_release_resource_inst(target_resource);
+
+ usleep(100 * 1000);
+ } // End Of While Loop
+
+ things_control_queue_empty();
+
+ usleep(100 * 1000);
+ } // End Of While Loop
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[Req.HDLoop] Leaving loop...");
+
+ return NULL;
+}
+
+void notify_result_of_reset(things_resource_s *target_resource, bool result)
+{
+ THINGS_LOG(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+
+ OCEntityHandlerResult eh_result = OC_EH_ERROR;
+
+ if (target_resource == NULL) {
+ THINGS_LOG(THINGS_DEBUG, TAG, "Not exist remote-client.");
+ return;
+ }
+
+ if (result == true) { // reset Success.
+ OCRepPayload *rep_payload = target_resource->things_get_rep_payload(target_resource);
+
+ eh_result = send_response(target_resource->request_handle, // reqInfo->reqHandle,
+ target_resource->resource_handle, // reqInfo->resHandle,
+ target_resource->error, target_resource->uri, rep_payload);
+
+ /*! Added by st_things for memory Leak fix
+ */
+// if(OC_EH_ERROR == eh_result)
+// {
+ OCPayloadDestroy((OCPayload *) rep_payload);
+ rep_payload = NULL;
+// }
+ } else {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Handing Request Failed, Sending ERROR Response");
+
+ send_response(target_resource->request_handle, target_resource->resource_handle, eh_result, target_resource->uri, NULL);
+ }
+
+ things_release_resource_inst(target_resource);
+
+ THINGS_LOG(THINGS_DEBUG, TAG, THINGS_FUNC_EXIT);
+}
+
+int notify_things_observers(const char *uri, const char *query)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+
+ int res = 0;
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "uri = %s", uri);
+ if (NULL != uri) {
+ int remainLen = MAX_RESOURCE_LEN - 1;
+ char tempUri[MAX_RESOURCE_LEN] = { 0 };
+
+ if (NULL != g_get_notify_obs_uri) {
+ char *temp = g_get_notify_obs_uri(uri, query);
+ if (NULL != temp) {
+ things_strncpy(tempUri, temp, remainLen);
+ remainLen -= strnlen(tempUri, MAX_RESOURCE_LEN - 1);
+ things_free(temp);
+ }
+ }
+
+ if (strnlen(tempUri, MAX_RESOURCE_LEN - 1) < 1) {
+ things_strncpy(tempUri, uri, remainLen);
+ remainLen -= strnlen(tempUri, MAX_RESOURCE_LEN - 1);
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "%s resource notifies to observers.", tempUri);
+
+ for (int iter = 0; iter < g_builder->res_num; iter++) {
+ if (strstr(g_builder->gres_arr[iter]->uri, tempUri) != NULL) {
+ OCStackResult ret2 = OCNotifyAllObservers((OCResourceHandle) g_builder->gres_arr[iter]->resource_handle,
+ OC_MEDIUM_QOS);
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "%s resource has notified to observers.", g_builder->gres_arr[iter]->uri);
+
+ if (OC_STACK_OK == ret2) {
+ THINGS_LOG(THINGS_INFO, TAG, "Success: Sent notification to Observers");
+ } else {
+ THINGS_LOG_D(THINGS_INFO, TAG, "Failed: No Observers to notify : %d ", ret2);
+ }
+ res = 1;
+ break;
+ }
+ }
+
+#ifndef __ST_THINGS_RTOS__
+ // if(res)
+ {
+ // Need to refactor later support the number bigger then 9
+ char *device_num = strrchr(uri, '/');
+ char res_uri[128] = { 0 };
+
+ memset(res_uri, 0, (size_t) 128);
+ strncat(res_uri, URI_DEVICE_COL, strlen(URI_DEVICE_COL));
+ strncat(res_uri, device_num, strlen(device_num));
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Target Collection URI : %s", res_uri);
+
+ things_resource_s *temp = g_builder->get_resource(g_builder, res_uri);
+ if (temp) {
+ OCStackResult ret3 = OCNotifyAllObservers((OCResourceHandle) temp->resource_handle,
+ OC_MEDIUM_QOS);
+
+ if (OC_STACK_OK == ret3) {
+ THINGS_LOG(THINGS_INFO, TAG, "Sent notification to Observers");
+ } else {
+ THINGS_LOG_D(THINGS_INFO, TAG, "No Observers to notify : %d ", ret3);
+ }
+ }
+ }
+#endif
+
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_EXIT);
+ return res;
+}
+
+OCEntityHandlerResult handle_message(things_resource_s *target_resource)
+{
+ OCEntityHandlerResult eh_result = OC_EH_ERROR;
+
+ if (NULL == target_resource) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Request Item is NULL.");
+ return OC_EH_ERROR;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Request Handle : %x, Resource Handle : %x", target_resource->request_handle, target_resource->resource_handle);
+
+ // THINGS_LOG_D(THINGS_DEBUG, TAG, "Request on cmd_id. %s",
+ // target_resource->cmd_id);
+
+ if (target_resource->req_type == OC_REST_GET) {
+ THINGS_LOG_V(THINGS_INFO, TAG, "\t\tReq. : GET on %s", target_resource->uri);
+ THINGS_LOG_V(THINGS_INFO, TAG, "\t\tQuery: %s", target_resource->query);
+ eh_result = process_get_request(target_resource);
+
+ } else if (target_resource->req_type == OC_REST_POST) {
+ THINGS_LOG_V(THINGS_INFO, TAG, "\t\tReq. : POST on %s", target_resource->uri);
+ THINGS_LOG_V(THINGS_INFO, TAG, "\t\tQuery: %s", target_resource->query);
+ eh_result = process_post_request(&target_resource);
+ } else {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, " Invalid Request Received : %d", target_resource->req_type);
+ }
+ THINGS_LOG_D(THINGS_DEBUG, TAG, " @@@@@ target_resource ->size : %d", target_resource->size);
+ // THINGS_LOG_D(THINGS_DEBUG, TAG, " @@@@@ target_resource ->cmd_id : %s", target_resource->cmd_id);
+
+ if (is_can_not_response_case(target_resource, target_resource->req_type, eh_result) == false) {
+ if (eh_result != OC_EH_OK && eh_result != OC_EH_SLOW) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Handing Request Failed, Sending ERROR Response");
+
+ things_resource_s *temp = g_builder->get_resource(g_builder, target_resource->uri);
+ const char *rt = temp->things_get_res_type(temp, 0);
+ if (0 == strncmp(rt, SEC_RTYPE_TEMPERATURE, strlen(SEC_RTYPE_TEMPERATURE)) || 0 == strncmp(rt, OIC_RTYPE_TEMPERATURE, strlen(OIC_RTYPE_TEMPERATURE))) {
+ OCRepPayload *rep_payload = target_resource->things_get_rep_payload(target_resource);
+ send_response(target_resource->request_handle, target_resource->resource_handle, OC_EH_ERROR, target_resource->uri, rep_payload);
+ } else {
+ send_response(target_resource->request_handle, target_resource->resource_handle, eh_result, target_resource->uri, NULL);
+ }
+ eh_result = OC_EH_OK;
+ } else {
+ OCRepPayload *rep_payload = target_resource->things_get_rep_payload(target_resource);
+
+ eh_result = send_response(target_resource->request_handle, // reqInfo->reqHandle,
+ target_resource->resource_handle, // reqInfo->resHandle,
+ target_resource->error, target_resource->uri, rep_payload);
+
+ /*! Added by st_things for memory Leak fix
+ */
+ //if(OC_EH_ERROR == eh_result)
+ //{
+ OCPayloadDestroy((OCPayload *) rep_payload);
+ rep_payload = NULL;
+ //}
+ }
+ }
+ // Need to design How to release memory allocated for the things_resource_s list.
+ things_release_resource_inst(target_resource);
+
+ return eh_result;
+}
+
+OCEntityHandlerResult entity_handler(OCEntityHandlerFlag flag, OCEntityHandlerRequest *entity_handler_request, void *callback)
+{
+ THINGS_LOG_D(THINGS_INFO, TAG, THINGS_FUNC_ENTRY);
+ OCEntityHandlerResult eh_result = OC_EH_ERROR;
+
+ // Validate pointer
+ if (!entity_handler_request) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Invalid request pointer");
+ return eh_result;
+ }
+
+ const char *uri = OCGetResourceUri(entity_handler_request->resource);
+
+ // Observe Request Handling
+ if (flag & OC_OBSERVE_FLAG) {
+ if (OC_OBSERVE_REGISTER == entity_handler_request->obsInfo.action) {
+ THINGS_LOG_V(THINGS_INFO, TAG, "Observe Requset on : %s ", uri);
+ // 1. Check whether it's Observe request on the Collection Resource
+ if (NULL != strstr(uri, URI_DEVICE_COL)) {
+ //2. Check whether the query carriese the if=oic.if.b
+ if ((strstr(entity_handler_request->query, OIC_INTERFACE_BATCH) == NULL)) {
+ //3. If not batch then error
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Collection Resource Requires BATCH for Observing : %s", entity_handler_request->query);
+ eh_result = OC_EH_BAD_REQ;
+ goto RESPONSE_ERROR;
+ } else {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Receiving Observe Request Collection Resource");
+ }
+ }
+ } else if (OC_OBSERVE_DEREGISTER == entity_handler_request->obsInfo.action) {
+ THINGS_LOG_V(THINGS_INFO, TAG, "CancelObserve Request on : %s", uri);
+ }
+ }
+ // Get/Post Request Handling
+ if (flag & OC_REQUEST_FLAG) {
+ THINGS_LOG_D(THINGS_INFO, TAG, "Req. URI : %s", uri);
+ THINGS_LOG_D(THINGS_INFO, TAG, "Req. TYPE : %d", entity_handler_request->method);
+
+ if (things_get_reset_mask(RST_CONTROL_MODULE_DISABLE) == true) {
+ THINGS_LOG(THINGS_INFO, TAG, "Control Module Disable.");
+ eh_result = OC_EH_NOT_ACCEPTABLE;
+ } else if ((OC_REST_GET == entity_handler_request->method)
+ || (OC_REST_POST == entity_handler_request->method)) {
+ THINGS_LOG_D(THINGS_INFO, TAG, "Request Handle : %x, Resource Handle : %x", entity_handler_request->requestHandle, entity_handler_request->resource);
+ if (verify_request(entity_handler_request, uri, (int)entity_handler_request->method) > 0) {
+ // IoTivity Stack Destroy the payload after receving result from this function
+ // Therefore, we need to copy/clone the payload for the later use..
+ things_resource_s *resource = things_create_resource_inst(entity_handler_request->requestHandle,
+ entity_handler_request->resource,
+ entity_handler_request->query,
+ entity_handler_request->payload);
+ resource->things_set_dev_addr(resource, &(entity_handler_request->devAddr));
+ resource->req_type = entity_handler_request->method;
+ //resource->set_uri(resource, uri);
+
+// THINGS_LOG_D(THINGS_DEBUG, TAG, "About to Queue a received Request~!!!!");
+//
+// //gOicReqQueue.push(&gOicReqQueue, resource, entity_handler_request->method);
+// gp_oic_req_queue->push(gp_oic_req_queue, resource, entity_handler_request->method);
+// eh_result = OC_EH_SLOW;
+ eh_result = handle_message(resource);
+ } else {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Invalid Query in the Request : %s", entity_handler_request->query);
+ }
+ } else if (OC_REST_DELETE == entity_handler_request->method || OC_REST_PUT == entity_handler_request->method) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Delete/PUT Req. Handling is not supported Yet");
+ } else {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Received unsupported method from client");
+ }
+
+ }
+
+RESPONSE_ERROR:
+
+ if (eh_result != OC_EH_SLOW && eh_result != OC_EH_OK) {
+ // If the result is OC_EH_ERROR, the stack will remove the
+ // received request in the stack.
+ // If the reusult is OC_EH_SLOW, then the request will be
+ // stored in the stack till the response goes out
+ eh_result = send_response(entity_handler_request->requestHandle, entity_handler_request->resource, eh_result, uri, NULL);
+ // Currently this code will not do anything...
+ // Need to refactor later..
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_EXIT);
+
+ return eh_result;
+}
+
+void init_handler()
+{
+ g_quit_flag = false;
+
+//#ifdef __ST_THINGS_RTOS__
+// pthread_create_rtos(&g_req_handle, NULL, message_handling_loop, (void *)NULL, THINGS_STACK_MESSAGE_HANDLING_THREAD);
+//#else
+// things_thread_create (&g_req_handle, NULL, message_handling_loop, (void *)NULL);
+//#endif
+
+}
+
+void deinit_handler()
+{
+ g_quit_flag = true;
+
+ int iter = 0;
+ if (g_handle_res_list != NULL) {
+ for (iter = 0; iter < g_handle_res_cnt; iter++) {
+ if (g_handle_res_list[iter] != NULL) {
+ things_free(g_handle_res_list[iter]);
+ g_handle_res_list[iter] = NULL;
+ }
+ }
+ things_free(g_handle_res_list);
+ g_handle_res_list = NULL;
+ }
+ g_handle_res_cnt = 0;
+}
+
+struct things_request_handler_s *get_handler_instance()
+{
+ struct things_request_handler_s *handler = (things_request_handler_s *) things_malloc(sizeof(things_request_handler_s));
+
+ if (handler == NULL) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Not Enough Memory");
+ return NULL;
+ } else {
+ handler->entity_handler = &entity_handler;
+ handler->init_module = &init_handler;
+ handler->deinit_module = &deinit_handler;
+ handler->notify_things_observers = ¬ify_things_observers;
+ return handler;
+ }
+}
+
+void release_handler_instance(struct things_request_handler_s *handler)
+{
+ if (handler) {
+ handler->deinit_module();
+ things_free(handler);
+ }
+}
+
+int register_stop_softap_cb(stop_softap_func_type func)
+{
+ if (NULL != func) {
+ g_stop_soft_ap_cb = func;
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+int register_handle_request_func(handle_request_func_type get_func, handle_request_func_type set_func)
+{
+ if (NULL != get_func && NULL != set_func) {
+ g_handle_request_get_cb = get_func;
+ g_handle_request_set_cb = set_func;
+ } else {
+ return 0;
+ }
+ return 1;
+}
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 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.
+ *
+ ****************************************************************************/
+
+#define _POSIX_C_SOURCE 200809L
+#define _BSD_SOURCE
+#include <string.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <pthread.h>
+
+#include "things_def.h"
+#include "things_common.h"
+#include "things_logger.h"
+#include "things_malloc.h"
+#include "things_string_util.h"
+#include "oic_malloc.h"
+#include "ocpayload.h"
+#include "things_resource.h"
+#include "octypes.h"
+
+#define TAG "[things_resource]"
+
+//#*******************************************************************************//
+//# Function definitions for the THINGS Resources.
+//#*******************************************************************************//
+
+void set_dev_addr(struct things_resource_s *p_res, void *dev_addr)
+{
+ if (dev_addr == NULL) {
+ p_res->dev_addr = NULL;
+ return;
+ }
+ (p_res->dev_addr) = (OCDevAddr *) things_malloc(sizeof(OCDevAddr));
+ if (NULL != p_res->dev_addr) {
+ memcpy((p_res->dev_addr), dev_addr, sizeof(OCDevAddr));
+ }
+ // p_res->dev_addr = dev_addr;
+}
+
+void *get_dev_addr(struct things_resource_s *p_res)
+{
+ return (p_res->dev_addr);
+}
+
+void set_uri(struct things_resource_s *res, const char *key)
+{
+ //THINGS_LOG_V(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+
+ if (key == NULL) {
+ return;
+ }
+
+ if (res->uri != NULL) {
+ things_free(res->uri);
+ res->uri = NULL;
+ }
+ res->uri = (char *)things_malloc(sizeof(char) *strlen(key) + 1);
+ memset(res->uri, 0, strlen(key) + 1);
+ things_strncpy(res->uri, key, strlen(key) + 1);
+
+ if (NULL != res->rep) {
+ OCRepPayloadSetUri(res->rep->payload, key);
+ } else {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Set URI Failed, No Representation Yet");
+ }
+
+ //THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_EXIT);
+}
+
+void set_error(struct things_resource_s *res, double error)
+{
+ res->error = error;
+}
+
+void things_set_value(struct things_representation_s *rep, char *key, char *value)
+{
+#ifdef __ST_THINGS_RTOS__
+ if (value != NULL && key != NULL) {
+ OCRepPayloadSetPropString(rep->payload, key, value);
+ }
+#else
+ OCRepPayloadSetPropString(rep->payload, key, value);
+#endif
+}
+
+void things_set_bool_value(struct things_representation_s *rep, char *key, bool value)
+{
+ OCRepPayloadSetPropBool(rep->payload, key, value);
+}
+
+void things_set_int_value(struct things_representation_s *rep, char *key, int64_t value)
+{
+ OCRepPayloadSetPropInt(rep->payload, key, value);
+}
+
+void things_set_double_value(struct things_representation_s *rep, char *key, double value)
+{
+ OCRepPayloadSetPropDouble(rep->payload, key, value);
+}
+
+void things_set_byte_value(struct things_representation_s *rep, char *key, uint8_t *value, size_t size)
+{
+ OCByteString b_val = { value, size };
+
+ if (b_val.len < 1) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "No byte value to Set");
+ } else {
+ OCRepPayloadSetPropByteString(rep->payload, key, b_val);
+ }
+}
+
+bool things_set_object_value(struct things_representation_s *mother, char *key, struct things_representation_s *child)
+{
+ return OCRepPayloadSetPropObject(mother->payload, key, child->payload);
+}
+
+static OCRepPayloadValue *things_rep_payload_find_values(const OCRepPayload *payload, const char *name)
+{
+ if (!payload || !name) {
+ return NULL;
+ }
+
+ OCRepPayloadValue *val = payload->values;
+ while (val) {
+ if (0 == strncmp(val->name, name, strlen(name))) {
+ return val;
+ }
+ val = val->next;
+ }
+
+ return NULL;
+}
+
+bool things_set_arrayvalue(struct things_representation_s *mother, char *key, int length, struct things_representation_s **children)
+{
+ bool things_set_value = false;
+ if (length < 1) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "DATA LENGTH IS ZERO!!!!!!");
+ return things_set_value;
+ }
+ size_t dimensions[MAX_REP_ARRAY_DEPTH] = { length, 0, 0 };
+
+ OCRepPayload *payloads[length];
+
+ for (int iter = 0; iter < length; iter++) {
+ payloads[iter] = children[iter]->payload;
+ }
+ // This is codesnippet for creating Array type of value inside the payload..
+ things_set_value = OCRepPayloadSetPropObjectArray(mother->payload, key, (const OCRepPayload **)(payloads), dimensions);
+
+ // THINGS_LOG_V(THINGS_INFO, TAG, " Length : %d", length);
+ // OCRepPayloadSetPropInt(mother->payload, SEC_ATTRIBUTE_LENGTH, length);
+
+ // Do we need to have those children representation
+ // with this resource instance????
+ return things_set_value;
+}
+
+bool things_get_arrayvalue(struct things_representation_s *mother, char *key, int *length, struct things_representation_s ***children)
+{
+ //THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "NOt Supported This Function Yet");
+ bool find_value = false;
+ THINGS_LOG_V(THINGS_DEBUG, TAG, "There're (%d) Number of children resources in the Payload : %d", mother->num_children);
+
+ // if( OCRepPayloadGetPropInt((OCRepPayload*)(mother->payload), SEC_ATTRIBUTE_LENGTH, &(mother->num_children) ) )
+ OCRepPayloadValue *payload_value = things_rep_payload_find_values((OCRepPayload *)(mother->payload), key);
+ if (NULL != payload_value) {
+ OCRepPayload **payload_values = NULL;
+ size_t dimension_size = calcDimTotal(payload_value->arr.dimensions);
+ size_t dimensions[3] = { dimension_size, 0, 0 };
+
+ THINGS_LOG_V(THINGS_DEBUG, TAG, "Dimension size in the Payload : %d", dimension_size);
+ // This is testing code only... will be removed...
+ find_value = OCRepPayloadGetPropObjectArray((OCRepPayload *)(mother->payload), key, &payload_values, dimensions);
+ THINGS_LOG_V(THINGS_DEBUG, TAG, "Find Value : %d", find_value);
+ if (find_value) {
+ *children = (things_representation_s **) things_malloc(sizeof(things_representation_s *) *dimension_size);
+
+ for (int iter = 0; iter < dimension_size; iter++) {
+ (*children)[iter] = things_create_representation_inst(payload_values[iter]);
+ /*! Added by st_things for memory Leak fix
+ */
+ OCRepPayloadDestroy(payload_values[iter]);
+ }
+ /*! Added by st_things for memory Leak fix
+ */
+ OICFree(payload_values);
+ *length = mother->num_children = dimension_size;
+ }
+ } else {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "DATA NOT EXIST~!!!!");
+ }
+
+ return find_value;
+}
+
+void things_set_string_arrayvalue(struct things_representation_s *mother, char *key, int length, char **array)
+{
+ if (length < 1) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "DATA LENGTH IS ZERO!!!!!!");
+ return;
+ }
+ size_t dimensions[MAX_REP_ARRAY_DEPTH] = { length, 0, 0 };
+
+ // This is codesnippet for creating Array type of value inside the payload..
+ OCRepPayloadSetStringArray(mother->payload, key, (const char **)array, dimensions);
+}
+
+bool things_get_string_arrayvalue(struct things_representation_s *mother, char *key, int *length, char ***array)
+{
+ THINGS_LOG_V(THINGS_DEBUG, TAG, "There're (%d) Number of children resources in the Payload : %d", mother->num_children);
+
+ bool find_value = false;
+
+ OCRepPayloadValue *payload_value = NULL;
+
+ payload_value = things_rep_payload_find_values((OCRepPayload *)(mother->payload), key);
+
+ if (payload_value != NULL) {
+ size_t dimension_size = calcDimTotal(payload_value->arr.dimensions);
+ size_t dimensions[3] = { dimension_size, 0, 0 };
+
+ find_value = OCRepPayloadGetStringArray((OCRepPayload *)(mother->payload), key, array, dimensions);
+ THINGS_LOG_V(THINGS_DEBUG, TAG, "Find Value : %d", find_value);
+ if (find_value) {
+
+ *length = dimension_size;
+ }
+ } else {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "DATA NOT EXIST~!!!!");
+ }
+
+ return find_value;
+}
+
+void things_set_double_arrayvalue(struct things_representation_s *mother, char *key, int length, double *array)
+{
+ if (length < 1) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "DATA LENGTH IS ZERO!!!!!!");
+ return;
+ }
+ size_t dimensions[MAX_REP_ARRAY_DEPTH] = { length, 0, 0 };
+
+ OCRepPayloadSetDoubleArray(mother->payload, key, array, dimensions);
+}
+
+bool things_get_double_arrayvalue(struct things_representation_s *mother, char *key, int *length, double **array)
+{
+ bool find_value = false;
+
+ OCRepPayloadValue *payload_value = things_rep_payload_find_values((OCRepPayload *)(mother->payload), key);
+ if (NULL != payload_value) {
+
+ size_t dimension_size = calcDimTotal(payload_value->arr.dimensions);
+ size_t dimensions[3] = { dimension_size, 0, 0 };
+
+ THINGS_LOG_V(THINGS_DEBUG, TAG, "Dimension size in the Payload : %d", dimension_size);
+
+ find_value = OCRepPayloadGetDoubleArray((OCRepPayload *)(mother->payload), key, array, dimensions);
+
+ THINGS_LOG_V(THINGS_DEBUG, TAG, "Find Value : %d", find_value);
+ if (find_value) {
+ *length = dimension_size;
+ }
+ } else {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "DATA NOT EXIST~!!!!");
+ }
+
+ return find_value;
+}
+
+void things_set_int_arrayvalue(struct things_representation_s *mother, char *key, int length, int64_t *array)
+{
+ if (length < 1) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "DATA LENGTH IS ZERO!!!!!!");
+ return;
+ }
+ size_t dimensions[MAX_REP_ARRAY_DEPTH] = { length, 0, 0 };
+
+ OCRepPayloadSetIntArray(mother->payload, key, array, dimensions);
+}
+
+bool things_get_int_arrayvalue(struct things_representation_s *mother, char *key, int *length, int64_t **array)
+{
+ bool find_value = false;
+
+ OCRepPayloadValue *payload_value = things_rep_payload_find_values((OCRepPayload *)(mother->payload), key);
+
+ if (NULL != payload_value) {
+ size_t dimension_size = calcDimTotal(payload_value->arr.dimensions);
+ size_t dimensions[3] = { dimension_size, 0, 0 };
+
+ THINGS_LOG_V(THINGS_DEBUG, TAG, "Dimension size in the Payload : %d", dimension_size);
+
+ find_value = OCRepPayloadGetIntArray((OCRepPayload *)(mother->payload), key, array, dimensions);
+
+ THINGS_LOG_V(THINGS_DEBUG, TAG, "Find Value : %d", find_value);
+ if (find_value) {
+ *length = dimension_size;
+ }
+ } else {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "DATA NOT EXIST~!!!!");
+ }
+ return find_value;
+}
+
+void set_representation(struct things_resource_s *res, struct things_representation_s *rep)
+{
+ if (res->rep) {
+ things_release_representation_inst(res->rep);
+ res->rep = NULL;
+ }
+ res->rep = rep;
+}
+
+// Getter should be refactored to deliver the request value as its return
+// not through the inserted param.
+void get_uri(struct things_resource_s *res, char **value)
+{
+ if (res->uri != NULL) {
+ *value = (char *)things_malloc(sizeof(char) *strlen(res->uri) + 1);
+ memset(*value, 0, strlen(res->uri) + 1);
+ things_strncpy(*value, res->uri, strlen(res->uri) + 1);
+ }
+}
+
+int get_num_of_res_types(struct things_resource_s *res)
+{
+ uint8_t num = 0;
+ OCGetNumberOfResourceTypes((OCResourceHandle) res->resource_handle, &num);
+ return (int)num;
+}
+
+const char *get_res_type(struct things_resource_s *res, int index)
+{
+ const char *resourcType = OCGetResourceTypeName((OCResourceHandle) res->resource_handle, index);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "=====> RH : %x cnt : %d", res->resource_handle, index);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "=====> RT : %s ", resourcType);
+
+ return resourcType;
+}
+
+int get_num_of_inf_types(struct things_resource_s *res)
+{
+ uint8_t num = 0;
+ OCGetNumberOfResourceInterfaces((OCResourceHandle) res->resource_handle, &num);
+ return (int)num;
+}
+
+const char *get_inf_type(struct things_resource_s *res, int index)
+{
+ const char *interface_type = OCGetResourceInterfaceName((OCResourceHandle) res->resource_handle, index);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "=====> RH : %x cnt : %d", res->resource_handle, index);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "=====> IT : %s ", interface_type);
+
+ return interface_type;
+}
+
+bool things_get_value(struct things_representation_s *rep, char *key, char **value)
+{
+ return OCRepPayloadGetPropString((OCRepPayload *) rep->payload, key, (char **)value);
+}
+
+bool things_get_bool_value(struct things_representation_s *rep, char *key, bool *value)
+{
+ return OCRepPayloadGetPropBool((OCRepPayload *) rep->payload, key, value);
+}
+
+bool things_get_int_value(struct things_representation_s *rep, char *key, int64_t *value)
+{
+ return OCRepPayloadGetPropInt((OCRepPayload *) rep->payload, key, value);
+}
+
+bool things_get_double_value(struct things_representation_s *rep, char *key, double *value)
+{
+ return OCRepPayloadGetPropDouble((OCRepPayload *) rep->payload, key, value);
+}
+
+bool things_get_byte_value(struct things_representation_s *rep, char *key, uint8_t **value, size_t *size)
+{
+ OCByteString b_val = { NULL, 0 };
+ bool ret = OCRepPayloadGetPropByteString((OCRepPayload *) rep->payload, key, &b_val);
+
+ if (true == ret) {
+ (*size) = b_val.len;
+ (*value) = (uint8_t *) things_malloc((*size) + 1);
+ memcpy((*value), b_val.bytes, b_val.len);
+
+ if (b_val.bytes != NULL) {
+ things_free(b_val.bytes);
+ b_val.bytes = NULL;
+ }
+ }
+
+ return ret;
+}
+
+bool things_get_object_value(struct things_representation_s *mother, char *key, struct things_representation_s *child)
+{
+ OCRepPayload *payload = NULL;
+ bool ret = OCRepPayloadGetPropObject(mother->payload, key, &payload);
+
+ if (true == ret && NULL != payload) {
+ if (child->payload) {
+ OCRepPayloadDestroy(child->payload);
+ child->payload = NULL;
+ }
+ child->payload = payload;
+ }
+ return ret;
+}
+
+bool get_query(struct things_resource_s *res, char *key, char **value)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+
+ if (NULL == key) {
+ return 0;
+ } else if (NULL == res) {
+ return 0;
+ } else if (NULL == res->query) {
+ return 0;
+ } else if (strlen(res->query) < 1) {
+ return 0;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Query is %s.", res->query);
+
+ *value = NULL;
+
+ char *p_buff = NULL, *p_origin = NULL;
+ char *p_ptr = NULL;
+ char *p_ptr2 = NULL;
+
+ p_origin = p_buff = (char *)things_malloc(strlen(res->query) + 1);
+
+ if (NULL == p_buff || NULL == p_origin) {
+ return 0;
+ }
+
+ memset(p_buff, 0, strlen(res->query) + 1);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "p_buff is initialized by 0.");
+ memcpy(p_buff, res->query, strlen(res->query));
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "p_buff is Initialized as", res->query);
+
+ p_ptr = strtok(p_buff, QUERY_DELIMITER);
+ if (p_ptr != NULL) {
+ p_ptr2 = p_ptr;
+ } else {
+ things_free(p_origin);
+ return 0;
+ }
+ //while (p_ptr != NULL)
+ while (p_ptr2 != NULL) {
+ if (strncmp(p_ptr2, key, strlen(key)) == 0) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "\tFind Query : %s", p_ptr2 + strlen(key) + 1);
+
+ duplicate_string(p_ptr2 + strlen(key) + 1, value);
+ if (NULL == *value) {
+ things_free(p_origin);
+ return 1;
+ }
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "\tRESULT : %s", *value);
+ break;
+ }
+
+ p_ptr2 = strtok(NULL, QUERY_DELIMITER);
+ }
+
+ things_free(p_origin);
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_EXIT);
+
+ return 1;
+}
+
+struct things_resource_s *get_children(struct things_resource_s *pParent)
+{
+ return pParent->next;
+}
+
+bool get_representation(struct things_resource_s *res, struct things_representation_s **rep)
+{
+ if (res->rep != NULL) {
+ *rep = res->rep;
+ return true;
+ }
+
+ return false;
+}
+
+void /*OCRepPayload */ *create_payload(struct things_resource_s *res, char *query)
+{
+ // To provide identical pattern for handling the result
+ // allocating new memory for the payload to delete later
+ OCRepPayload *payload = OCRepPayloadClone((OCRepPayload *)(res->rep->payload));
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Query : %s", query);
+
+ if (query == NULL || (query != NULL && strlen(query) < 1)
+ || strstr(query, OIC_INTERFACE_ACTUATOR) != NULL || strstr(query, OIC_INTERFACE_SENSOR) != NULL) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Including properties & its values only");
+ // Do nothing..
+ } else if (strstr(query, OIC_INTERFACE_BASELINE)) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Including all the properties & its values");
+
+ uint8_t index = 0;
+ uint8_t number_of_interfaces = 0;
+ uint8_t number_of_resource_type = 0;
+
+ OCGetNumberOfResourceInterfaces((OCResourceHandle) res->resource_handle, &number_of_interfaces);
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "@@ IF # : %d ", number_of_interfaces);
+ //2.a Find interface type(s) & insert it/them into payload
+ for (index = 0; index < number_of_interfaces; index++) {
+ const char *interface = OCGetResourceInterfaceName((OCResourceHandle) res->resource_handle, index);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "=====> IF : %s ", interface);
+ OCRepPayloadAddInterface(payload, interface);
+ }
+
+ //3.a Find resource type & insert it into payload
+ OCGetNumberOfResourceTypes((OCResourceHandle) res->resource_handle, &number_of_resource_type);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "@@ RT # : %d ", number_of_resource_type);
+ for (index = 0; index < number_of_resource_type; index++) {
+ const char *rt = OCGetResourceTypeName((OCResourceHandle) res->resource_handle, index);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "=====> RT : %s ", rt);
+ OCRepPayloadAddResourceType(payload, rt);
+ }
+ } else if (strstr(query, OC_RSRVD_INTERFACE_BATCH)) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Batch only supported by Collection Resource");
+ } else if (strstr(query, OC_RSRVD_INTERFACE_LL)) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Link-List only supported by Collection Resource");
+ } else {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Not supporting Interface type : %s", query);
+ }
+
+ return payload;
+}
+
+void /*OCRepPayload */ *get_rep_payload(struct things_resource_s *res)
+{
+ if (res->rep != NULL) {
+ // Create Payload for the mother resource
+ // It applies not only single resource but also the collection resource..
+ things_resource_s *p_temp;
+ OCRepPayload *rep_payload;
+
+ if (NULL != res->things_get_children(res) && (NULL != strstr(res->uri, URI_DEVICE_COL)) && (strstr(res->query, OIC_INTERFACE_BATCH) != NULL)) {
+ p_temp = res->next;
+ rep_payload = p_temp->things_create_payload(p_temp, p_temp->query);
+ p_temp = p_temp->next;
+ }
+
+ else {
+ rep_payload = res->things_create_payload(res, res->query);
+ // Create payload for the children resource(s)
+ p_temp = res->things_get_children(res);
+ }
+
+ while (NULL != p_temp) {
+ if (NULL != p_temp->rep) {
+ OCRepPayloadAppend(rep_payload, p_temp->things_create_payload(p_temp, p_temp->query));
+ }
+ p_temp = p_temp->next;
+ }
+
+ return rep_payload;
+ } else {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "ROOT(Parent) Paylaod is NULL.");
+ return NULL;
+ }
+}
+
+bool is_supporting_interface_type(struct things_resource_s *res, char *query)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+ bool result = false;
+ uint8_t number_of_interfaces = 0;
+
+ OCGetNumberOfResourceInterfaces((OCResourceHandle) res->resource_handle, &number_of_interfaces);
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "@@ IF # : %d ", number_of_interfaces);
+ //2.a Find interface type(s) & insert it/them into payload
+ for (uint8_t index = 0; index < number_of_interfaces; index++) {
+ const char *interface = OCGetResourceInterfaceName((OCResourceHandle) res->resource_handle, index);
+
+ // THINGS_LOG_D(THINGS_DEBUG, TAG, "Supporting Interface :: %s(%s)", query, interface);
+ if (NULL != query) {
+ if (strstr(query, interface) != NULL) {
+ // THINGS_LOG_D(THINGS_DEBUG, TAG, "Confirm Interface.");
+ result = true;
+ break;
+ }
+ }
+ }
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_EXIT);
+ return result;
+}
+
+bool is_supporting_resource_type(struct things_resource_s *res, char *query)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+ bool result = false;
+ uint8_t number_of_resource_type = 0;
+
+ OCGetNumberOfResourceTypes((OCResourceHandle) res->resource_handle, &number_of_resource_type);
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "@@ RT # : %d ", number_of_resource_type);
+ //2.a Find resource type(s) & insert it/them into payload
+ for (uint8_t index = 0; index < number_of_resource_type; index++) {
+ const char *rtype = OCGetResourceTypeName((OCResourceHandle) res->resource_handle, index);
+
+ // THINGS_LOG_D(THINGS_DEBUG, TAG, "Supporting rtype :: %s(%s)", query, rtype);
+ if (strstr(query, rtype) != NULL) {
+ // THINGS_LOG_D(THINGS_DEBUG, TAG, "Confirm rtype.");
+ result = true;
+ break;
+ }
+ }
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_EXIT);
+ return result;
+}
+
+void set_command_id(things_resource_s *res, char *cmd_id)
+{
+ duplicate_string(cmd_id, &res->cmd_id);
+}
+
+things_resource_s *get_next(things_resource_s *res)
+{
+ if (NULL != res) {
+ if (NULL != res->next) {
+ return res->next;
+ }
+ }
+
+ return NULL;
+}
+
+void add_child(things_resource_s *root, things_resource_s *child)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+
+ things_resource_s *p_node = NULL;
+
+ p_node = root;
+ while (NULL != p_node->things_get_next(p_node)) {
+ p_node = p_node->things_get_next(p_node);
+ }
+
+ p_node->next = child;
+ root->size++;
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_EXIT);
+}
+
+things_representation_s *things_create_representation_inst(void *rep_payload)
+{
+ things_representation_s *rep = (things_representation_s *) things_malloc(sizeof(things_representation_s));
+ if (NULL == rep) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, THINGS_MEMORY_ERROR);
+ return NULL;
+ }
+
+ rep->things_set_value = &things_set_value;
+ rep->things_set_bool_value = &things_set_bool_value;
+ rep->things_set_double_value = &things_set_double_value;
+ rep->things_set_int_value = &things_set_int_value;
+ rep->things_set_byte_value = &things_set_byte_value;
+ rep->things_set_object_value = &things_set_object_value;
+
+ rep->things_set_arrayvalue = &things_set_arrayvalue;
+ rep->things_get_arrayvalue = &things_get_arrayvalue;
+ rep->things_set_string_arrayvalue = &things_set_string_arrayvalue;
+ rep->things_get_string_arrayvalue = &things_get_string_arrayvalue;
+
+ rep->things_set_double_arrayvalue = &things_set_double_arrayvalue;
+ rep->things_get_double_arrayvalue = &things_get_double_arrayvalue;
+ rep->things_set_int_arrayvalue = &things_set_int_arrayvalue;
+ rep->things_get_int_arrayvalue = &things_get_int_arrayvalue;
+
+ rep->things_get_value = &things_get_value;
+ rep->things_get_bool_value = &things_get_bool_value;
+ rep->things_get_int_value = &things_get_int_value;
+ rep->things_get_double_value = &things_get_double_value;
+ rep->things_get_byte_value = &things_get_byte_value;
+ rep->things_get_object_value = &things_get_object_value;
+
+ rep->payload = NULL;
+ rep->children_payload = NULL;
+ rep->children = NULL;
+ rep->num_children = 0;
+
+ if (rep_payload != NULL) {
+ rep->payload = OCRepPayloadClone((OCRepPayload *) rep_payload);
+ } else {
+ rep->payload = OCRepPayloadCreate();
+ }
+
+ return rep;
+}
+
+things_resource_s *create_resource_inst_impl(void *requesthd, void *resourcehd, void *query, void *rep_payload)
+{
+ things_resource_s *res = (things_resource_s *) things_malloc(sizeof(things_resource_s));
+ if (NULL == res) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, THINGS_MEMORY_ERROR);
+ return NULL;
+ }
+
+ res->error = 0; // OC_EH_OK;
+
+ res->dev_addr = NULL;
+
+ res->things_set_dev_addr = &set_dev_addr;
+ res->things_get_dev_addr = &get_dev_addr;
+
+ res->things_set_uri = &set_uri;
+ res->things_set_error = &set_error;
+
+ res->things_set_command_id = &set_command_id;
+
+ res->things_add_child = &add_child;
+ res->things_get_children = &get_children;
+
+ res->things_get_uri = &get_uri;
+ res->things_get_res_type = &get_res_type;
+ res->things_get_num_of_res_types = &get_num_of_res_types;
+ res->things_get_inf_type = &get_inf_type;
+ res->things_get_num_of_inf_types = &get_num_of_inf_types;
+ res->things_set_representation = &set_representation;
+ res->things_get_representation = &get_representation;
+
+ res->things_get_query = &get_query;
+ res->things_get_rep_payload = &get_rep_payload;
+ res->things_create_payload = &create_payload;
+ res->things_is_supporting_interface_type = &is_supporting_interface_type;
+ res->things_is_supporting_resource_type = &is_supporting_resource_type;
+
+ res->next = NULL;
+ res->things_get_next = &get_next;
+
+ res->resource_handle = resourcehd;
+ res->request_handle = requesthd;
+
+ res->uri = NULL;
+ const char *uri = OCGetResourceUri(resourcehd);
+ if (uri != NULL && strlen(uri) > 0) {
+ res->uri = (char *)things_malloc(sizeof(char) * strlen(uri) + 1);
+ memset(res->uri, 0, strlen(uri) + 1);
+ things_strncpy(res->uri, uri, strlen(uri));
+ }
+
+ res->res_type = NULL;
+ res->interface_type = NULL;
+ res->req_type = 0;
+ res->cmd_id = NULL;
+ res->rep = NULL;
+ res->query = NULL;
+ res->size = 1;
+
+ if (NULL != query) {
+ duplicate_string((char *)query, &(res->query));
+ }
+
+ if (NULL != rep_payload) {
+ res->rep = things_create_representation_inst(rep_payload);
+ }
+ // else
+ // {
+ // THINGS_LOG_D(THINGS_DEBUG,TAG, "Representation not created!!");
+ // }
+
+ return res;
+}
+
+things_resource_s *things_create_resource_inst(OCRequestHandle requesthd, OCResourceHandle resourcehd, void *query, void *rep_payload)
+{
+ things_resource_s *res = create_resource_inst_impl(requesthd,
+ resourcehd,
+ query,
+ rep_payload);
+
+ if (NULL != rep_payload) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Representation Inserted to Clone~!!!");
+ OCRepPayload *pl = ((OCRepPayload *) rep_payload)->next;
+
+ things_resource_s *pTempRes = NULL;
+ while (pl) {
+ if (NULL != pl->uri) {
+ pTempRes = create_resource_inst_impl(requesthd, resourcehd, NULL, pl);
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Child Resource URI : %s", pl->uri);
+ pTempRes->things_set_uri(pTempRes, pl->uri);
+ res->things_add_child(res, pTempRes);
+ //res->size++;
+ } else {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "No Uri in this payload for child, this payload was ignored.");
+ }
+
+ pl = pl->next;
+ }
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "\t Child Count : %d", res->size);
+ } else {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "No Representation to Clone : %x", rep_payload);
+ }
+
+ return res;
+}
+
+// BTD
+things_resource_s *clone_resource_inst(things_resource_s *pori)
+{
+ if (pori == NULL) {
+ return NULL;
+ }
+
+ things_resource_s *pclone = create_resource_inst_impl(pori->request_handle,
+ pori->resource_handle,
+ pori->query,
+ (pori->rep == NULL) ? NULL : pori->rep->payload);
+ pclone->things_set_uri(pclone, pori->uri);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "@@@@@@@@@@@@@@@ URI %s", pclone->uri);
+
+ things_resource_s *p_temp = pori->next;
+ while (p_temp) {
+ things_resource_s *p_new = create_resource_inst_impl(p_temp->request_handle,
+ p_temp->resource_handle,
+ p_temp->query,
+ ((p_temp->rep == NULL) ? NULL : p_temp->rep->payload));
+
+ p_new->things_set_uri(p_new, p_temp->uri);
+ p_temp->things_add_child(p_temp, p_new);
+ p_temp = p_temp->next;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "@@@@@@@@@@@@@@@ Address of cloned %x", pclone);
+ return pclone;
+}
+
+void things_clone_resource_inst2(things_resource_s *pori, things_resource_s **pclone)
+{
+ if (pori == NULL) {
+ return;
+ }
+
+ *pclone = create_resource_inst_impl(pori->request_handle, pori->resource_handle, pori->query, ((pori->rep == NULL) ? NULL : pori->rep->payload));
+
+ (*pclone)->things_set_uri(*pclone, pori->uri);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "@@@@@@@@@@@@@@@ URI %s", (*pclone)->uri);
+
+ return;
+}
+
+void things_release_representation_inst(things_representation_s *rep)
+{
+ if (rep != NULL) {
+ if (rep->children_payload != NULL) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Representation has %lld Children.", rep->num_children);
+ for (int64_t iter = 0; iter < rep->num_children; iter++) {
+ if ((rep->children_payload[iter]) != NULL) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "\t RELEASED.");
+ OCPayloadDestroy((OCPayload *)(rep->children_payload[iter]));
+ rep->children_payload[iter] = NULL;
+ }
+ }
+ }
+ if (rep->payload != NULL) {
+ OCPayloadDestroy((OCPayload *)(rep->payload));
+ rep->payload = NULL;
+ }
+
+ things_free(rep);
+ rep = NULL;
+ }
+}
+
+void release_resource_inst_impl(things_resource_s *res)
+{
+ if (res != NULL) {
+ if (res->uri != NULL) {
+ things_free(res->uri);
+ res->uri = NULL;
+ }
+ if (res->res_type != NULL) {
+ things_free(res->res_type);
+ res->res_type = NULL;
+ }
+ if (res->interface_type != NULL) {
+ things_free(res->interface_type);
+ res->interface_type = NULL;
+ }
+ if (res->cmd_id != NULL) {
+ things_free(res->cmd_id);
+ res->cmd_id = NULL;
+ }
+ if (res->query != NULL) {
+ things_free(res->query);
+ res->query = NULL;
+ }
+ if (res->rep != NULL) {
+ things_release_representation_inst(res->rep);
+ }
+ if (res->dev_addr != NULL) {
+ things_free(res->dev_addr);
+ }
+ things_free(res);
+ res = NULL;
+ }
+}
+
+void things_release_resource_inst(things_resource_s *res)
+{
+ if (res != NULL) {
+ if (NULL != res->next) {
+ things_resource_s *p_temp = res->next;
+ things_resource_s *pDel = NULL;
+ while (NULL != p_temp) {
+ pDel = p_temp;
+ p_temp = p_temp->next;
+
+ release_resource_inst_impl(pDel);
+ pDel = NULL;
+ }
+ }
+
+ release_resource_inst_impl(res);
+ res = NULL;
+ }
+}
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 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 <stdlib.h>
+#include <unistd.h>
+#include <ifaddrs.h>
+#include <netpacket/packet.h>
+
+#include "securevirtualresourcetypes.h"
+
+//Added as workround to test cert based (D)TLS connection
+#include "srmresourcestrings.h"
+
+#include "things_logger.h"
+#include "things_malloc.h"
+#include "things_security_manager.h"
+#include "things_common.h"
+#include "credresource.h"
+#include "ss_sha2.h"
+#include "oxmverifycommon.h"
+#include "oic_string.h"
+#include "utlist.h"
+#include "aclresource.h"
+#include "srmutility.h"
+
+#include <wifi_manager/wifi_manager.h>
+
+#if defined(CONFIG_TLS_WITH_SSS) && defined(CONFIG_HW_ECDSA)
+#if defined(CONFIG_IOTIVITY_SSS_STORAGE) // pkss
+#ifndef USE_SSS
+#define USE_SSS
+#endif
+#endif // pkss
+#endif
+
+#define TAG "OIC_SEC_MGR"
+
+typedef enum {
+ OIC_SEC_OK = 0,
+ OIC_SEC_ERROR = 1,
+ OIC_SEC_INVALID_PARAM = 2
+} OICSecurityResult;
+
+#if __MIPS__
+#define STRING_SVR_DB_PATH "/data1/oic_svr_db_server.dat"
+#elif __TIZEN__
+#define STRING_SVR_DB_PATH "/opt/data/ocfData/oic_svr_db_server.dat"
+#else
+#define STRING_SVR_DB_PATH "./oic_svr_db_server.dat"
+#endif
+
+#define MD_MAX_LEN 64
+#define MAC_BUF_SIZE 64
+#define MAX_PATH_LEN 100
+
+static char SVR_DB_PATH[MAX_PATH_LEN] = { 0 };
+
+static things_auth_type_e g_auth_type = AUTH_JUST_WORKS;
+static bool g_is_svr_db_exist = false;
+static bool g_is_mfg_cert_required = false;
+#ifdef __ST_THINGS_RTOS__
+#define USER_CONFIRM 1
+#define SetVerifyOption(x) {}
+#define sync() {}
+#endif
+const unsigned char OIC_SVR_DB_COMMON[] = {
+ 0xBF, 0x63, 0x61, 0x63, 0x6C, 0x59, 0x03, 0x2B, 0xA4, 0x66, 0x61, 0x63, 0x6C, 0x69, 0x73, 0x74,
+ 0xA1, 0x64, 0x61, 0x63, 0x65, 0x73, 0x84, 0xA3, 0x6B, 0x73, 0x75, 0x62, 0x6A, 0x65, 0x63, 0x74,
+ 0x75, 0x75, 0x69, 0x64, 0x61, 0x2A, 0x69, 0x72, 0x65, 0x73, 0x6F, 0x75, 0x72, 0x63, 0x65, 0x73,
+ 0x83, 0xA4, 0x64, 0x68, 0x72, 0x65, 0x66, 0x68, 0x2F, 0x6F, 0x69, 0x63, 0x2F, 0x72, 0x65, 0x73,
+ 0x62, 0x72, 0x74, 0x81, 0x6A, 0x6F, 0x69, 0x63, 0x2E, 0x77, 0x6B, 0x2E, 0x72, 0x65, 0x73, 0x62,
+ 0x69, 0x66, 0x81, 0x69, 0x6F, 0x69, 0x63, 0x2E, 0x69, 0x66, 0x2E, 0x6C, 0x6C, 0x63, 0x72, 0x65,
+ 0x6C, 0x60, 0xA4, 0x64, 0x68, 0x72, 0x65, 0x66, 0x66, 0x2F, 0x6F, 0x69, 0x63, 0x2F, 0x64, 0x62,
+ 0x72, 0x74, 0x81, 0x68, 0x6F, 0x69, 0x63, 0x2E, 0x77, 0x6B, 0x2E, 0x64, 0x62, 0x69, 0x66, 0x82,
+ 0x6F, 0x6F, 0x69, 0x63, 0x2E, 0x69, 0x66, 0x2E, 0x62, 0x61, 0x73, 0x65, 0x6C, 0x69, 0x6E, 0x65,
+ 0x68, 0x6F, 0x69, 0x63, 0x2E, 0x69, 0x66, 0x2E, 0x72, 0x63, 0x72, 0x65, 0x6C, 0x60, 0xA4, 0x64,
+ 0x68, 0x72, 0x65, 0x66, 0x66, 0x2F, 0x6F, 0x69, 0x63, 0x2F, 0x70, 0x62, 0x72, 0x74, 0x81, 0x68,
+ 0x6F, 0x69, 0x63, 0x2E, 0x77, 0x6B, 0x2E, 0x70, 0x62, 0x69, 0x66, 0x82, 0x6F, 0x6F, 0x69, 0x63,
+ 0x2E, 0x69, 0x66, 0x2E, 0x62, 0x61, 0x73, 0x65, 0x6C, 0x69, 0x6E, 0x65, 0x68, 0x6F, 0x69, 0x63,
+ 0x2E, 0x69, 0x66, 0x2E, 0x72, 0x63, 0x72, 0x65, 0x6C, 0x60, 0x6A, 0x70, 0x65, 0x72, 0x6D, 0x69,
+ 0x73, 0x73, 0x69, 0x6F, 0x6E, 0x02, 0xA3, 0x6B, 0x73, 0x75, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x75,
+ 0x75, 0x69, 0x64, 0x61, 0x2A, 0x69, 0x72, 0x65, 0x73, 0x6F, 0x75, 0x72, 0x63, 0x65, 0x73, 0x84,
+ 0xA4, 0x64, 0x68, 0x72, 0x65, 0x66, 0x6D, 0x2F, 0x6F, 0x69, 0x63, 0x2F, 0x73, 0x65, 0x63, 0x2F,
+ 0x64, 0x6F, 0x78, 0x6D, 0x62, 0x72, 0x74, 0x81, 0x6A, 0x6F, 0x69, 0x63, 0x2E, 0x72, 0x2E, 0x64,
+ 0x6F, 0x78, 0x6D, 0x62, 0x69, 0x66, 0x81, 0x6F, 0x6F, 0x69, 0x63, 0x2E, 0x69, 0x66, 0x2E, 0x62,
+ 0x61, 0x73, 0x65, 0x6C, 0x69, 0x6E, 0x65, 0x63, 0x72, 0x65, 0x6C, 0x60, 0xA4, 0x64, 0x68, 0x72,
+ 0x65, 0x66, 0x6E, 0x2F, 0x6F, 0x69, 0x63, 0x2F, 0x73, 0x65, 0x63, 0x2F, 0x70, 0x73, 0x74, 0x61,
+ 0x74, 0x62, 0x72, 0x74, 0x81, 0x6B, 0x6F, 0x69, 0x63, 0x2E, 0x72, 0x2E, 0x70, 0x73, 0x74, 0x61,
+ 0x74, 0x62, 0x69, 0x66, 0x81, 0x6F, 0x6F, 0x69, 0x63, 0x2E, 0x69, 0x66, 0x2E, 0x62, 0x61, 0x73,
+ 0x65, 0x6C, 0x69, 0x6E, 0x65, 0x63, 0x72, 0x65, 0x6C, 0x60, 0xA4, 0x64, 0x68, 0x72, 0x65, 0x66,
+ 0x6C, 0x2F, 0x6F, 0x69, 0x63, 0x2F, 0x73, 0x65, 0x63, 0x2F, 0x61, 0x63, 0x6C, 0x62, 0x72, 0x74,
+ 0x81, 0x69, 0x6F, 0x69, 0x63, 0x2E, 0x72, 0x2E, 0x61, 0x63, 0x6C, 0x62, 0x69, 0x66, 0x81, 0x6F,
+ 0x6F, 0x69, 0x63, 0x2E, 0x69, 0x66, 0x2E, 0x62, 0x61, 0x73, 0x65, 0x6C, 0x69, 0x6E, 0x65, 0x63,
+ 0x72, 0x65, 0x6C, 0x60, 0xA4, 0x64, 0x68, 0x72, 0x65, 0x66, 0x6D, 0x2F, 0x6F, 0x69, 0x63, 0x2F,
+ 0x73, 0x65, 0x63, 0x2F, 0x63, 0x72, 0x65, 0x64, 0x62, 0x72, 0x74, 0x81, 0x6A, 0x6F, 0x69, 0x63,
+ 0x2E, 0x72, 0x2E, 0x63, 0x72, 0x65, 0x64, 0x62, 0x69, 0x66, 0x81, 0x6F, 0x6F, 0x69, 0x63, 0x2E,
+ 0x69, 0x66, 0x2E, 0x62, 0x61, 0x73, 0x65, 0x6C, 0x69, 0x6E, 0x65, 0x63, 0x72, 0x65, 0x6C, 0x60,
+ 0x6A, 0x70, 0x65, 0x72, 0x6D, 0x69, 0x73, 0x73, 0x69, 0x6F, 0x6E, 0x06, 0xA3, 0x6B, 0x73, 0x75,
+ 0x62, 0x6A, 0x65, 0x63, 0x74, 0x75, 0x75, 0x69, 0x64, 0x61, 0x2A, 0x69, 0x72, 0x65, 0x73, 0x6F,
+ 0x75, 0x72, 0x63, 0x65, 0x73, 0x81, 0xA3, 0x64, 0x68, 0x72, 0x65, 0x66, 0x75, 0x2F, 0x73, 0x65,
+ 0x63, 0x2F, 0x70, 0x72, 0x6F, 0x76, 0x69, 0x73, 0x69, 0x6F, 0x6E, 0x69, 0x6E, 0x67, 0x69, 0x6E,
+ 0x66, 0x6F, 0x62, 0x72, 0x74, 0x81, 0x78, 0x1E, 0x78, 0x2E, 0x63, 0x6F, 0x6D, 0x2E, 0x73, 0x61,
+ 0x6D, 0x73, 0x75, 0x6E, 0x67, 0x2E, 0x70, 0x72, 0x6F, 0x76, 0x69, 0x73, 0x69, 0x6F, 0x6E, 0x69,
+ 0x6E, 0x67, 0x69, 0x6E, 0x66, 0x6F, 0x62, 0x69, 0x66, 0x81, 0x68, 0x6F, 0x69, 0x63, 0x2E, 0x69,
+ 0x66, 0x2E, 0x61, 0x6A, 0x70, 0x65, 0x72, 0x6D, 0x69, 0x73, 0x73, 0x69, 0x6F, 0x6E, 0x07, 0xA3,
+ 0x6B, 0x73, 0x75, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x75, 0x75, 0x69, 0x64, 0x61, 0x2A, 0x69, 0x72,
+ 0x65, 0x73, 0x6F, 0x75, 0x72, 0x63, 0x65, 0x73, 0x81, 0xA3, 0x64, 0x68, 0x72, 0x65, 0x66, 0x74,
+ 0x2F, 0x73, 0x65, 0x63, 0x2F, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x70, 0x6F, 0x69, 0x6E, 0x74,
+ 0x6C, 0x69, 0x73, 0x74, 0x62, 0x72, 0x74, 0x81, 0x78, 0x1D, 0x78, 0x2E, 0x63, 0x6F, 0x6D, 0x2E,
+ 0x73, 0x61, 0x6D, 0x73, 0x75, 0x6E, 0x67, 0x2E, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x70, 0x6F,
+ 0x69, 0x6E, 0x74, 0x6C, 0x69, 0x73, 0x74, 0x62, 0x69, 0x66, 0x81, 0x68, 0x6F, 0x69, 0x63, 0x2E,
+ 0x69, 0x66, 0x2E, 0x73, 0x6A, 0x70, 0x65, 0x72, 0x6D, 0x69, 0x73, 0x73, 0x69, 0x6F, 0x6E, 0x02,
+ 0x6A, 0x72, 0x6F, 0x77, 0x6E, 0x65, 0x72, 0x75, 0x75, 0x69, 0x64, 0x78, 0x24, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x2D, 0x30, 0x30, 0x30, 0x30, 0x2D, 0x30, 0x30, 0x30, 0x30, 0x2D,
+ 0x30, 0x30, 0x30, 0x30, 0x2D, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x62, 0x72, 0x74, 0x81, 0x69, 0x6F, 0x69, 0x63, 0x2E, 0x72, 0x2E, 0x61, 0x63, 0x6C, 0x62,
+ 0x69, 0x66, 0x81, 0x6F, 0x6F, 0x69, 0x63, 0x2E, 0x69, 0x66, 0x2E, 0x62, 0x61, 0x73, 0x65, 0x6C,
+ 0x69, 0x6E, 0x65, 0x65, 0x70, 0x73, 0x74, 0x61, 0x74, 0x58, 0x9D, 0xA9, 0x64, 0x69, 0x73, 0x6F,
+ 0x70, 0xF4, 0x62, 0x63, 0x6D, 0x02, 0x62, 0x74, 0x6D, 0x00, 0x62, 0x6F, 0x6D, 0x04, 0x62, 0x73,
+ 0x6D, 0x04, 0x6A, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x75, 0x75, 0x69, 0x64, 0x78, 0x24, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x2D, 0x30, 0x30, 0x30, 0x30, 0x2D, 0x30, 0x30, 0x30,
+ 0x30, 0x2D, 0x30, 0x30, 0x30, 0x30, 0x2D, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x6A, 0x72, 0x6F, 0x77, 0x6E, 0x65, 0x72, 0x75, 0x75, 0x69, 0x64, 0x78, 0x24,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x2D, 0x30, 0x30, 0x30, 0x30, 0x2D, 0x30, 0x30,
+ 0x30, 0x30, 0x2D, 0x30, 0x30, 0x30, 0x30, 0x2D, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x62, 0x72, 0x74, 0x81, 0x6B, 0x6F, 0x69, 0x63, 0x2E, 0x72, 0x2E, 0x70,
+ 0x73, 0x74, 0x61, 0x74, 0x62, 0x69, 0x66, 0x81, 0x6F, 0x6F, 0x69, 0x63, 0x2E, 0x69, 0x66, 0x2E,
+ 0x62, 0x61, 0x73, 0x65, 0x6C, 0x69, 0x6E, 0x65, 0x64, 0x64, 0x6F, 0x78, 0x6D, 0x58
+};
+
+//, 0xD9 + oxm array size /*length of doxm header + length of doxm payload */,
+#define DOXM_PAYLOAD_SIZE (0xD4)
+
+const unsigned char OIC_SVR_DB_DOXM_HEADER[] = {
+ 0xBF, 0x64, 0x6F, 0x78, 0x6D, 0x73
+};
+
+//0x80 + oxm array size /*oxm size*/,
+#define DOXM_OXM_SIZE (0x80)
+
+// 0x00, 0x01, 0x02 : oxm value as array
+
+const unsigned char OIC_SVR_DB_DOXM_PAYLOAD[] = {
+ 0x66, 0x6F, 0x78, 0x6D, 0x73, 0x65, 0x6C, 0x00, 0x63, 0x73, 0x63, 0x74, 0x01, 0x65, 0x6F, 0x77,
+ 0x6E, 0x65, 0x64, 0xF4, 0x6A, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x75, 0x75, 0x69, 0x64, 0x78,
+ 0x24, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x2D, 0x30, 0x30, 0x30, 0x30, 0x2D, 0x30,
+ 0x30, 0x30, 0x30, 0x2D, 0x30, 0x30, 0x30, 0x30, 0x2D, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, /*0x63, 0x6D, 0x6F, 0x6D, 0x01, *//*"mom":1 */ 0x6C, 0x64, 0x65, 0x76, 0x6F, 0x77,
+ 0x6E, 0x65, 0x72, 0x75, 0x75, 0x69, 0x64, 0x78, 0x24, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x2D, 0x30, 0x30, 0x30, 0x30, 0x2D, 0x30, 0x30, 0x30, 0x30, 0x2D, 0x30, 0x30, 0x30, 0x30,
+ 0x2D, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x6A, 0x72, 0x6F,
+ 0x77, 0x6E, 0x65, 0x72, 0x75, 0x75, 0x69, 0x64, 0x78, 0x24, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x2D, 0x30, 0x30, 0x30, 0x30, 0x2D, 0x30, 0x30, 0x30, 0x30, 0x2D, 0x30, 0x30, 0x30,
+ 0x30, 0x2D, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x62, 0x72,
+ 0x74, 0x81, 0x6A, 0x6F, 0x69, 0x63, 0x2E, 0x72, 0x2E, 0x64, 0x6F, 0x78, 0x6D, 0x62, 0x69, 0x66,
+ 0x81, 0x6F, 0x6F, 0x69, 0x63, 0x2E, 0x69, 0x66, 0x2E, 0x62, 0x61, 0x73, 0x65, 0x6C, 0x69, 0x6E,
+ 0x65, 0xFF, 0xFF
+};
+
+FILE *server_fopen(const char *path, const char *mode) // pkss
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "F SVR DB File Path : %s", SVR_DB_PATH);
+ (void)path;
+ return fopen(SVR_DB_PATH, mode);
+}
+
+size_t server_fread(FAR void *ptr, size_t size, size_t n_items, FAR FILE *stream)
+{
+ struct timeval start, end;
+ size_t ret = 0;
+ gettimeofday(&start, NULL);
+ ret = fread(ptr, size, n_items, stream);
+ gettimeofday(&end, NULL);
+ return ret;
+}
+
+size_t server_fwrite(FAR const void *ptr, size_t size, size_t n_items, FAR FILE *stream)
+{
+ struct timeval start, end;
+ size_t ret = 0;
+ gettimeofday(&start, NULL);
+
+ ret = fwrite(ptr, size, n_items, stream);
+
+ gettimeofday(&end, NULL);
+ return ret;
+}
+
+int server_fclose(FILE *stream)
+{
+ int ret = fclose(stream);
+ return ret;
+}
+
+/*
+ * This API Setup Seckey from filepath
+ */
+static OCStackResult seckey_setup(const char *filename, OicSecKey_t *key, OicEncodingType_t encoding)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "IN: %s", __func__);
+
+ size_t size = 0;
+ key->data = NULL;
+ key->len = 0;
+ key->encoding = OIC_ENCODING_UNKNOW;
+ FILE *fp = fopen(filename, "rb");
+
+ if (fp == NULL) {
+ THINGS_LOG_D(THINGS_ERROR, TAG, "Can not open file[%s].", filename);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "OUT[FAIL]: %s", __func__);
+ return OC_STACK_ERROR;
+ }
+
+ if (0 == fseek(fp, 0L, SEEK_END)) {
+ size = ftell(fp);
+ rewind(fp);
+ key->data = (uint8_t *) things_malloc(size);
+ if (key->data == NULL) {
+ THINGS_LOG_D(THINGS_ERROR, TAG, "Memory Full");
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "OUT[FAIL]: %s", __func__);
+ return OC_STACK_NO_MEMORY;
+ }
+ fread(key->data, 1, size, fp);
+ key->len = size;
+ key->encoding = encoding;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "OUT: %s", __func__);
+ return OC_STACK_OK;
+}
+
+/*
+ * This API added as workaround to test certificate based (D)TLS connection.
+ * It will be replaced to use TZ or eSE based key protection.
+ */
+static OCStackResult save_signed_asymmetric_key(OicUuid_t *subject_uuid);
+
+static int GenerateSvrDb()
+{
+ THINGS_LOG_D(THINGS_INFO, TAG, "In %s", __func__);
+
+ if (AUTH_UNKNOW == g_auth_type) {
+ THINGS_LOG(THINGS_INFO, TAG, "Unknown authentication type for ownership transfer.");
+ THINGS_LOG(THINGS_INFO, TAG, "please make sure your configuration in json file.");
+ THINGS_LOG(THINGS_INFO, TAG, "----------------------");
+ THINGS_LOG(THINGS_INFO, TAG, "Justwork authentication will be used as default authentication method.");
+ THINGS_LOG(THINGS_INFO, TAG, "----------------------");
+ g_auth_type = AUTH_JUST_WORKS;
+ }
+
+ FILE *fp = NULL;
+ fp = fopen(SVR_DB_PATH, "w");
+
+ OICSecurityResult res = OIC_SEC_ERROR;
+
+ if (NULL != fp) {
+ int idx = 0;
+ unsigned char *svrdb = NULL;
+ unsigned char *cur_pos = NULL;
+ //To generate OxM Array.
+ uint16_t oxms[OIC_OXM_COUNT + 3 /*Number of vendor specific OxM */] = { 0 };
+ size_t oxm_cnt = 0;
+ size_t oxm_size = 0;
+ size_t svrdb_size = 0;
+
+ if (g_auth_type & AUTH_JUST_WORKS) {
+ THINGS_LOG(THINGS_DEBUG, TAG, "Added Justworks OxM.");
+ oxms[oxm_cnt++] = OIC_JUST_WORKS;
+ oxm_size++;
+ }
+ if (g_auth_type & AUTH_RANDOM_PIN) {
+ THINGS_LOG(THINGS_DEBUG, TAG, "Added Random PIN based OxM.");
+ oxms[oxm_cnt++] = OIC_RANDOM_DEVICE_PIN;
+ oxm_size++;
+ }
+ if (g_auth_type & AUTH_CERTIFICATE || g_auth_type & AUTH_CERTIFICATE_CONFIRM) {
+ THINGS_LOG(THINGS_DEBUG, TAG, "Added Certificate based OxM.");
+ oxms[oxm_cnt++] = OIC_MANUFACTURER_CERTIFICATE;
+ oxm_size++;
+ }
+ if (g_auth_type & AUTH_DECENTRALIZED_PUB_KEY) {
+ THINGS_LOG(THINGS_DEBUG, TAG, "Added Decentralized public key based OxM.");
+ oxms[oxm_cnt++] = OIC_DECENTRALIZED_PUBLIC_KEY;
+ oxm_size++;
+ }
+ if (g_auth_type & AUTH_PRECONF_PIN) {
+ THINGS_LOG(THINGS_DEBUG, TAG, "Added Preconfigured-PIN based OxM (for MOT only).");
+ oxms[oxm_cnt++] = 0xFF00; //OIC_PRECONFIG_PIN
+ oxm_size += 3;
+ }
+ if (g_auth_type & AUTH_JUST_WORKS_MUTUAL_VERIFIED) {
+ THINGS_LOG(THINGS_DEBUG, TAG, "Added Mutual Verification Justworks based OxM.");
+ oxms[oxm_cnt++] = 0xFF01;
+ oxm_size += 3;
+ }
+ if (g_auth_type & AUTH_CERTIFICATE || g_auth_type & AUTH_CERTIFICATE_CONFIRM) {
+ THINGS_LOG(THINGS_DEBUG, TAG, "Added Certificate+Confirm based OxM.");
+ oxms[oxm_cnt++] = 0xFF02;
+ oxm_size += 3;
+ }
+ if (0 == oxm_cnt) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Failed to extract authentication types.");
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Please make sure your configuration in json file.");
+ res = OIC_SEC_INVALID_PARAM;
+ goto error;
+ }
+
+ svrdb_size = sizeof(OIC_SVR_DB_COMMON) + sizeof(OIC_SVR_DB_DOXM_HEADER) + sizeof(OIC_SVR_DB_DOXM_PAYLOAD) + 2 /*size of payload length */ + oxm_size;
+ svrdb = (unsigned char *)things_malloc(svrdb_size + 32);
+ if (NULL == svrdb) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Failed to memory allocation.");
+ goto error;
+ }
+ //
+ //Generate default SVR DB
+ cur_pos = svrdb;
+
+ //Construct Common part of SVR DB
+ memcpy(cur_pos, OIC_SVR_DB_COMMON, sizeof(OIC_SVR_DB_COMMON));
+ cur_pos += sizeof(OIC_SVR_DB_COMMON);
+
+ //Construct Doxm payload size
+ *cur_pos = (unsigned char)(DOXM_PAYLOAD_SIZE + oxm_size);
+ cur_pos++;
+
+ //Construct Doxm Header
+ memcpy(cur_pos, OIC_SVR_DB_DOXM_HEADER, sizeof(OIC_SVR_DB_DOXM_HEADER));
+ cur_pos += sizeof(OIC_SVR_DB_DOXM_HEADER);
+
+ //Construct Length of OxM array
+ *cur_pos = (unsigned char)(DOXM_OXM_SIZE + oxm_cnt);
+ cur_pos++;
+
+ //Construct OxM array
+ for (idx = 0; idx < oxm_cnt; idx++) {
+ if (oxms[idx] < OIC_OXM_COUNT) {
+ *cur_pos = oxms[idx];
+ cur_pos++;
+ } else if (oxms[idx] == 0xFF00) {
+ *cur_pos = 0x19;
+ cur_pos++;
+ *cur_pos = 0xFF;
+ cur_pos++;
+ *cur_pos = 0x00;
+ cur_pos++;
+ } else if (oxms[idx] == 0xFF01) {
+ *cur_pos = 0x19;
+ cur_pos++;
+ *cur_pos = 0xFF;
+ cur_pos++;
+ *cur_pos = 0x01;
+ cur_pos++;
+ } else if (oxms[idx] == 0xFF02) {
+ *cur_pos = 0x19;
+ cur_pos++;
+ *cur_pos = 0xFF;
+ cur_pos++;
+ *cur_pos = 0x02;
+ cur_pos++;
+ }
+ }
+
+ //Construct Doxm payload
+ memcpy(cur_pos, OIC_SVR_DB_DOXM_PAYLOAD, sizeof(OIC_SVR_DB_DOXM_PAYLOAD));
+
+ //End of default SVR DB generation
+ //
+
+ //Save the constructed SVR DB into persistent storage.
+ fwrite(svrdb, 1, svrdb_size, fp);
+ fclose(fp);
+ things_free(svrdb);
+ THINGS_LOG_D(THINGS_INFO, TAG, "Out %s", __func__);
+ return OIC_SEC_OK;
+error:
+ fclose(fp);
+ things_free(svrdb);
+ return OIC_SEC_ERROR;
+ } else {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "Can not open the [%s], Please make sure the access permision of file system.", SVR_DB_PATH);
+ }
+
+ return res; // return 0 when failed, 1 otherwise..
+}
+
+static int get_mac_addr(unsigned char *p_id_buf, size_t p_id_buf_size, unsigned int *p_id_out_len)
+{
+ char mac_addr[MAC_BUF_SIZE];
+ struct ifaddrs *ifaddr = NULL;
+ struct ifaddrs *ifa = NULL;
+ int family = 0;
+ int i = 0;
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "In %s", __func__);
+
+#ifdef __ST_THINGS_RTOS__
+ wifi_manager_info_s st_wifi_info;
+ wifi_manager_get_info(&st_wifi_info);
+
+ if (wifi_manager_get_info(&st_wifi_info) != WIFI_MANAGER_SUCCESS) {
+
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "MAC Get Error\n");
+ return OIC_SEC_ERROR;
+ }
+
+ snprintf((char *)p_id_buf, MAC_BUF_SIZE - 1, "%02X%02X%02X%02X%02X%02X", st_wifi_info.mac_address[0], st_wifi_info.mac_address[1], st_wifi_info.mac_address[2], st_wifi_info.mac_address[3], st_wifi_info.mac_address[4], st_wifi_info.mac_address[5]);
+#else
+ if (getifaddrs(&ifaddr) == -1) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "Failed to read network address information.");
+ return OIC_SEC_ERROR;
+ } else {
+ for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
+ if ((ifa->ifa_addr) && (ifa->ifa_addr->sa_family == AF_PACKET)) {
+ struct sockaddr_ll *s = (struct sockaddr_ll *)ifa->ifa_addr;
+
+ memset(p_id_buf, 0x00, p_id_buf_size);
+ for (i = 0; i < s->sll_halen && i < p_id_buf_size; i++) {
+ snprintf((char *)(p_id_buf + (i * 2)), MAC_BUF_SIZE - i, "%02X", (s->sll_addr[i]));
+ }
+ }
+ }
+ freeifaddrs(ifaddr);
+ }
+#endif
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "MAC Address : %s", (char *)p_id_buf);
+ *p_id_out_len = strlen((char *)p_id_buf);
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Out %s", __func__);
+
+ return OIC_SEC_OK;
+}
+
+// ++ Added by Chul Lee : To support MAC based UUID
+int sm_generate_mac_based_device_id(bool is_forced)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "In %s", __func__);
+
+ if (g_is_svr_db_exist && !is_forced) {
+ THINGS_LOG_D(THINGS_WARNING, TAG, "MAC based device UUID generation is not required.");
+ return OIC_SEC_OK;
+ }
+
+ OICSecurityResult res = OIC_SEC_ERROR;
+ OicUuid_t device_id;
+ unsigned char mac_id[MAC_BUF_SIZE];
+ unsigned char hash_value[SS_SHA256_DIGEST_SIZE + 1];
+ unsigned int id_len = 0;
+
+ res = get_mac_addr(mac_id, MAC_BUF_SIZE, &id_len);
+ if (OIC_SEC_OK != res) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Failed to read MAC Address.");
+ return res;
+ }
+ THINGS_LOG_V(THINGS_INFO, TAG, "MAC Address : %s", mac_id);
+
+ ss_sha256_ctx sha256_ctx;
+ ss_sha256_init(&sha256_ctx);
+ ss_sha256_update(&sha256_ctx, mac_id, id_len);
+ ss_sha256_final(&sha256_ctx, hash_value);
+
+ memcpy(device_id.id, hash_value, sizeof(device_id.id));
+
+ OCStackResult oc_res = SetDoxmDeviceID(&device_id);
+ if (OC_STACK_OK != oc_res) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "Error in SetDoxmDeviceID : %d", (int)oc_res);
+ return OIC_SEC_ERROR;
+ }
+ // Added as workaround for cert based D2D & D2S connection
+ oc_res = save_signed_asymmetric_key(&device_id);
+ if (OC_STACK_OK != oc_res) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "Error in save_signed_asymmetric_key : %d", (int)oc_res);
+ return OIC_SEC_ERROR;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Out %s", __func__);
+
+ return res;
+}
+
+// ++ Added by Chul Lee : To support MAC based UUID
+//
+
+int sm_init_things_security(int auth_type, const char *db_path)
+{
+ OICSecurityResult res = OIC_SEC_ERROR;
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "In %s", __func__);
+
+ memset(SVR_DB_PATH, 0x00, MAX_PATH_LEN);
+
+ if (db_path != NULL && strlen(db_path) > 0) {
+ things_strncpy(SVR_DB_PATH, db_path, MAX_PATH_LEN);
+ } else {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "DB Path Not Inserted. Using Default Value");
+ things_strncpy(SVR_DB_PATH, STRING_SVR_DB_PATH, MAX_PATH_LEN);
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "SVR DB PATH : %s", SVR_DB_PATH);
+
+ g_auth_type = auth_type;
+ if ((g_auth_type & AUTH_JUST_WORKS_MUTUAL_VERIFIED) || (g_auth_type & AUTH_CERTIFICATE_CONFIRM)) {
+ SetVerifyOption(USER_CONFIRM);
+ }
+
+ g_is_mfg_cert_required = false;
+ if ((g_auth_type & AUTH_CERTIFICATE) || (g_auth_type & AUTH_CERTIFICATE_CONFIRM)) {
+ g_is_mfg_cert_required = true;
+ }
+
+ res = SM_InitSvrDb();
+ if (OIC_SEC_OK != res) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Failed to create SVR DB.");
+ return res;
+ }
+
+ static OCPersistentStorage ps = { server_fopen, server_fread, server_fwrite, server_fclose, unlink };
+ THINGS_LOG(THINGS_INFO, TAG, "******* WARNING : SVR DB will be used without encryption *******");
+
+ OCStackResult oc_res = OCRegisterPersistentStorageHandler(&ps);
+ if (OC_STACK_INCONSISTENT_DB == oc_res || OC_STACK_SVR_DB_NOT_EXIST == oc_res) {
+ //If failed to load SVR DB
+ THINGS_LOG_D(THINGS_WARNING, TAG, "SVR DB[%s] is inconsistent or not exist : %d", SVR_DB_PATH, oc_res);
+ THINGS_LOG_D(THINGS_WARNING, TAG, "SVR DB will be reinstalled as default SVR DB.");
+
+ //re-generate and re-install SVR DB
+ g_is_svr_db_exist = false;
+ res = SM_InitSvrDb();
+ if (OIC_SEC_OK != res) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Failed to create SVR DB.");
+ return res;
+ }
+ //Re-register PSI
+ oc_res = OCRegisterPersistentStorageHandler(&ps);
+ if (OC_STACK_OK != oc_res) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "Failed to register persistent storage for SVR DB : %d", (int)oc_res);
+ return OIC_SEC_ERROR;
+ }
+ } else if (OC_STACK_OK != oc_res) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "Failed to register persistent storage for SVR DB : %d", (int)oc_res);
+ return OIC_SEC_ERROR;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Out %s", __func__);
+
+ return OIC_SEC_OK;
+}
+
+int SM_InitSvrDb()
+{
+ FILE *fp = fopen(SVR_DB_PATH, "r");
+ if (fp == NULL) {
+ THINGS_LOG_D(THINGS_INFO, TAG, "Can not find the [%s], SVR DB will be automatically generated...", SVR_DB_PATH);
+ THINGS_LOG_D(THINGS_INFO, TAG, "Out %s", __func__);
+ return GenerateSvrDb();
+ } else {
+ THINGS_LOG_D(THINGS_INFO, TAG, "SVR DB [%s] is already exist.", SVR_DB_PATH);
+ g_is_svr_db_exist = true;
+ }
+
+ fclose(fp);
+ THINGS_LOG_D(THINGS_INFO, TAG, "Out %s", __func__);
+
+ return OIC_SEC_OK;
+}
+
+int sm_reset_svrdb()
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "In %s", __func__);
+ OCStackResult oc_res = ResetSecureResourceInPS();
+ if (OC_STACK_OK != oc_res) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "ResetSecureResourceInPS error : %d", oc_res);
+ return OIC_SEC_ERROR;
+ }
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Out %s", __func__);
+ return OIC_SEC_OK;
+}
+
+//
+// ++ Added by Chul Lee : to test certificate based (D)TLS connection for D2D & D2S
+
+#ifndef _EXCLUDE_TEST_KEY_
+static OicSecKey_t primary_cert;
+static OicSecKey_t primary_key;
+// static OicSecKey_t mfgPrimaryCert;
+// static OicSecKey_t mfgPrimaryKey;
+#endif //_EXCLUDE_TEST_KEY_
+
+//thawte_Primary_Root_CA.der
+const unsigned char g_global_ci_root_ca[] = {
+ 0x30, 0x82, 0x04, 0x20, 0x30, 0x82, 0x03, 0x08, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x34, 0x4E, 0xD5, 0x57, 0x20,
+ 0xD5, 0xED, 0xEC, 0x49, 0xF4, 0x2F, 0xCE, 0x37, 0xDB, 0x2B, 0x6D, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7,
+ 0x0D, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, 0xA9, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+ 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0C, 0x74, 0x68, 0x61, 0x77, 0x74, 0x65, 0x2C,
+ 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x1F, 0x43, 0x65, 0x72, 0x74,
+ 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x44,
+ 0x69, 0x76, 0x69, 0x73, 0x69, 0x6F, 0x6E, 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x2F, 0x28, 0x63,
+ 0x29, 0x20, 0x32, 0x30, 0x30, 0x36, 0x20, 0x74, 0x68, 0x61, 0x77, 0x74, 0x65, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x20,
+ 0x2D, 0x20, 0x46, 0x6F, 0x72, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x7A, 0x65, 0x64, 0x20, 0x75, 0x73, 0x65,
+ 0x20, 0x6F, 0x6E, 0x6C, 0x79, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x16, 0x74, 0x68, 0x61, 0x77,
+ 0x74, 0x65, 0x20, 0x50, 0x72, 0x69, 0x6D, 0x61, 0x72, 0x79, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1E,
+ 0x17, 0x0D, 0x30, 0x36, 0x31, 0x31, 0x31, 0x37, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x17, 0x0D, 0x33, 0x36, 0x30,
+ 0x37, 0x31, 0x36, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5A, 0x30, 0x81, 0xA9, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55,
+ 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0C, 0x74, 0x68, 0x61,
+ 0x77, 0x74, 0x65, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x1F,
+ 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63,
+ 0x65, 0x73, 0x20, 0x44, 0x69, 0x76, 0x69, 0x73, 0x69, 0x6F, 0x6E, 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, 0x04, 0x0B,
+ 0x13, 0x2F, 0x28, 0x63, 0x29, 0x20, 0x32, 0x30, 0x30, 0x36, 0x20, 0x74, 0x68, 0x61, 0x77, 0x74, 0x65, 0x2C, 0x20, 0x49,
+ 0x6E, 0x63, 0x2E, 0x20, 0x2D, 0x20, 0x46, 0x6F, 0x72, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x7A, 0x65, 0x64,
+ 0x20, 0x75, 0x73, 0x65, 0x20, 0x6F, 0x6E, 0x6C, 0x79, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x16,
+ 0x74, 0x68, 0x61, 0x77, 0x74, 0x65, 0x20, 0x50, 0x72, 0x69, 0x6D, 0x61, 0x72, 0x79, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20,
+ 0x43, 0x41, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05,
+ 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xAC, 0xA0, 0xF0, 0xFB, 0x80,
+ 0x59, 0xD4, 0x9C, 0xC7, 0xA4, 0xCF, 0x9D, 0xA1, 0x59, 0x73, 0x09, 0x10, 0x45, 0x0C, 0x0D, 0x2C, 0x6E, 0x68, 0xF1, 0x6C,
+ 0x5B, 0x48, 0x68, 0x49, 0x59, 0x37, 0xFC, 0x0B, 0x33, 0x19, 0xC2, 0x77, 0x7F, 0xCC, 0x10, 0x2D, 0x95, 0x34, 0x1C, 0xE6,
+ 0xEB, 0x4D, 0x09, 0xA7, 0x1C, 0xD2, 0xB8, 0xC9, 0x97, 0x36, 0x02, 0xB7, 0x89, 0xD4, 0x24, 0x5F, 0x06, 0xC0, 0xCC, 0x44,
+ 0x94, 0x94, 0x8D, 0x02, 0x62, 0x6F, 0xEB, 0x5A, 0xDD, 0x11, 0x8D, 0x28, 0x9A, 0x5C, 0x84, 0x90, 0x10, 0x7A, 0x0D, 0xBD,
+ 0x74, 0x66, 0x2F, 0x6A, 0x38, 0xA0, 0xE2, 0xD5, 0x54, 0x44, 0xEB, 0x1D, 0x07, 0x9F, 0x07, 0xBA, 0x6F, 0xEE, 0xE9, 0xFD,
+ 0x4E, 0x0B, 0x29, 0xF5, 0x3E, 0x84, 0xA0, 0x01, 0xF1, 0x9C, 0xAB, 0xF8, 0x1C, 0x7E, 0x89, 0xA4, 0xE8, 0xA1, 0xD8, 0x71,
+ 0x65, 0x0D, 0xA3, 0x51, 0x7B, 0xEE, 0xBC, 0xD2, 0x22, 0x60, 0x0D, 0xB9, 0x5B, 0x9D, 0xDF, 0xBA, 0xFC, 0x51, 0x5B, 0x0B,
+ 0xAF, 0x98, 0xB2, 0xE9, 0x2E, 0xE9, 0x04, 0xE8, 0x62, 0x87, 0xDE, 0x2B, 0xC8, 0xD7, 0x4E, 0xC1, 0x4C, 0x64, 0x1E, 0xDD,
+ 0xCF, 0x87, 0x58, 0xBA, 0x4A, 0x4F, 0xCA, 0x68, 0x07, 0x1D, 0x1C, 0x9D, 0x4A, 0xC6, 0xD5, 0x2F, 0x91, 0xCC, 0x7C, 0x71,
+ 0x72, 0x1C, 0xC5, 0xC0, 0x67, 0xEB, 0x32, 0xFD, 0xC9, 0x92, 0x5C, 0x94, 0xDA, 0x85, 0xC0, 0x9B, 0xBF, 0x53, 0x7D, 0x2B,
+ 0x09, 0xF4, 0x8C, 0x9D, 0x91, 0x1F, 0x97, 0x6A, 0x52, 0xCB, 0xDE, 0x09, 0x36, 0xA4, 0x77, 0xD8, 0x7B, 0x87, 0x50, 0x44,
+ 0xD5, 0x3E, 0x6E, 0x29, 0x69, 0xFB, 0x39, 0x49, 0x26, 0x1E, 0x09, 0xA5, 0x80, 0x7B, 0x40, 0x2D, 0xEB, 0xE8, 0x27, 0x85,
+ 0xC9, 0xFE, 0x61, 0xFD, 0x7E, 0xE6, 0x7C, 0x97, 0x1D, 0xD5, 0x9D, 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x42, 0x30, 0x40,
+ 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x0E, 0x06,
+ 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E,
+ 0x04, 0x16, 0x04, 0x14, 0x7B, 0x5B, 0x45, 0xCF, 0xAF, 0xCE, 0xCB, 0x7A, 0xFD, 0x31, 0x92, 0x1A, 0x6A, 0xB6, 0xF3, 0x46,
+ 0xEB, 0x57, 0x48, 0x50, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03,
+ 0x82, 0x01, 0x01, 0x00, 0x79, 0x11, 0xC0, 0x4B, 0xB3, 0x91, 0xB6, 0xFC, 0xF0, 0xE9, 0x67, 0xD4, 0x0D, 0x6E, 0x45, 0xBE,
+ 0x55, 0xE8, 0x93, 0xD2, 0xCE, 0x03, 0x3F, 0xED, 0xDA, 0x25, 0xB0, 0x1D, 0x57, 0xCB, 0x1E, 0x3A, 0x76, 0xA0, 0x4C, 0xEC,
+ 0x50, 0x76, 0xE8, 0x64, 0x72, 0x0C, 0xA4, 0xA9, 0xF1, 0xB8, 0x8B, 0xD6, 0xD6, 0x87, 0x84, 0xBB, 0x32, 0xE5, 0x41, 0x11,
+ 0xC0, 0x77, 0xD9, 0xB3, 0x60, 0x9D, 0xEB, 0x1B, 0xD5, 0xD1, 0x6E, 0x44, 0x44, 0xA9, 0xA6, 0x01, 0xEC, 0x55, 0x62, 0x1D,
+ 0x77, 0xB8, 0x5C, 0x8E, 0x48, 0x49, 0x7C, 0x9C, 0x3B, 0x57, 0x11, 0xAC, 0xAD, 0x73, 0x37, 0x8E, 0x2F, 0x78, 0x5C, 0x90,
+ 0x68, 0x47, 0xD9, 0x60, 0x60, 0xE6, 0xFC, 0x07, 0x3D, 0x22, 0x20, 0x17, 0xC4, 0xF7, 0x16, 0xE9, 0xC4, 0xD8, 0x72, 0xF9,
+ 0xC8, 0x73, 0x7C, 0xDF, 0x16, 0x2F, 0x15, 0xA9, 0x3E, 0xFD, 0x6A, 0x27, 0xB6, 0xA1, 0xEB, 0x5A, 0xBA, 0x98, 0x1F, 0xD5,
+ 0xE3, 0x4D, 0x64, 0x0A, 0x9D, 0x13, 0xC8, 0x61, 0xBA, 0xF5, 0x39, 0x1C, 0x87, 0xBA, 0xB8, 0xBD, 0x7B, 0x22, 0x7F, 0xF6,
+ 0xFE, 0xAC, 0x40, 0x79, 0xE5, 0xAC, 0x10, 0x6F, 0x3D, 0x8F, 0x1B, 0x79, 0x76, 0x8B, 0xC4, 0x37, 0xB3, 0x21, 0x18, 0x84,
+ 0xE5, 0x36, 0x00, 0xEB, 0x63, 0x20, 0x99, 0xB9, 0xE9, 0xFE, 0x33, 0x04, 0xBB, 0x41, 0xC8, 0xC1, 0x02, 0xF9, 0x44, 0x63,
+ 0x20, 0x9E, 0x81, 0xCE, 0x42, 0xD3, 0xD6, 0x3F, 0x2C, 0x76, 0xD3, 0x63, 0x9C, 0x59, 0xDD, 0x8F, 0xA6, 0xE1, 0x0E, 0xA0,
+ 0x2E, 0x41, 0xF7, 0x2E, 0x95, 0x47, 0xCF, 0xBC, 0xFD, 0x33, 0xF3, 0xF6, 0x0B, 0x61, 0x7E, 0x7E, 0x91, 0x2B, 0x81, 0x47,
+ 0xC2, 0x27, 0x30, 0xEE, 0xA7, 0x10, 0x5D, 0x37, 0x8F, 0x5C, 0x39, 0x2B, 0xE4, 0x04, 0xF0, 0x7B, 0x8D, 0x56, 0x8C, 0x68
+};
+
+//thawte_Primary_Root_CA-G2_ECC.der
+const unsigned char g_global_ci_root_ca_g2[] = {
+ 0x30, 0x82, 0x02, 0x88, 0x30, 0x82, 0x02, 0x0D, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x35, 0xFC, 0x26, 0x5C, 0xD9,
+ 0x84, 0x4F, 0xC9, 0x3D, 0x26, 0x3D, 0x57, 0x9B, 0xAE, 0xD7, 0x56, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D,
+ 0x04, 0x03, 0x03, 0x30, 0x81, 0x84, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31,
+ 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0C, 0x74, 0x68, 0x61, 0x77, 0x74, 0x65, 0x2C, 0x20, 0x49, 0x6E,
+ 0x63, 0x2E, 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x2F, 0x28, 0x63, 0x29, 0x20, 0x32, 0x30, 0x30,
+ 0x37, 0x20, 0x74, 0x68, 0x61, 0x77, 0x74, 0x65, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x20, 0x2D, 0x20, 0x46, 0x6F, 0x72,
+ 0x20, 0x61, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x7A, 0x65, 0x64, 0x20, 0x75, 0x73, 0x65, 0x20, 0x6F, 0x6E, 0x6C, 0x79,
+ 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1B, 0x74, 0x68, 0x61, 0x77, 0x74, 0x65, 0x20, 0x50, 0x72,
+ 0x69, 0x6D, 0x61, 0x72, 0x79, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, 0x32, 0x30, 0x1E,
+ 0x17, 0x0D, 0x30, 0x37, 0x31, 0x31, 0x30, 0x35, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x17, 0x0D, 0x33, 0x38, 0x30,
+ 0x31, 0x31, 0x38, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5A, 0x30, 0x81, 0x84, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55,
+ 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0C, 0x74, 0x68, 0x61,
+ 0x77, 0x74, 0x65, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x2F,
+ 0x28, 0x63, 0x29, 0x20, 0x32, 0x30, 0x30, 0x37, 0x20, 0x74, 0x68, 0x61, 0x77, 0x74, 0x65, 0x2C, 0x20, 0x49, 0x6E, 0x63,
+ 0x2E, 0x20, 0x2D, 0x20, 0x46, 0x6F, 0x72, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x7A, 0x65, 0x64, 0x20, 0x75,
+ 0x73, 0x65, 0x20, 0x6F, 0x6E, 0x6C, 0x79, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1B, 0x74, 0x68,
+ 0x61, 0x77, 0x74, 0x65, 0x20, 0x50, 0x72, 0x69, 0x6D, 0x61, 0x72, 0x79, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41,
+ 0x20, 0x2D, 0x20, 0x47, 0x32, 0x30, 0x76, 0x30, 0x10, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x05,
+ 0x2B, 0x81, 0x04, 0x00, 0x22, 0x03, 0x62, 0x00, 0x04, 0xA2, 0xD5, 0x9C, 0x82, 0x7B, 0x95, 0x9D, 0xF1, 0x52, 0x78, 0x87,
+ 0xFE, 0x8A, 0x16, 0xBF, 0x05, 0xE6, 0xDF, 0xA3, 0x02, 0x4F, 0x0D, 0x07, 0xC6, 0x00, 0x51, 0xBA, 0x0C, 0x02, 0x52, 0x2D,
+ 0x22, 0xA4, 0x42, 0x39, 0xC4, 0xFE, 0x8F, 0xEA, 0xC9, 0xC1, 0xBE, 0xD4, 0x4D, 0xFF, 0x9F, 0x7A, 0x9E, 0xE2, 0xB1, 0x7C,
+ 0x9A, 0xAD, 0xA7, 0x86, 0x09, 0x73, 0x87, 0xD1, 0xE7, 0x9A, 0xE3, 0x7A, 0xA5, 0xAA, 0x6E, 0xFB, 0xBA, 0xB3, 0x70, 0xC0,
+ 0x67, 0x88, 0xA2, 0x35, 0xD4, 0xA3, 0x9A, 0xB1, 0xFD, 0xAD, 0xC2, 0xEF, 0x31, 0xFA, 0xA8, 0xB9, 0xF3, 0xFB, 0x08, 0xC6,
+ 0x91, 0xD1, 0xFB, 0x29, 0x95, 0xA3, 0x42, 0x30, 0x40, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04,
+ 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02,
+ 0x01, 0x06, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x9A, 0xD8, 0x00, 0x30, 0x00, 0xE7, 0x6B,
+ 0x7F, 0x85, 0x18, 0xEE, 0x8B, 0xB6, 0xCE, 0x8A, 0x0C, 0xF8, 0x11, 0xE1, 0xBB, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48,
+ 0xCE, 0x3D, 0x04, 0x03, 0x03, 0x03, 0x69, 0x00, 0x30, 0x66, 0x02, 0x31, 0x00, 0xDD, 0xF8, 0xE0, 0x57, 0x47, 0x5B, 0xA7,
+ 0xE6, 0x0A, 0xC3, 0xBD, 0xF5, 0x80, 0x8A, 0x97, 0x35, 0x0D, 0x1B, 0x89, 0x3C, 0x54, 0x86, 0x77, 0x28, 0xCA, 0xA1, 0xF4,
+ 0x79, 0xDE, 0xB5, 0xE6, 0x38, 0xB0, 0xF0, 0x65, 0x70, 0x8C, 0x7F, 0x02, 0x54, 0xC2, 0xBF, 0xFF, 0xD8, 0xA1, 0x3E, 0xD9,
+ 0xCF, 0x02, 0x31, 0x00, 0xC4, 0x8D, 0x94, 0xFC, 0xDC, 0x53, 0xD2, 0xDC, 0x9D, 0x78, 0x16, 0x1F, 0x15, 0x33, 0x23, 0x53,
+ 0x52, 0xE3, 0x5A, 0x31, 0x5D, 0x9D, 0xCA, 0xAE, 0xBD, 0x13, 0x29, 0x44, 0x0D, 0x27, 0x5B, 0xA8, 0xE7, 0x68, 0x9C, 0x12,
+ 0xF7, 0x58, 0x3F, 0x2E, 0x72, 0x02, 0x57, 0xA3, 0x8F, 0xA1, 0x14, 0x2E
+};
+
+//thawte_Primary_Root_CA-G3_SHA256.der
+const unsigned char g_global_ci_root_ca_g3[] = {
+ 0x30, 0x82, 0x04, 0x2A, 0x30, 0x82, 0x03, 0x12, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x60, 0x01, 0x97, 0xB7, 0x46,
+ 0xA7, 0xEA, 0xB4, 0xB4, 0x9A, 0xD6, 0x4B, 0x2F, 0xF7, 0x90, 0xFB, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7,
+ 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, 0x81, 0xAE, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+ 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0C, 0x74, 0x68, 0x61, 0x77, 0x74, 0x65, 0x2C,
+ 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x1F, 0x43, 0x65, 0x72, 0x74,
+ 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x44,
+ 0x69, 0x76, 0x69, 0x73, 0x69, 0x6F, 0x6E, 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x2F, 0x28, 0x63,
+ 0x29, 0x20, 0x32, 0x30, 0x30, 0x38, 0x20, 0x74, 0x68, 0x61, 0x77, 0x74, 0x65, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x20,
+ 0x2D, 0x20, 0x46, 0x6F, 0x72, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x7A, 0x65, 0x64, 0x20, 0x75, 0x73, 0x65,
+ 0x20, 0x6F, 0x6E, 0x6C, 0x79, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1B, 0x74, 0x68, 0x61, 0x77,
+ 0x74, 0x65, 0x20, 0x50, 0x72, 0x69, 0x6D, 0x61, 0x72, 0x79, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D,
+ 0x20, 0x47, 0x33, 0x30, 0x1E, 0x17, 0x0D, 0x30, 0x38, 0x30, 0x34, 0x30, 0x32, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A,
+ 0x17, 0x0D, 0x33, 0x37, 0x31, 0x32, 0x30, 0x31, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5A, 0x30, 0x81, 0xAE, 0x31, 0x0B,
+ 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A,
+ 0x13, 0x0C, 0x74, 0x68, 0x61, 0x77, 0x74, 0x65, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03,
+ 0x55, 0x04, 0x0B, 0x13, 0x1F, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x53,
+ 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x44, 0x69, 0x76, 0x69, 0x73, 0x69, 0x6F, 0x6E, 0x31, 0x38, 0x30, 0x36,
+ 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x2F, 0x28, 0x63, 0x29, 0x20, 0x32, 0x30, 0x30, 0x38, 0x20, 0x74, 0x68, 0x61, 0x77,
+ 0x74, 0x65, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x20, 0x2D, 0x20, 0x46, 0x6F, 0x72, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6F,
+ 0x72, 0x69, 0x7A, 0x65, 0x64, 0x20, 0x75, 0x73, 0x65, 0x20, 0x6F, 0x6E, 0x6C, 0x79, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03,
+ 0x55, 0x04, 0x03, 0x13, 0x1B, 0x74, 0x68, 0x61, 0x77, 0x74, 0x65, 0x20, 0x50, 0x72, 0x69, 0x6D, 0x61, 0x72, 0x79, 0x20,
+ 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, 0x33, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09,
+ 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A,
+ 0x02, 0x82, 0x01, 0x01, 0x00, 0xB2, 0xBF, 0x27, 0x2C, 0xFB, 0xDB, 0xD8, 0x5B, 0xDD, 0x78, 0x7B, 0x1B, 0x9E, 0x77, 0x66,
+ 0x81, 0xCB, 0x3E, 0xBC, 0x7C, 0xAE, 0xF3, 0xA6, 0x27, 0x9A, 0x34, 0xA3, 0x68, 0x31, 0x71, 0x38, 0x33, 0x62, 0xE4, 0xF3,
+ 0x71, 0x66, 0x79, 0xB1, 0xA9, 0x65, 0xA3, 0xA5, 0x8B, 0xD5, 0x8F, 0x60, 0x2D, 0x3F, 0x42, 0xCC, 0xAA, 0x6B, 0x32, 0xC0,
+ 0x23, 0xCB, 0x2C, 0x41, 0xDD, 0xE4, 0xDF, 0xFC, 0x61, 0x9C, 0xE2, 0x73, 0xB2, 0x22, 0x95, 0x11, 0x43, 0x18, 0x5F, 0xC4,
+ 0xB6, 0x1F, 0x57, 0x6C, 0x0A, 0x05, 0x58, 0x22, 0xC8, 0x36, 0x4C, 0x3A, 0x7C, 0xA5, 0xD1, 0xCF, 0x86, 0xAF, 0x88, 0xA7,
+ 0x44, 0x02, 0x13, 0x74, 0x71, 0x73, 0x0A, 0x42, 0x59, 0x02, 0xF8, 0x1B, 0x14, 0x6B, 0x42, 0xDF, 0x6F, 0x5F, 0xBA, 0x6B,
+ 0x82, 0xA2, 0x9D, 0x5B, 0xE7, 0x4A, 0xBD, 0x1E, 0x01, 0x72, 0xDB, 0x4B, 0x74, 0xE8, 0x3B, 0x7F, 0x7F, 0x7D, 0x1F, 0x04,
+ 0xB4, 0x26, 0x9B, 0xE0, 0xB4, 0x5A, 0xAC, 0x47, 0x3D, 0x55, 0xB8, 0xD7, 0xB0, 0x26, 0x52, 0x28, 0x01, 0x31, 0x40, 0x66,
+ 0xD8, 0xD9, 0x24, 0xBD, 0xF6, 0x2A, 0xD8, 0xEC, 0x21, 0x49, 0x5C, 0x9B, 0xF6, 0x7A, 0xE9, 0x7F, 0x55, 0x35, 0x7E, 0x96,
+ 0x6B, 0x8D, 0x93, 0x93, 0x27, 0xCB, 0x92, 0xBB, 0xEA, 0xAC, 0x40, 0xC0, 0x9F, 0xC2, 0xF8, 0x80, 0xCF, 0x5D, 0xF4, 0x5A,
+ 0xDC, 0xCE, 0x74, 0x86, 0xA6, 0x3E, 0x6C, 0x0B, 0x53, 0xCA, 0xBD, 0x92, 0xCE, 0x19, 0x06, 0x72, 0xE6, 0x0C, 0x5C, 0x38,
+ 0x69, 0xC7, 0x04, 0xD6, 0xBC, 0x6C, 0xCE, 0x5B, 0xF6, 0xF7, 0x68, 0x9C, 0xDC, 0x25, 0x15, 0x48, 0x88, 0xA1, 0xE9, 0xA9,
+ 0xF8, 0x98, 0x9C, 0xE0, 0xF3, 0xD5, 0x31, 0x28, 0x61, 0x11, 0x6C, 0x67, 0x96, 0x8D, 0x39, 0x99, 0xCB, 0xC2, 0x45, 0x24,
+ 0x39, 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x42, 0x30, 0x40, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF,
+ 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03,
+ 0x02, 0x01, 0x06, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0xAD, 0x6C, 0xAA, 0x94, 0x60, 0x9C,
+ 0xED, 0xE4, 0xFF, 0xFA, 0x3E, 0x0A, 0x74, 0x2B, 0x63, 0x03, 0xF7, 0xB6, 0x59, 0xBF, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86,
+ 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x1A, 0x40, 0xD8, 0x95, 0x65, 0xAC,
+ 0x09, 0x92, 0x89, 0xC6, 0x39, 0xF4, 0x10, 0xE5, 0xA9, 0x0E, 0x66, 0x53, 0x5D, 0x78, 0xDE, 0xFA, 0x24, 0x91, 0xBB, 0xE7,
+ 0x44, 0x51, 0xDF, 0xC6, 0x16, 0x34, 0x0A, 0xEF, 0x6A, 0x44, 0x51, 0xEA, 0x2B, 0x07, 0x8A, 0x03, 0x7A, 0xC3, 0xEB, 0x3F,
+ 0x0A, 0x2C, 0x52, 0x16, 0xA0, 0x2B, 0x43, 0xB9, 0x25, 0x90, 0x3F, 0x70, 0xA9, 0x33, 0x25, 0x6D, 0x45, 0x1A, 0x28, 0x3B,
+ 0x27, 0xCF, 0xAA, 0xC3, 0x29, 0x42, 0x1B, 0xDF, 0x3B, 0x4C, 0xC0, 0x33, 0x34, 0x5B, 0x41, 0x88, 0xBF, 0x6B, 0x2B, 0x65,
+ 0xAF, 0x28, 0xEF, 0xB2, 0xF5, 0xC3, 0xAA, 0x66, 0xCE, 0x7B, 0x56, 0xEE, 0xB7, 0xC8, 0xCB, 0x67, 0xC1, 0xC9, 0x9C, 0x1A,
+ 0x18, 0xB8, 0xC4, 0xC3, 0x49, 0x03, 0xF1, 0x60, 0x0E, 0x50, 0xCD, 0x46, 0xC5, 0xF3, 0x77, 0x79, 0xF7, 0xB6, 0x15, 0xE0,
+ 0x38, 0xDB, 0xC7, 0x2F, 0x28, 0xA0, 0x0C, 0x3F, 0x77, 0x26, 0x74, 0xD9, 0x25, 0x12, 0xDA, 0x31, 0xDA, 0x1A, 0x1E, 0xDC,
+ 0x29, 0x41, 0x91, 0x22, 0x3C, 0x69, 0xA7, 0xBB, 0x02, 0xF2, 0xB6, 0x5C, 0x27, 0x03, 0x89, 0xF4, 0x06, 0xEA, 0x9B, 0xE4,
+ 0x72, 0x82, 0xE3, 0xA1, 0x09, 0xC1, 0xE9, 0x00, 0x19, 0xD3, 0x3E, 0xD4, 0x70, 0x6B, 0xBA, 0x71, 0xA6, 0xAA, 0x58, 0xAE,
+ 0xF4, 0xBB, 0xE9, 0x6C, 0xB6, 0xEF, 0x87, 0xCC, 0x9B, 0xBB, 0xFF, 0x39, 0xE6, 0x56, 0x61, 0xD3, 0x0A, 0xA7, 0xC4, 0x5C,
+ 0x4C, 0x60, 0x7B, 0x05, 0x77, 0x26, 0x7A, 0xBF, 0xD8, 0x07, 0x52, 0x2C, 0x62, 0xF7, 0x70, 0x63, 0xD9, 0x39, 0xBC, 0x6F,
+ 0x1C, 0xC2, 0x79, 0xDC, 0x76, 0x29, 0xAF, 0xCE, 0xC5, 0x2C, 0x64, 0x04, 0x5E, 0x88, 0x36, 0x6E, 0x31, 0xD4, 0x40, 0x1A,
+ 0x62, 0x34, 0x36, 0x3F, 0x35, 0x01, 0xAE, 0xAC, 0x63, 0xA0
+};
+
+//Samsung_OCF_RootCA.der
+const unsigned char g_regional_root_ca[] = {
+ 0x30, 0x82, 0x02, 0x5D, 0x30, 0x82, 0x02, 0x01, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x30, 0x0C, 0x06, 0x08,
+ 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x05, 0x00, 0x30, 0x6B, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04,
+ 0x03, 0x13, 0x1F, 0x53, 0x61, 0x6D, 0x73, 0x75, 0x6E, 0x67, 0x20, 0x45, 0x6C, 0x65, 0x63, 0x74, 0x72, 0x6F, 0x6E, 0x69,
+ 0x63, 0x73, 0x20, 0x4F, 0x43, 0x46, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03,
+ 0x55, 0x04, 0x0B, 0x13, 0x0B, 0x4F, 0x43, 0x46, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x1C, 0x30, 0x1A,
+ 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x13, 0x53, 0x61, 0x6D, 0x73, 0x75, 0x6E, 0x67, 0x20, 0x45, 0x6C, 0x65, 0x63, 0x74,
+ 0x72, 0x6F, 0x6E, 0x69, 0x63, 0x73, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4B, 0x52, 0x30,
+ 0x20, 0x17, 0x0D, 0x31, 0x36, 0x31, 0x31, 0x32, 0x34, 0x30, 0x32, 0x35, 0x35, 0x31, 0x31, 0x5A, 0x18, 0x0F, 0x32, 0x30,
+ 0x36, 0x39, 0x31, 0x32, 0x33, 0x31, 0x31, 0x34, 0x35, 0x39, 0x35, 0x39, 0x5A, 0x30, 0x6B, 0x31, 0x28, 0x30, 0x26, 0x06,
+ 0x03, 0x55, 0x04, 0x03, 0x13, 0x1F, 0x53, 0x61, 0x6D, 0x73, 0x75, 0x6E, 0x67, 0x20, 0x45, 0x6C, 0x65, 0x63, 0x74, 0x72,
+ 0x6F, 0x6E, 0x69, 0x63, 0x73, 0x20, 0x4F, 0x43, 0x46, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x14, 0x30,
+ 0x12, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x0B, 0x4F, 0x43, 0x46, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31,
+ 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x13, 0x53, 0x61, 0x6D, 0x73, 0x75, 0x6E, 0x67, 0x20, 0x45, 0x6C,
+ 0x65, 0x63, 0x74, 0x72, 0x6F, 0x6E, 0x69, 0x63, 0x73, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+ 0x4B, 0x52, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48,
+ 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x62, 0xC7, 0xFF, 0x2B, 0x1F, 0xAC, 0x50, 0x50, 0x50, 0x11, 0x26,
+ 0xEE, 0xCA, 0xD4, 0xC3, 0x3F, 0x02, 0xCF, 0x21, 0xED, 0x17, 0xFF, 0xCF, 0xC1, 0xD4, 0xBE, 0xDB, 0xDD, 0xA6, 0xF1, 0x13,
+ 0xDC, 0x34, 0x81, 0x06, 0x40, 0x7C, 0x8F, 0x16, 0x61, 0x49, 0x0A, 0x7C, 0xD7, 0xCF, 0xEC, 0x75, 0xE1, 0xD4, 0xCE, 0x52,
+ 0x0A, 0x73, 0xA4, 0x7F, 0x05, 0xAB, 0x6A, 0x5B, 0x46, 0x38, 0xA4, 0xDE, 0x5F, 0xA3, 0x81, 0x91, 0x30, 0x81, 0x8E, 0x30,
+ 0x0E, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, 0x01, 0xC6, 0x30, 0x32, 0x06, 0x03, 0x55,
+ 0x1D, 0x1F, 0x04, 0x2B, 0x30, 0x29, 0x30, 0x27, 0xA0, 0x25, 0xA0, 0x23, 0x86, 0x21, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F,
+ 0x2F, 0x70, 0x72, 0x6F, 0x64, 0x63, 0x61, 0x2E, 0x73, 0x61, 0x6D, 0x73, 0x75, 0x6E, 0x67, 0x69, 0x6F, 0x74, 0x73, 0x2E,
+ 0x63, 0x6F, 0x6D, 0x2F, 0x63, 0x72, 0x6C, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04, 0x05, 0x30,
+ 0x03, 0x01, 0x01, 0xFF, 0x30, 0x37, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x2B, 0x30, 0x29,
+ 0x30, 0x27, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x1B, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F,
+ 0x2F, 0x6F, 0x63, 0x73, 0x70, 0x2E, 0x73, 0x61, 0x6D, 0x73, 0x75, 0x6E, 0x67, 0x69, 0x6F, 0x74, 0x73, 0x2E, 0x63, 0x6F,
+ 0x6D, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x05, 0x00, 0x03, 0x48, 0x00, 0x30, 0x45,
+ 0x02, 0x20, 0x11, 0x63, 0xD6, 0x92, 0x13, 0x7D, 0x2A, 0xDF, 0x5A, 0xB9, 0xBF, 0xC0, 0x78, 0xB0, 0x97, 0x33, 0x06, 0xA3,
+ 0xA9, 0xEC, 0x0B, 0x03, 0xF6, 0x8F, 0x19, 0x22, 0xE3, 0x66, 0x1F, 0xB2, 0x30, 0x4B, 0x02, 0x21, 0x00, 0xB7, 0xD1, 0xE7,
+ 0xA8, 0xDC, 0x5E, 0x81, 0x62, 0xB3, 0xF9, 0xC3, 0xC7, 0x4B, 0x50, 0xDB, 0x14, 0xC8, 0xFD, 0xFD, 0x1B, 0xEC, 0x5E, 0xAD,
+ 0x58, 0xFA, 0xA3, 0xDA, 0xFC, 0x8A, 0x41, 0xE3, 0x51
+};
+
+#ifndef _EXCLUDE_TEST_KEY_
+//Samsung_OCF_TestRootCA.der
+const unsigned char g_regional_test_root_ca[] = {
+ 0x30, 0x82, 0x02, 0x68, 0x30, 0x82, 0x02, 0x0C, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x02, 0x30, 0x0C, 0x06, 0x08,
+ 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x05, 0x00, 0x30, 0x70, 0x31, 0x2D, 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04,
+ 0x03, 0x13, 0x24, 0x53, 0x61, 0x6D, 0x73, 0x75, 0x6E, 0x67, 0x20, 0x45, 0x6C, 0x65, 0x63, 0x74, 0x72, 0x6F, 0x6E, 0x69,
+ 0x63, 0x73, 0x20, 0x4F, 0x43, 0x46, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x54, 0x45, 0x53, 0x54, 0x31,
+ 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x0B, 0x4F, 0x43, 0x46, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43,
+ 0x41, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x13, 0x53, 0x61, 0x6D, 0x73, 0x75, 0x6E, 0x67, 0x20,
+ 0x45, 0x6C, 0x65, 0x63, 0x74, 0x72, 0x6F, 0x6E, 0x69, 0x63, 0x73, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+ 0x13, 0x02, 0x4B, 0x52, 0x30, 0x20, 0x17, 0x0D, 0x31, 0x36, 0x31, 0x31, 0x32, 0x34, 0x30, 0x32, 0x34, 0x37, 0x32, 0x37,
+ 0x5A, 0x18, 0x0F, 0x32, 0x30, 0x36, 0x39, 0x31, 0x32, 0x33, 0x31, 0x31, 0x34, 0x35, 0x39, 0x35, 0x39, 0x5A, 0x30, 0x70,
+ 0x31, 0x2D, 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x24, 0x53, 0x61, 0x6D, 0x73, 0x75, 0x6E, 0x67, 0x20, 0x45,
+ 0x6C, 0x65, 0x63, 0x74, 0x72, 0x6F, 0x6E, 0x69, 0x63, 0x73, 0x20, 0x4F, 0x43, 0x46, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20,
+ 0x43, 0x41, 0x20, 0x54, 0x45, 0x53, 0x54, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x0B, 0x4F, 0x43,
+ 0x46, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x13,
+ 0x53, 0x61, 0x6D, 0x73, 0x75, 0x6E, 0x67, 0x20, 0x45, 0x6C, 0x65, 0x63, 0x74, 0x72, 0x6F, 0x6E, 0x69, 0x63, 0x73, 0x31,
+ 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4B, 0x52, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86,
+ 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x1C,
+ 0xF3, 0xBA, 0xBC, 0xBB, 0xA7, 0xC1, 0xC0, 0x35, 0x59, 0xFE, 0xBF, 0x80, 0x88, 0x6B, 0x68, 0x7F, 0x47, 0xF4, 0x80, 0xB7,
+ 0x75, 0x55, 0xB2, 0xDF, 0xAF, 0x4E, 0xFE, 0x3F, 0x91, 0x1F, 0xA5, 0x81, 0x4D, 0x4E, 0x12, 0x24, 0xF7, 0xB7, 0xDF, 0xA6,
+ 0x39, 0x61, 0x3B, 0x27, 0xEA, 0x1D, 0x76, 0x94, 0x68, 0x7C, 0x55, 0xB6, 0x0D, 0xD7, 0x89, 0x92, 0x97, 0xD0, 0x51, 0x53,
+ 0xA7, 0xE0, 0xD3, 0xA3, 0x81, 0x92, 0x30, 0x81, 0x8F, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04,
+ 0x04, 0x03, 0x02, 0x01, 0xC6, 0x30, 0x2E, 0x06, 0x03, 0x55, 0x1D, 0x1F, 0x04, 0x27, 0x30, 0x25, 0x30, 0x23, 0xA0, 0x21,
+ 0xA0, 0x1F, 0x86, 0x1D, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x63, 0x61, 0x2E, 0x73, 0x61, 0x6D, 0x73, 0x75, 0x6E,
+ 0x67, 0x69, 0x6F, 0x74, 0x73, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x63, 0x72, 0x6C, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x13,
+ 0x01, 0x01, 0xFF, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x3C, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07,
+ 0x01, 0x01, 0x04, 0x30, 0x30, 0x2E, 0x30, 0x2C, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x20,
+ 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x6F, 0x63, 0x73, 0x70, 0x2D, 0x74, 0x65, 0x73, 0x74, 0x2E, 0x73, 0x61, 0x6D,
+ 0x73, 0x75, 0x6E, 0x67, 0x69, 0x6F, 0x74, 0x73, 0x2E, 0x63, 0x6F, 0x6D, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE,
+ 0x3D, 0x04, 0x03, 0x02, 0x05, 0x00, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x21, 0x00, 0x88, 0xB2, 0x2D, 0xC1, 0x70, 0xE4,
+ 0x0C, 0x5C, 0xEF, 0xE9, 0x0A, 0x25, 0x00, 0xF9, 0x2E, 0xF9, 0x6D, 0x81, 0x56, 0x4B, 0x6E, 0xC4, 0x18, 0x0A, 0xBD, 0x7B,
+ 0x61, 0x37, 0xFA, 0x14, 0x36, 0x4C, 0x02, 0x20, 0x5A, 0xB4, 0xE2, 0x78, 0x50, 0x19, 0xE7, 0x14, 0x47, 0xDC, 0x19, 0xD2,
+ 0x1C, 0x6F, 0x97, 0x10, 0x5D, 0x87, 0x3C, 0x3F, 0x7D, 0xCB, 0xF4, 0x98, 0x49, 0xAE, 0x93, 0xE7, 0xD6, 0x16, 0xFA, 0x31
+};
+
+//global_ocf_connect_cert_root.der
+const unsigned char g_trust_ca_chain1[] = {
+ 0x30, 0x82, 0x04, 0x20, 0x30, 0x82, 0x03, 0x08, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x34, 0x4E, 0xD5, 0x57, 0x20,
+ 0xD5, 0xED, 0xEC, 0x49, 0xF4, 0x2F, 0xCE, 0x37, 0xDB, 0x2B, 0x6D, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7,
+ 0x0D, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, 0xA9, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+ 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0C, 0x74, 0x68, 0x61, 0x77, 0x74, 0x65, 0x2C,
+ 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x1F, 0x43, 0x65, 0x72, 0x74,
+ 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x44,
+ 0x69, 0x76, 0x69, 0x73, 0x69, 0x6F, 0x6E, 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x2F, 0x28, 0x63,
+ 0x29, 0x20, 0x32, 0x30, 0x30, 0x36, 0x20, 0x74, 0x68, 0x61, 0x77, 0x74, 0x65, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x20,
+ 0x2D, 0x20, 0x46, 0x6F, 0x72, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x7A, 0x65, 0x64, 0x20, 0x75, 0x73, 0x65,
+ 0x20, 0x6F, 0x6E, 0x6C, 0x79, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x16, 0x74, 0x68, 0x61, 0x77,
+ 0x74, 0x65, 0x20, 0x50, 0x72, 0x69, 0x6D, 0x61, 0x72, 0x79, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1E,
+ 0x17, 0x0D, 0x30, 0x36, 0x31, 0x31, 0x31, 0x37, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x17, 0x0D, 0x33, 0x36, 0x30,
+ 0x37, 0x31, 0x36, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5A, 0x30, 0x81, 0xA9, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55,
+ 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0C, 0x74, 0x68, 0x61,
+ 0x77, 0x74, 0x65, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x1F,
+ 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63,
+ 0x65, 0x73, 0x20, 0x44, 0x69, 0x76, 0x69, 0x73, 0x69, 0x6F, 0x6E, 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, 0x04, 0x0B,
+ 0x13, 0x2F, 0x28, 0x63, 0x29, 0x20, 0x32, 0x30, 0x30, 0x36, 0x20, 0x74, 0x68, 0x61, 0x77, 0x74, 0x65, 0x2C, 0x20, 0x49,
+ 0x6E, 0x63, 0x2E, 0x20, 0x2D, 0x20, 0x46, 0x6F, 0x72, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x7A, 0x65, 0x64,
+ 0x20, 0x75, 0x73, 0x65, 0x20, 0x6F, 0x6E, 0x6C, 0x79, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x16,
+ 0x74, 0x68, 0x61, 0x77, 0x74, 0x65, 0x20, 0x50, 0x72, 0x69, 0x6D, 0x61, 0x72, 0x79, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20,
+ 0x43, 0x41, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05,
+ 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xAC, 0xA0, 0xF0, 0xFB, 0x80,
+ 0x59, 0xD4, 0x9C, 0xC7, 0xA4, 0xCF, 0x9D, 0xA1, 0x59, 0x73, 0x09, 0x10, 0x45, 0x0C, 0x0D, 0x2C, 0x6E, 0x68, 0xF1, 0x6C,
+ 0x5B, 0x48, 0x68, 0x49, 0x59, 0x37, 0xFC, 0x0B, 0x33, 0x19, 0xC2, 0x77, 0x7F, 0xCC, 0x10, 0x2D, 0x95, 0x34, 0x1C, 0xE6,
+ 0xEB, 0x4D, 0x09, 0xA7, 0x1C, 0xD2, 0xB8, 0xC9, 0x97, 0x36, 0x02, 0xB7, 0x89, 0xD4, 0x24, 0x5F, 0x06, 0xC0, 0xCC, 0x44,
+ 0x94, 0x94, 0x8D, 0x02, 0x62, 0x6F, 0xEB, 0x5A, 0xDD, 0x11, 0x8D, 0x28, 0x9A, 0x5C, 0x84, 0x90, 0x10, 0x7A, 0x0D, 0xBD,
+ 0x74, 0x66, 0x2F, 0x6A, 0x38, 0xA0, 0xE2, 0xD5, 0x54, 0x44, 0xEB, 0x1D, 0x07, 0x9F, 0x07, 0xBA, 0x6F, 0xEE, 0xE9, 0xFD,
+ 0x4E, 0x0B, 0x29, 0xF5, 0x3E, 0x84, 0xA0, 0x01, 0xF1, 0x9C, 0xAB, 0xF8, 0x1C, 0x7E, 0x89, 0xA4, 0xE8, 0xA1, 0xD8, 0x71,
+ 0x65, 0x0D, 0xA3, 0x51, 0x7B, 0xEE, 0xBC, 0xD2, 0x22, 0x60, 0x0D, 0xB9, 0x5B, 0x9D, 0xDF, 0xBA, 0xFC, 0x51, 0x5B, 0x0B,
+ 0xAF, 0x98, 0xB2, 0xE9, 0x2E, 0xE9, 0x04, 0xE8, 0x62, 0x87, 0xDE, 0x2B, 0xC8, 0xD7, 0x4E, 0xC1, 0x4C, 0x64, 0x1E, 0xDD,
+ 0xCF, 0x87, 0x58, 0xBA, 0x4A, 0x4F, 0xCA, 0x68, 0x07, 0x1D, 0x1C, 0x9D, 0x4A, 0xC6, 0xD5, 0x2F, 0x91, 0xCC, 0x7C, 0x71,
+ 0x72, 0x1C, 0xC5, 0xC0, 0x67, 0xEB, 0x32, 0xFD, 0xC9, 0x92, 0x5C, 0x94, 0xDA, 0x85, 0xC0, 0x9B, 0xBF, 0x53, 0x7D, 0x2B,
+ 0x09, 0xF4, 0x8C, 0x9D, 0x91, 0x1F, 0x97, 0x6A, 0x52, 0xCB, 0xDE, 0x09, 0x36, 0xA4, 0x77, 0xD8, 0x7B, 0x87, 0x50, 0x44,
+ 0xD5, 0x3E, 0x6E, 0x29, 0x69, 0xFB, 0x39, 0x49, 0x26, 0x1E, 0x09, 0xA5, 0x80, 0x7B, 0x40, 0x2D, 0xEB, 0xE8, 0x27, 0x85,
+ 0xC9, 0xFE, 0x61, 0xFD, 0x7E, 0xE6, 0x7C, 0x97, 0x1D, 0xD5, 0x9D, 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x42, 0x30, 0x40,
+ 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x0E, 0x06,
+ 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E,
+ 0x04, 0x16, 0x04, 0x14, 0x7B, 0x5B, 0x45, 0xCF, 0xAF, 0xCE, 0xCB, 0x7A, 0xFD, 0x31, 0x92, 0x1A, 0x6A, 0xB6, 0xF3, 0x46,
+ 0xEB, 0x57, 0x48, 0x50, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03,
+ 0x82, 0x01, 0x01, 0x00, 0x79, 0x11, 0xC0, 0x4B, 0xB3, 0x91, 0xB6, 0xFC, 0xF0, 0xE9, 0x67, 0xD4, 0x0D, 0x6E, 0x45, 0xBE,
+ 0x55, 0xE8, 0x93, 0xD2, 0xCE, 0x03, 0x3F, 0xED, 0xDA, 0x25, 0xB0, 0x1D, 0x57, 0xCB, 0x1E, 0x3A, 0x76, 0xA0, 0x4C, 0xEC,
+ 0x50, 0x76, 0xE8, 0x64, 0x72, 0x0C, 0xA4, 0xA9, 0xF1, 0xB8, 0x8B, 0xD6, 0xD6, 0x87, 0x84, 0xBB, 0x32, 0xE5, 0x41, 0x11,
+ 0xC0, 0x77, 0xD9, 0xB3, 0x60, 0x9D, 0xEB, 0x1B, 0xD5, 0xD1, 0x6E, 0x44, 0x44, 0xA9, 0xA6, 0x01, 0xEC, 0x55, 0x62, 0x1D,
+ 0x77, 0xB8, 0x5C, 0x8E, 0x48, 0x49, 0x7C, 0x9C, 0x3B, 0x57, 0x11, 0xAC, 0xAD, 0x73, 0x37, 0x8E, 0x2F, 0x78, 0x5C, 0x90,
+ 0x68, 0x47, 0xD9, 0x60, 0x60, 0xE6, 0xFC, 0x07, 0x3D, 0x22, 0x20, 0x17, 0xC4, 0xF7, 0x16, 0xE9, 0xC4, 0xD8, 0x72, 0xF9,
+ 0xC8, 0x73, 0x7C, 0xDF, 0x16, 0x2F, 0x15, 0xA9, 0x3E, 0xFD, 0x6A, 0x27, 0xB6, 0xA1, 0xEB, 0x5A, 0xBA, 0x98, 0x1F, 0xD5,
+ 0xE3, 0x4D, 0x64, 0x0A, 0x9D, 0x13, 0xC8, 0x61, 0xBA, 0xF5, 0x39, 0x1C, 0x87, 0xBA, 0xB8, 0xBD, 0x7B, 0x22, 0x7F, 0xF6,
+ 0xFE, 0xAC, 0x40, 0x79, 0xE5, 0xAC, 0x10, 0x6F, 0x3D, 0x8F, 0x1B, 0x79, 0x76, 0x8B, 0xC4, 0x37, 0xB3, 0x21, 0x18, 0x84,
+ 0xE5, 0x36, 0x00, 0xEB, 0x63, 0x20, 0x99, 0xB9, 0xE9, 0xFE, 0x33, 0x04, 0xBB, 0x41, 0xC8, 0xC1, 0x02, 0xF9, 0x44, 0x63,
+ 0x20, 0x9E, 0x81, 0xCE, 0x42, 0xD3, 0xD6, 0x3F, 0x2C, 0x76, 0xD3, 0x63, 0x9C, 0x59, 0xDD, 0x8F, 0xA6, 0xE1, 0x0E, 0xA0,
+ 0x2E, 0x41, 0xF7, 0x2E, 0x95, 0x47, 0xCF, 0xBC, 0xFD, 0x33, 0xF3, 0xF6, 0x0B, 0x61, 0x7E, 0x7E, 0x91, 0x2B, 0x81, 0x47,
+ 0xC2, 0x27, 0x30, 0xEE, 0xA7, 0x10, 0x5D, 0x37, 0x8F, 0x5C, 0x39, 0x2B, 0xE4, 0x04, 0xF0, 0x7B, 0x8D, 0x56, 0x8C, 0x68
+};
+
+//Samsung_OCF_RootCA.der
+const unsigned char g_trust_ca_chain2[] = {
+ 0x30, 0x82, 0x02, 0x5D, 0x30, 0x82, 0x02, 0x01, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x30, 0x0C, 0x06, 0x08,
+ 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x05, 0x00, 0x30, 0x6B, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04,
+ 0x03, 0x13, 0x1F, 0x53, 0x61, 0x6D, 0x73, 0x75, 0x6E, 0x67, 0x20, 0x45, 0x6C, 0x65, 0x63, 0x74, 0x72, 0x6F, 0x6E, 0x69,
+ 0x63, 0x73, 0x20, 0x4F, 0x43, 0x46, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03,
+ 0x55, 0x04, 0x0B, 0x13, 0x0B, 0x4F, 0x43, 0x46, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x1C, 0x30, 0x1A,
+ 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x13, 0x53, 0x61, 0x6D, 0x73, 0x75, 0x6E, 0x67, 0x20, 0x45, 0x6C, 0x65, 0x63, 0x74,
+ 0x72, 0x6F, 0x6E, 0x69, 0x63, 0x73, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4B, 0x52, 0x30,
+ 0x20, 0x17, 0x0D, 0x31, 0x36, 0x31, 0x31, 0x32, 0x34, 0x30, 0x32, 0x35, 0x35, 0x31, 0x31, 0x5A, 0x18, 0x0F, 0x32, 0x30,
+ 0x36, 0x39, 0x31, 0x32, 0x33, 0x31, 0x31, 0x34, 0x35, 0x39, 0x35, 0x39, 0x5A, 0x30, 0x6B, 0x31, 0x28, 0x30, 0x26, 0x06,
+ 0x03, 0x55, 0x04, 0x03, 0x13, 0x1F, 0x53, 0x61, 0x6D, 0x73, 0x75, 0x6E, 0x67, 0x20, 0x45, 0x6C, 0x65, 0x63, 0x74, 0x72,
+ 0x6F, 0x6E, 0x69, 0x63, 0x73, 0x20, 0x4F, 0x43, 0x46, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x14, 0x30,
+ 0x12, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x0B, 0x4F, 0x43, 0x46, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31,
+ 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x13, 0x53, 0x61, 0x6D, 0x73, 0x75, 0x6E, 0x67, 0x20, 0x45, 0x6C,
+ 0x65, 0x63, 0x74, 0x72, 0x6F, 0x6E, 0x69, 0x63, 0x73, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+ 0x4B, 0x52, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48,
+ 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x62, 0xC7, 0xFF, 0x2B, 0x1F, 0xAC, 0x50, 0x50, 0x50, 0x11, 0x26,
+ 0xEE, 0xCA, 0xD4, 0xC3, 0x3F, 0x02, 0xCF, 0x21, 0xED, 0x17, 0xFF, 0xCF, 0xC1, 0xD4, 0xBE, 0xDB, 0xDD, 0xA6, 0xF1, 0x13,
+ 0xDC, 0x34, 0x81, 0x06, 0x40, 0x7C, 0x8F, 0x16, 0x61, 0x49, 0x0A, 0x7C, 0xD7, 0xCF, 0xEC, 0x75, 0xE1, 0xD4, 0xCE, 0x52,
+ 0x0A, 0x73, 0xA4, 0x7F, 0x05, 0xAB, 0x6A, 0x5B, 0x46, 0x38, 0xA4, 0xDE, 0x5F, 0xA3, 0x81, 0x91, 0x30, 0x81, 0x8E, 0x30,
+ 0x0E, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, 0x01, 0xC6, 0x30, 0x32, 0x06, 0x03, 0x55,
+ 0x1D, 0x1F, 0x04, 0x2B, 0x30, 0x29, 0x30, 0x27, 0xA0, 0x25, 0xA0, 0x23, 0x86, 0x21, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F,
+ 0x2F, 0x70, 0x72, 0x6F, 0x64, 0x63, 0x61, 0x2E, 0x73, 0x61, 0x6D, 0x73, 0x75, 0x6E, 0x67, 0x69, 0x6F, 0x74, 0x73, 0x2E,
+ 0x63, 0x6F, 0x6D, 0x2F, 0x63, 0x72, 0x6C, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04, 0x05, 0x30,
+ 0x03, 0x01, 0x01, 0xFF, 0x30, 0x37, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x2B, 0x30, 0x29,
+ 0x30, 0x27, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x1B, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F,
+ 0x2F, 0x6F, 0x63, 0x73, 0x70, 0x2E, 0x73, 0x61, 0x6D, 0x73, 0x75, 0x6E, 0x67, 0x69, 0x6F, 0x74, 0x73, 0x2E, 0x63, 0x6F,
+ 0x6D, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x05, 0x00, 0x03, 0x48, 0x00, 0x30, 0x45,
+ 0x02, 0x20, 0x11, 0x63, 0xD6, 0x92, 0x13, 0x7D, 0x2A, 0xDF, 0x5A, 0xB9, 0xBF, 0xC0, 0x78, 0xB0, 0x97, 0x33, 0x06, 0xA3,
+ 0xA9, 0xEC, 0x0B, 0x03, 0xF6, 0x8F, 0x19, 0x22, 0xE3, 0x66, 0x1F, 0xB2, 0x30, 0x4B, 0x02, 0x21, 0x00, 0xB7, 0xD1, 0xE7,
+ 0xA8, 0xDC, 0x5E, 0x81, 0x62, 0xB3, 0xF9, 0xC3, 0xC7, 0x4B, 0x50, 0xDB, 0x14, 0xC8, 0xFD, 0xFD, 0x1B, 0xEC, 0x5E, 0xAD,
+ 0x58, 0xFA, 0xA3, 0xDA, 0xFC, 0x8A, 0x41, 0xE3, 0x51
+};
+
+//Samsung_OCF_TestRootCA.der
+const unsigned char g_trust_ca_chain3[] = {
+ 0x30, 0x82, 0x02, 0x68, 0x30, 0x82, 0x02, 0x0C, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x02, 0x30, 0x0C, 0x06, 0x08,
+ 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x05, 0x00, 0x30, 0x70, 0x31, 0x2D, 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04,
+ 0x03, 0x13, 0x24, 0x53, 0x61, 0x6D, 0x73, 0x75, 0x6E, 0x67, 0x20, 0x45, 0x6C, 0x65, 0x63, 0x74, 0x72, 0x6F, 0x6E, 0x69,
+ 0x63, 0x73, 0x20, 0x4F, 0x43, 0x46, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x54, 0x45, 0x53, 0x54, 0x31,
+ 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x0B, 0x4F, 0x43, 0x46, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43,
+ 0x41, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x13, 0x53, 0x61, 0x6D, 0x73, 0x75, 0x6E, 0x67, 0x20,
+ 0x45, 0x6C, 0x65, 0x63, 0x74, 0x72, 0x6F, 0x6E, 0x69, 0x63, 0x73, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+ 0x13, 0x02, 0x4B, 0x52, 0x30, 0x20, 0x17, 0x0D, 0x31, 0x36, 0x31, 0x31, 0x32, 0x34, 0x30, 0x32, 0x34, 0x37, 0x32, 0x37,
+ 0x5A, 0x18, 0x0F, 0x32, 0x30, 0x36, 0x39, 0x31, 0x32, 0x33, 0x31, 0x31, 0x34, 0x35, 0x39, 0x35, 0x39, 0x5A, 0x30, 0x70,
+ 0x31, 0x2D, 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x24, 0x53, 0x61, 0x6D, 0x73, 0x75, 0x6E, 0x67, 0x20, 0x45,
+ 0x6C, 0x65, 0x63, 0x74, 0x72, 0x6F, 0x6E, 0x69, 0x63, 0x73, 0x20, 0x4F, 0x43, 0x46, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20,
+ 0x43, 0x41, 0x20, 0x54, 0x45, 0x53, 0x54, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x0B, 0x4F, 0x43,
+ 0x46, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x13,
+ 0x53, 0x61, 0x6D, 0x73, 0x75, 0x6E, 0x67, 0x20, 0x45, 0x6C, 0x65, 0x63, 0x74, 0x72, 0x6F, 0x6E, 0x69, 0x63, 0x73, 0x31,
+ 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4B, 0x52, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86,
+ 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x1C,
+ 0xF3, 0xBA, 0xBC, 0xBB, 0xA7, 0xC1, 0xC0, 0x35, 0x59, 0xFE, 0xBF, 0x80, 0x88, 0x6B, 0x68, 0x7F, 0x47, 0xF4, 0x80, 0xB7,
+ 0x75, 0x55, 0xB2, 0xDF, 0xAF, 0x4E, 0xFE, 0x3F, 0x91, 0x1F, 0xA5, 0x81, 0x4D, 0x4E, 0x12, 0x24, 0xF7, 0xB7, 0xDF, 0xA6,
+ 0x39, 0x61, 0x3B, 0x27, 0xEA, 0x1D, 0x76, 0x94, 0x68, 0x7C, 0x55, 0xB6, 0x0D, 0xD7, 0x89, 0x92, 0x97, 0xD0, 0x51, 0x53,
+ 0xA7, 0xE0, 0xD3, 0xA3, 0x81, 0x92, 0x30, 0x81, 0x8F, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04,
+ 0x04, 0x03, 0x02, 0x01, 0xC6, 0x30, 0x2E, 0x06, 0x03, 0x55, 0x1D, 0x1F, 0x04, 0x27, 0x30, 0x25, 0x30, 0x23, 0xA0, 0x21,
+ 0xA0, 0x1F, 0x86, 0x1D, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x63, 0x61, 0x2E, 0x73, 0x61, 0x6D, 0x73, 0x75, 0x6E,
+ 0x67, 0x69, 0x6F, 0x74, 0x73, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x63, 0x72, 0x6C, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x13,
+ 0x01, 0x01, 0xFF, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x3C, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07,
+ 0x01, 0x01, 0x04, 0x30, 0x30, 0x2E, 0x30, 0x2C, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x20,
+ 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x6F, 0x63, 0x73, 0x70, 0x2D, 0x74, 0x65, 0x73, 0x74, 0x2E, 0x73, 0x61, 0x6D,
+ 0x73, 0x75, 0x6E, 0x67, 0x69, 0x6F, 0x74, 0x73, 0x2E, 0x63, 0x6F, 0x6D, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE,
+ 0x3D, 0x04, 0x03, 0x02, 0x05, 0x00, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x21, 0x00, 0x88, 0xB2, 0x2D, 0xC1, 0x70, 0xE4,
+ 0x0C, 0x5C, 0xEF, 0xE9, 0x0A, 0x25, 0x00, 0xF9, 0x2E, 0xF9, 0x6D, 0x81, 0x56, 0x4B, 0x6E, 0xC4, 0x18, 0x0A, 0xBD, 0x7B,
+ 0x61, 0x37, 0xFA, 0x14, 0x36, 0x4C, 0x02, 0x20, 0x5A, 0xB4, 0xE2, 0x78, 0x50, 0x19, 0xE7, 0x14, 0x47, 0xDC, 0x19, 0xD2,
+ 0x1C, 0x6F, 0x97, 0x10, 0x5D, 0x87, 0x3C, 0x3F, 0x7D, 0xCB, 0xF4, 0x98, 0x49, 0xAE, 0x93, 0xE7, 0xD6, 0x16, 0xFA, 0x31
+};
+
+#endif //_EXCLUDE_TEST_KEY_
+
+/*
+ * This API added as workaround to test certificate based TLS connection.
+ * It will be replaced to use TZ or eSE based key protection.
+ *
+ * NOTE : This API should be invoked after sm_generate_mac_based_device_id invoked.
+ */
+static OCStackResult save_signed_asymmetric_key(OicUuid_t *subject_uuid)
+{
+ OCStackResult res = OC_STACK_ERROR;
+ uint16_t cred_id = 0;
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "IN: %s", __func__);
+
+ // For D2S
+
+ /*
+ * 1. Save the Trust CA cert chain.
+ */
+ res = CredSaveTrustCertChain(subject_uuid, g_trust_ca_chain1, sizeof(g_trust_ca_chain1), OIC_ENCODING_DER, TRUST_CA, &cred_id);
+ if (OC_STACK_OK != res) {
+ THINGS_LOG_D(THINGS_ERROR, TAG, "SRPCredSaveTrustCertChain #1 error");
+ return res;
+ }
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "global_ocf_connect_cert_root.der saved w/ cred ID=%d", cred_id);
+
+ res = CredSaveTrustCertChain(subject_uuid, g_trust_ca_chain2, sizeof(g_trust_ca_chain2), OIC_ENCODING_DER, TRUST_CA, &cred_id);
+ if (OC_STACK_OK != res) {
+ THINGS_LOG_D(THINGS_ERROR, TAG, "SRPCredSaveTrustCertChain #2 error");
+ return res;
+ }
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Samsung_OCF_RootCA.der saved w/ cred ID=%d", cred_id);
+
+ res = CredSaveTrustCertChain(subject_uuid, g_trust_ca_chain3, sizeof(g_trust_ca_chain3), OIC_ENCODING_DER, TRUST_CA, &cred_id);
+ if (OC_STACK_OK != res) {
+ THINGS_LOG_D(THINGS_ERROR, TAG, "SRPCredSaveTrustCertChain #3 error");
+ return res;
+ }
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Samsung_OCF_TestRootCA.der saved w/ cred ID=%d", cred_id);
+
+#ifndef _EXCLUDE_TEST_KEY_
+ /*
+ * 2. Save the key for D2S (primary cert & key)
+ */
+ res = seckey_setup(dm_get_certificate_file_path(), &primary_cert, OIC_ENCODING_DER);
+ if (OC_STACK_OK != res) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "seckey_setup error");
+ return res;
+ }
+ res = seckey_setup(dm_get_privatekey_file_path(), &primary_key, OIC_ENCODING_RAW);
+ if (OC_STACK_OK != res) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "seckey_setup error");
+ return res;
+ }
+ res = CredSaveOwnCert(subject_uuid, &primary_cert, &primary_key, PRIMARY_CERT, &cred_id);
+ if (OC_STACK_OK != res) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "SRPCredSaveOwnCertChain error");
+ return res;
+ }
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Primary cert & key saved w/ cred ID=%d", cred_id);
+#endif //_EXCLUDE_TEST_KEY_
+
+ // For D2D
+ if (g_is_mfg_cert_required) {
+ /*
+ * 3. Save the MFG trust CA cert chain.
+ */
+#ifndef _EXCLUDE_TEST_KEY_
+ res = CredSaveTrustCertChain(subject_uuid, g_regional_test_root_ca, sizeof(g_regional_test_root_ca), OIC_ENCODING_DER, MF_TRUST_CA, &cred_id);
+#else
+ res = CredSaveTrustCertChain(subject_uuid, g_regional_root_ca, sizeof(g_regional_root_ca), OIC_ENCODING_DER, MF_TRUST_CA, &cred_id);
+#endif //_EXCLUDE_TEST_KEY_
+ if (OC_STACK_OK != res) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "SRPCredSaveOwnCertChain error");
+ return res;
+ }
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "MFG trust CA chain saved w/ cred ID=%d", cred_id);
+#ifndef _EXCLUDE_TEST_KEY_
+ /*
+ * 4. Save the key for D2D (manufacturer cert & key)
+ */
+ res = CredSaveOwnCert(subject_uuid, &primary_cert, &primary_key, MF_PRIMARY_CERT, &cred_id);
+ if (OC_STACK_OK != res) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "SRPCredSaveOwnCertChain error");
+ return res;
+ }
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "MFG primary cert & key saved w/ cred ID=%d", cred_id);
+#endif //_EXCLUDE_TEST_KEY_
+ }
+#ifndef _EXCLUDE_TEST_KEY_
+ if (primary_cert.data != NULL) {
+ things_free(primary_cert.data);
+ }
+
+ if (primary_key.data != NULL) {
+ things_free(primary_key.data);
+ }
+#endif //_EXCLUDE_TEST_KEY_
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Out: %s", __func__);
+
+ return res;
+}
+
+int sm_save_cloud_acl(const char *cloud_uuid)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "IN : %s", __func__);
+
+ if (!cloud_uuid) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "cloud_uuid is NULL");
+ return OIC_SEC_ERROR;
+ }
+
+ OicUuid_t oic_uuid;
+ if (OC_STACK_OK != ConvertStrToUuid(cloud_uuid, &oic_uuid)) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "cloud_uuid is NULL");
+ return OIC_SEC_ERROR;
+ }
+ // allocate memory for |acl| struct
+ OicSecAcl_t *acl = (OicSecAcl_t *) things_calloc(1, sizeof(OicSecAcl_t));
+ if (!acl) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, " %s : things_calloc error return", __func__);
+ return OIC_SEC_ERROR;
+ }
+ OicSecAce_t *ace = (OicSecAce_t *) things_calloc(1, sizeof(OicSecAce_t));
+ if (!ace) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "%s : things_calloc error return", __func__);
+ return OIC_SEC_ERROR;
+ }
+ LL_APPEND(acl->aces, ace);
+
+ memcpy(ace->subjectuuid.id, oic_uuid.id, sizeof(oic_uuid.id));
+
+ OicSecRsrc_t *rsrc = (OicSecRsrc_t *) things_calloc(1, sizeof(OicSecRsrc_t));
+ if (!rsrc) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "%s : things_calloc error return", __func__);
+ DeleteACLList(acl);
+ return OIC_SEC_ERROR;
+ }
+
+ char href[] = "*";
+ size_t len = strlen(href) + 1; // '1' for null termination
+ rsrc->href = (char *)things_calloc(len, sizeof(char));
+ if (!rsrc->href) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "%s : things_calloc error return", __func__);
+ FreeRsrc(rsrc);
+ DeleteACLList(acl);
+ return OIC_SEC_ERROR;
+ }
+ things_strncpy(rsrc->href, href, len);
+
+ size_t arrLen = 1;
+ rsrc->typeLen = arrLen;
+ rsrc->types = (char **)things_calloc(arrLen, sizeof(char *));
+ if (!rsrc->types) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "%s : things_calloc error return", __func__);
+ FreeRsrc(rsrc);
+ DeleteACLList(acl);
+ return OIC_SEC_ERROR;
+ }
+ rsrc->types[0] = OICStrdup("x.com.samsung.cloudconnection"); // ignore
+ if (!rsrc->types[0]) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "%s : OICStrdup error return", __func__);
+ FreeRsrc(rsrc);
+ DeleteACLList(acl);
+ return OIC_SEC_ERROR;
+ }
+
+ rsrc->interfaceLen = 1;
+ rsrc->interfaces = (char **)things_calloc(arrLen, sizeof(char *));
+ if (!rsrc->interfaces) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "%s : things_calloc error return", __func__);
+ FreeRsrc(rsrc);
+ DeleteACLList(acl);
+ return OIC_SEC_ERROR;
+ }
+ rsrc->interfaces[0] = OICStrdup("oic.if.baseline"); // ignore
+ if (!rsrc->interfaces[0]) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "%s : OICStrdup error return", __func__);
+ FreeRsrc(rsrc);
+ DeleteACLList(acl);
+ return OIC_SEC_ERROR;
+ }
+ LL_APPEND(ace->resources, rsrc);
+
+ ace->permission = 31; // CRUDN
+
+ OCStackResult installRes = InstallACL(acl);
+ if (OC_STACK_DUPLICATE_REQUEST == installRes) {
+ THINGS_LOG_D(THINGS_WARNING, TAG, "%s : [%s]'s ACL already installed.", __func__, cloud_uuid);
+ } else if (OC_STACK_OK != installRes) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "%s : OICStrdup error return", __func__);
+ /*SVACE warning fix */
+ DeleteACLList(acl);
+ return OIC_SEC_ERROR;
+ }
+ DeleteACLList(acl);
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "OUT : %s", __func__);
+
+ return OIC_SEC_OK;
+}
+
+void sm_set_otm_event_handler(OicSecOtmEventHandler_t otmEventHandler)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "IN : %s", __func__);
+
+ SetOtmEventHandler(otmEventHandler);
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "OUT : %s", __func__);
+}
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 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.
+ *
+ ****************************************************************************/
+
+#define _POSIX_C_SOURCE 200809L
+#define _BSD_SOURCE
+#include <string.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <pthread.h>
+
+#include "things_def.h"
+#include "things_common.h"
+#include "things_logger.h"
+#include "things_malloc.h"
+#include "things_string_util.h"
+#include "ocpayload.h"
+#include "things_resource.h"
+#include "things_server_builder.h"
+#include "resource_handler.h"
+
+#include "things_thread.h"
+#ifdef __ST_THINGS_RTOS__
+#include "things_rtos_util.h"
+#endif
+#define TAG "[things_svrbldr]"
+
+#define DEFAULT_DATA_MODEL_VERSIONS "res.1.1.0,sh.1.1.0"
+
+#define KEY_ATTR_DEVICE_NAME "n"
+#define KEY_ATTR_PLATFORM_VENDERID "vid"
+
+static pthread_t g_thread_id_server;
+static pthread_t g_thread_id_presence;
+
+static int g_quit_flag = 0;
+static uint g_presence_flag = 0;
+static int g_presence_duration = 20;
+static volatile bool is_presence = false;
+
+things_server_builder_s *g_builder = NULL;
+
+void *server_execute_loop(void *param)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+
+ while (!g_quit_flag) {
+ if (OCProcess() != OC_STACK_OK) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "OCProcess Error");
+ // need to insert error handling logic from here
+ }
+ // The proper time period for looping need to be decided..
+ usleep(10 * 1000);
+ }
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_EXIT);
+
+ return NULL;
+}
+
+void *presence_noti_loop(void *param)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+
+ if (OCStartPresence(0) == OC_STACK_OK) {
+ /* while (!g_quit_flag)
+ {
+ g_presence_flag++;
+ //THINGS_LOG_D(THINGS_DEBUG, TAG, "COUNT : %d", g_presence_flag);
+ if (g_presence_flag > g_presence_duration)
+ {
+ g_presence_flag = 0;
+ OCStopPresence();
+ THINGS_LOG(THINGS_INFO, TAG, "Stop Sending Presence Packet");
+ is_presence = false;
+ break;
+ }
+ sleep(1);
+ }
+ */
+ } else {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "OCStartPresence Error");
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_EXIT);
+
+ return NULL;
+}
+
+void register_req_handler(struct things_server_builder_s *builder, request_handler_cb handler)
+{
+ if (handler == NULL || builder == NULL) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "Invalid Param");
+ return;
+ }
+ builder->handler = handler;
+}
+
+struct things_resource_s *create_resource(struct things_server_builder_s *builder, char *uri, char *type, char *interface, int isDiscoverable, int isObserable, int isSecure)
+{
+ things_resource_s *res = NULL;
+ OCResourceHandle hd = NULL;
+ uint8_t rsc_properties = OC_DISCOVERABLE;
+
+ if (builder->handler == NULL) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Handler for serverbuilder is not registered");
+ return res;
+ }
+
+ if (1 != isDiscoverable) {
+ rsc_properties = OC_ACTIVE;
+ }
+
+ if (1 == isObserable) {
+ rsc_properties |= OC_OBSERVABLE;
+ }
+ // if( strstr(uri, URI_ACCESSPOINTLIST) == 0
+ // && strstr(uri, URI_PROVINFO) == 0 )
+ if (1 == isSecure) {
+#ifdef __SECURED__
+ rsc_properties |= OC_SECURE;
+#else
+ THINGS_LOG(THINGS_DEBUG, TAG, "Stack is in UNSECURED Mode");
+#endif
+ }
+
+ OCStackResult ret = OCCreateResource(&hd,
+ type,
+ interface,
+ uri,
+ builder->handler,
+ NULL,
+ rsc_properties);
+
+ if (ret != OC_STACK_OK) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Resource Creation Failed - ret = %d, %s", ret, uri);
+ return NULL;
+ }
+
+ res = things_create_resource_inst(NULL, hd, NULL, NULL);
+
+ if (NULL == res) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "things_create_resource_inst is failed");
+ return res;
+ }
+
+ res->res_type = type;
+
+ builder->gres_arr[builder->res_num++] = res;
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Created hd [%x], prop [0x%X] uri : %s", res->resource_handle, rsc_properties, res->uri);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "DISCOVERABLE : %s", (isDiscoverable == 1 ? "YES" : "NO"));
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "OBSERABLE : %s", (isObserable == 1 ? "YES" : "NO"));
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "SECURE : %s", (isSecure == 1 ? "YES" : "NO"));
+ return res;
+}
+
+struct things_resource_s *create_collection_resource(struct things_server_builder_s *builder, char *uri, char *type, char *interface)
+{
+ things_resource_s *res = NULL;
+ OCResourceHandle hd = NULL;
+ uint8_t rsc_properties = OC_DISCOVERABLE | OC_OBSERVABLE;
+
+ if (builder->handler == NULL) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Handler for serverbuilder is not registered");
+ return res;
+ }
+#ifdef __SECURED__
+
+ rsc_properties |= OC_SECURE;
+
+#endif //#ifdef __SECURED__
+
+ OCStackResult ret = OCCreateResource(&hd,
+ uri,
+ type,
+ uri,
+ builder->handler,
+ NULL,
+ rsc_properties);
+
+ if (ret != OC_STACK_OK) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Resource Creation Failed - ret = %d, %s", ret, uri);
+ return NULL;
+ }
+ // Baseline interface will be binded automatically by IoTivity Stack.
+
+ res = things_create_resource_inst(NULL, hd, NULL, NULL);
+
+ if (NULL == res) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "things_create_resource_inst is failed");
+ return res;
+ }
+
+ res->res_type = type;
+
+ builder->gres_arr[builder->res_num++] = res;
+
+ THINGS_LOG_D(THINGS_INFO, TAG, "Created hd [%x], prop [0x%X] uri : %s", res->resource_handle, rsc_properties, uri);
+
+ return res;
+}
+
+void delete_resource(struct things_server_builder_s *builder)
+{
+ for (size_t iter = 0; iter < builder->res_num; iter++) {
+ OCStackResult ret = OCDeleteResource((OCResourceHandle)(builder->gres_arr[iter]->resource_handle));
+ if (ret != OC_STACK_OK) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Failed to delete the resource");
+ }
+ }
+}
+
+int add_interface_type(things_resource_s *resource, char *interface)
+{
+ if (NULL != resource && NULL != interface) {
+ if (NULL != resource->resource_handle) {
+ if (OC_STACK_OK == OCBindResourceInterfaceToResource(resource->resource_handle, interface)) {
+ return OC_STACK_OK;
+ }
+ }
+ }
+
+ return OC_STACK_ERROR;
+}
+
+int add_resource_type(things_resource_s *resource, char *type)
+{
+ if (NULL != resource && NULL != type) {
+ if (NULL != resource->resource_handle) {
+ if (OC_STACK_OK == OCBindResourceTypeToResource(resource->resource_handle, type)) {
+ return OC_STACK_OK;
+ }
+ }
+ }
+
+ return OC_STACK_ERROR;
+}
+
+void things_bind(struct things_resource_s *res, struct things_resource_s *bind)
+{
+ if (res == NULL || bind == NULL) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Invalid Resource");
+ return;
+ }
+
+ if (res->resource_handle == bind->resource_handle) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "It's identical resource");
+ return;
+ }
+
+ OCStackResult ret = OCBindResource((OCResourceHandle)(res->resource_handle),
+ (OCResourceHandle)(bind->resource_handle));
+ if (ret != OC_STACK_OK) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "bind Failed ");
+ }
+}
+
+void bind_all(struct things_resource_s *res, struct things_resource_s *bind[], size_t size)
+{
+ for (size_t iter = 0; iter < size; iter++) {
+ things_bind(res, bind[iter]);
+ // This time value achieved via testing
+ // May need to re-test to find the opt. value for give platform.
+ usleep(100 * 1000);
+ }
+}
+
+struct things_resource_s *get_resource(things_server_builder_s *builder, const char *uri)
+{
+ things_resource_s *ret = NULL;
+ for (size_t iter = 0; iter < builder->res_num; iter++) {
+ const char *rURI = OCGetResourceUri((OCResourceHandle)(builder->gres_arr[iter]->resource_handle));
+
+ if (compare_strings(rURI, uri) == 0) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "URI Compare : %s , %s", uri, rURI);
+ ret = builder->gres_arr[iter];
+ break;
+ }
+ }
+ return ret;
+}
+
+int broadcast_presence(things_server_builder_s *builder, int max_cnt)
+{
+ if (max_cnt <= 0) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "check your max_cnt value.(must max_cnt > 0)");
+ return 1;
+ }
+
+ if (!is_presence) {
+ is_presence = true;
+ g_presence_flag = 0;
+ g_presence_duration = max_cnt;
+#ifdef __ST_THINGS_RTOS__
+ pthread_create_rtos(&g_thread_id_presence, NULL, presence_noti_loop, (void *)NULL, THINGS_STACK_PRESENCE_NOTI_THREAD);
+#else
+ things_thread_create(&g_thread_id_presence, NULL, presence_noti_loop, (void *)NULL);
+#endif
+ } else if ((uint) g_presence_duration < g_presence_flag + ((uint) max_cnt)) {
+ g_presence_duration = max_cnt;
+ g_presence_flag = 0;
+ }
+
+ return 0;
+}
+
+void init_builder(struct things_server_builder_s *builder, request_handler_cb cb)
+{
+ //if (OCInit(NULL, 0, OC_SERVER) != OC_STACK_OK)
+ //if(OC_STACK_OK != OCInit1 (OC_CLIENT_SERVER,OC_IP_USE_V4, OC_IP_USE_V4) )
+ OCTransportAdapter m_transport = (OC_ADAPTER_IP | OC_ADAPTER_TCP);
+ if (OC_STACK_OK != OCInit2(OC_CLIENT_SERVER, OC_IP_USE_V4, OC_IP_USE_V4, m_transport)) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "RESOURCE SERVER START FAILED");
+ return;
+ }
+
+ THINGS_LOG(THINGS_INFO, TAG, "Resource Server IS NOW STARTING...");
+
+ g_quit_flag = 0;
+
+#ifdef __ST_THINGS_RTOS__
+ pthread_create_rtos(&g_thread_id_server, NULL, server_execute_loop, (void *)NULL, THINGS_STACK_SERVEREXCETUE_LOOP_THREAD);
+#else
+ things_thread_create(&g_thread_id_server, NULL, server_execute_loop, (void *)NULL);
+#endif
+
+ register_req_handler(builder, cb);
+}
+
+void deinit_builder(things_server_builder_s *builder)
+{
+ if (builder != NULL) {
+ g_quit_flag = 1;
+ pthread_cancel(g_thread_id_server);
+ pthread_join(g_thread_id_server, NULL);
+ pthread_detach(g_thread_id_server);
+ g_thread_id_server = NULL;
+
+ pthread_cancel(g_thread_id_presence);
+ pthread_join(g_thread_id_presence, NULL);
+ pthread_detach(g_thread_id_presence);
+ g_thread_id_presence = NULL;
+
+ // 1. Need to unregister those registered resource in the Stack
+ // 2. Free the payload of each resources
+ for (size_t iter = 0; iter < builder->res_num; iter++) {
+
+ if (builder->gres_arr[iter]->rep != NULL) {
+ things_release_representation_inst(builder->gres_arr[iter]->rep);
+ }
+ }
+ }
+
+ if (OCStop() != OC_STACK_OK) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "OCStack process error");
+ }
+}
+
+void set_device_info(things_server_builder_s *builder, char *device_name, char *device_type)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[/oic/d] name :%s", device_name);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[/oic/d] type :%s", device_type);
+
+ OCDeviceInfo device_info;
+ device_info.deviceName = NULL;
+ device_info.types = NULL;
+ device_info.specVersion = NULL;
+ device_info.dataModelVersions = NULL;
+
+ duplicate_string(device_name, &device_info.deviceName);
+ duplicate_string(OC_SPEC_VERSION, &device_info.specVersion);
+ device_info.dataModelVersions = OCCreateOCStringLL(DEFAULT_DATA_MODEL_VERSIONS);
+ device_info.types = OCCreateOCStringLL(device_type);
+ OCResourcePayloadAddStringLL(&device_info.types, OC_RSRVD_RESOURCE_TYPE_DEVICE);
+ OCSetDeviceInfo(device_info);
+
+ // OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, KEY_ATTR_DEVICE_NAME, device_name);
+
+ free(device_info.deviceName);
+ free(device_info.specVersion);
+ OCFreeOCStringLL(device_info.dataModelVersions);
+ OCFreeOCStringLL(device_info.types);
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_EXIT);
+}
+
+void set_platform_info(things_server_builder_s *builder, char *model_num, char *pver, char *osver, char *hwver, char *fwver, char *venderid)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+
+ if (model_num == NULL || strlen(model_num) < 1) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "Invalid input for registering platform Info");
+ return;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[/oic/p] Manufacturer :%s", MANUFACTURER_NAME);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[/oic/p] Model Name :%s", model_num);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[/oic/p] Ver. Plaform :%s", pver);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[/oic/p] Ver. OS :%s", osver);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[/oic/p] Ver. HW :%s", hwver);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[/oic/p] Ver. FW :%s", fwver);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[/oic/p] Ver. vid :%s", venderid);
+
+ OCPlatformInfo platform_info;
+
+ platform_info.platformID = (char *)OCGetServerInstanceIDString();
+ platform_info.manufacturerName = MANUFACTURER_NAME;
+ platform_info.modelNumber = model_num;
+ platform_info.platformVersion = pver;
+ platform_info.operatingSystemVersion = osver;
+ platform_info.hardwareVersion = hwver;
+ platform_info.firmwareVersion = fwver;
+
+ platform_info.manufacturerUrl = MANUFACTURER_URL;
+ platform_info.dateOfManufacture = NULL;
+ platform_info.supportUrl = NULL;
+ platform_info.systemTime = NULL;
+
+ OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, KEY_ATTR_PLATFORM_VENDERID, venderid);
+
+ OCSetPlatformInfo(platform_info);
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_EXIT);
+}
+
+things_server_builder_s *get_builder_instance()
+{
+ if (g_builder == NULL) {
+ g_builder = (things_server_builder_s *) things_malloc(sizeof(things_server_builder_s));
+ if (g_builder != NULL) {
+ g_builder->init_module = &init_builder;
+ g_builder->deinit_module = &deinit_builder;
+ g_builder->set_device_info = &set_device_info;
+ g_builder->set_platform_info = &set_platform_info;
+ g_builder->create_resource = &create_resource;
+ // g_builder->CreateActiveResource = &CreateActiveResource;
+ g_builder->create_collection_resource = &create_collection_resource;
+ g_builder->get_resource = &get_resource;
+ g_builder->delete_resource = &delete_resource;
+ g_builder->add_interface_type = &add_interface_type;
+ g_builder->add_resource_type = &add_resource_type;
+ g_builder->bind = &things_bind;
+ g_builder->bind_all = &bind_all;
+ g_builder->broadcast_presence = &broadcast_presence;
+ g_builder->res_num = 0;
+ g_builder->handler = NULL;
+
+ is_presence = false;
+
+ return g_builder;
+ } else {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Not enough Memory for Builder Instance");
+ return NULL;
+ }
+ } else {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Builder Instance Already Created");
+ return g_builder;
+ }
+}
+
+void release_builder_instance(things_server_builder_s *builder)
+{
+ if (builder) {
+ // Thread should be terminated first..
+ if (!g_quit_flag) {
+ builder->deinit_module(builder);
+ }
+
+ if (builder->res_num > 0) {
+ for (size_t iter = 0; iter < builder->res_num; iter++) {
+ if (builder->gres_arr[iter] != NULL) {
+ /*! Added by st_things for memory Leak fix
+ */
+ release_resource_inst_impl(builder->gres_arr[iter]);
+ builder->gres_arr[iter] = NULL;
+ }
+ }
+ }
+
+ things_free(builder);
+ g_builder = NULL;
+ is_presence = false;
+ }
+}
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 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.
+ *
+ ****************************************************************************/
+
+#ifndef _THINGS_DEF_
+#define _THINGS_DEF_
+
+/**
+ * Defines used in more than 2 devices are defined here
+ * All the other device specific values are defined
+ * in the "oicXXdef.h"
+ */
+
+#define OIC_STACK_FIRMWARE_VERSION "OIC_0.9.1.D.17.03.31_1_30dbca2"
+
+#define MANUFACTURER_NAME "Samsung Electronics"
+#define MANUFACTURER_URL "http://www.samsung.com"
+
+/* Resource Types */
+#define OIC_INTERFACE_BASELINE "oic.if.baseline"
+#define OIC_INTERFACE_LINKEDLIST "oic.if.ll"
+#define OIC_INTERFACE_LINKEDBATCH "oic.if.lb"
+#define OIC_INTERFACE_BATCH "oic.if.b"
+#define OIC_INTERFACE_ACTUATOR "oic.if.a"
+#define OIC_INTERFACE_SENSOR "oic.if.s"
+
+#define OIC_RTYPE_COLLECTION_WK "oic.wk.col"
+#define OIC_RTYPE_MAINTENANCE_WK "oic.wk.mnt"
+#define OIC_RTYPE_BINARY_SWITCH "oic.r.switch.binary"
+#define OIC_RTYPE_MODE "oic.r.mode"
+#define OIC_RTYPE_TEMPERATURE "oic.r.temperature"
+#define OIC_RTYPE_LIGHT_DIMMING "oic.r.light.dimming"
+
+#define SEC_RTYPE_ALARM "x.com.samsung.da.alarms"
+#define SEC_RTYPE_THINGS_DEVICE "x.com.samsung.devcol"
+#define SEC_RTYPE_TEMPERATURE "x.com.samsung.da.temperatures"
+#define SEC_RTYPE_BIXBY "x.com.samsung.bixby"
+#define SEC_RTYPE_FILE_LIST "x.com.samsung.file.list"
+#define SEC_RTYPE_FILE_TRANSFER "x.com.samsung.file.transfer"
+#define SEC_RTYPE_CONTENTS_PROVIDER "x.com.samsung.contents.provider"
+#define SEC_RTYPE_CONTENTS_RENDERER "x.com.samsung.contents.renderer"
+#define SEC_RTYPE_DISHWASHER "x.com.samsung.da.dishwasher"
+#define SEC_RTYPE_PROV_INFO "x.com.samsung.provisioninginfo"
+
+/* Atrribute Keys */
+#define SEC_ATTRIBUTE_LENGTH "x.com.samsung.da.length"
+#define SEC_ATTRIBUTE_TYPE "x.com.samsung.da.type"
+#define SEC_ATTRIBUTE_ID "x.com.samsung.da.id"
+#define SEC_ATTRIBUTE_NUMBER "x.com.samsung.da.number"
+#define SEC_ATTRIBUTE_DESCRIPTION "x.com.samsung.da.description"
+
+#define SEC_ATTRIBUTE_THINGS_NAME "x.com.samsung.da.name"
+#define SEC_ATTRIBUTE_MODEL_NUM "x.com.samsung.da.model_num"
+#define SEC_ATTRIBUTE_DESCRIPTION "x.com.samsung.da.description"
+#define SEC_ATTRIBUTE_SERIAL_NUM "x.com.samsung.da.serialNum"
+#define SEC_ATTRIBUTE_VERSION_ID "x.com.samsung.da.versionId"
+#define SEC_ATTRIBUTE_APPROVED_STATE "x.com.samsung.da.approvedState"
+#define SEC_ATTRIBUTE_VERSION_AVAILABLE "x.com.samsung.da.newVersionAvailable"
+#define SEC_ATTRIBUTE_ITEMS "x.com.samsung.da.items"
+
+// Common Attribute Keys
+#define SEC_ATTRIBUTE_COMMON_ITEMS "x.com.samsung.items"
+#define SEC_ATTRIBUTE_COMMON_ID "x.com.samsung.id"
+#define SEC_ATTRIBUTE_COMMON_TARGET "x.com.samsung.target"
+#define SEC_ATTRIBUTE_COMMON_VALUE "x.com.samsung.value"
+#define SEC_ATTRIBUTE_LOG_COLLECT "x.com.samsung.collectlogs"
+#define SEC_ATTRIBUTE_LOG_IDS "x.com.samsung.logids"
+#define SEC_ATTRIBUTE_FILE_BLOB "x.com.samsung.blob"
+#define SEC_ATTRIBUTE_NAME "x.com.samsung.name"
+
+#define SEC_ATTRIBUTE_PROV_TARGETS "x.com.samsung.provisioning.targets"
+#define SEC_ATTRIBUTE_PROV_EZSETDI "x.com.samsung.provisioning.easysetupdi"
+#define SEC_ATTRIBUTE_PROV_RESET "x.com.samsung.provisioning.reset"
+#define SEC_ATTRIBUTE_PROV_TARGET_OWNED "x.com.samsung.provisioning.owned"
+#define SEC_ATTRIBUTE_PROV_TERMINATE_AP "x.com.samsung.provisioning.stopAP"
+#define SEC_ATTRIBUTE_PROV_ABORT "x.com.samsung.provisioning.abort"
+#define SEC_ATTRIBUTE_PROV_TARGET_ID "x.com.samsung.targetDi"
+#define SEC_ATTRIBUTE_PROV_TARGET_RT "x.com.samsung.targetRt"
+#define SEC_ATTRIBUTE_PROV_TARGET_PUBED "x.com.samsung.published"
+
+#define SEC_ATTRIBUTE_AP_ITEMS "x.com.samsung.accesspoint.items"
+#define SEC_ATTRIBUTE_AP_CHANNAL "x.com.samsung.channel"
+#define SEC_ATTRIBUTE_AP_ENCTYPE "x.com.samsung.encryptionType"
+#define SEC_ATTRIBUTE_AP_MACADDR "x.com.samsung.macAddress"
+#define SEC_ATTRIBUTE_AP_MAXRATE "x.com.samsung.maxRate"
+#define SEC_ATTRIBUTE_AP_RSSI "x.com.samsung.rssi"
+#define SEC_ATTRIBUTE_AP_SECTYPE "x.com.samsung.securityType"
+#define SEC_ATTRIBUTE_AP_SSID "x.com.samsung.ssid"
+
+#define SEC_ATTRIBUTE_CONTENTS "x.com.samsung.contents"
+#define SEC_ATTRIBUTE_CONTENTS_RT "x.com.samsung.rt"
+#define SEC_ATTRIBUTE_CONTENTS_PROVIDER "x.com.samsung.provider"
+#define SEC_ATTRIBUTE_CONTENTS_HOST "x.com.samsung.host"
+#define SEC_ATTRIBUTE_CONTENTS_PATH "x.com.samsung.path"
+#define SEC_ATTRIBUTE_CONTENTS_QUERY "x.com.samsung.query"
+#define SEC_ATTRIBUTE_CONTENTS_MIME_TYPE "x.com.samsung.mimeType"
+#define SEC_ATTRIBUTE_CONTENTS_TRANSPORT "x.com.samsung.transport"
+#define SEC_ATTRIBUTE_CONTENTS_ENCODING "x.com.samsung.encoding"
+#define SEC_ATTRIBUTE_CONTENTS_PAYLOAD "x.com.samsung.payload"
+#define SEC_ATTRIBUTE_CONTENTS_ACTION "x.com.samsung.action"
+#define SEC_ATTRIBUTE_CONTENTS_CAPA_TYPE "x.com.samsung.capability.type"
+#define SEC_ATTRIBUTE_CONTENTS_DATETIME "x.com.samsung.datetime"
+
+#define OIC_QUERY_KEY_OP "op"
+#define OIC_QUERY_VALUE_UPDATE "update"
+
+/* Resource URI */
+#define URI_OIC "/oic"
+#define URI_SEC "/sec"
+#define URI_WK_MAINTENANCE "/mnt"
+#define URI_OVEN "/oven"
+#define URI_DEVICE_COL "/device"
+#define URI_TEMPERATURE "/temperature"
+#define URI_TEMPERATURES "/temperatures"
+#define URI_BIXBY "/bixby"
+#define URI_ACTIONS "/actions"
+#define URI_ALARMS "/alarms"
+#define URI_INFORMATION "/information"
+#define URI_SENSOR "/sensors"
+#define URI_VENDER_SPECIFIC "/vs"
+#define URI_COOK "/cook"
+#define URI_DOOR "/door"
+#define URI_DOORS "/doors"
+#define URI_FILE "/file"
+#define URI_LIST "/list"
+#define URI_TRANSFER "/transfer"
+#define URI_CONTENTS "/contents"
+#define URI_PROVIDER "/provider"
+#define URI_RENDERER "/renderer"
+#define URI_PROVINFO "/provisioninginfo"
+
+/* Temperature Type Resources */
+#define URI_FRIDGE_COOLER "/cooler"
+#define URI_FRIDGE_FREEZER "/freezer"
+#define URI_FRIDGE_CVROOM "/cvroom"
+#define URI_OVEN_PROBE "/prob"
+#define URI_ACCESSPOINTLIST "/accesspointlist"
+
+/* Notification */
+#define URI_PUSHSERVICE "/service/pushservice"
+#define KEY_MESSAGE "message"
+#define KEY_EXTRA "x.com.samsung.da.notification"
+#define KEY_PUSH_CODE "x.com.samsung.code"
+#define KEY_PUSH_DATA "x.com.samsung.data"
+#define KEY_PUSH_DATA_ET "et"
+#define KEY_PUSH_DATA_DT "dt" //Device Type
+#define KEY_PUSH_DATA_RT "rt" //Resource Type
+#define KEY_PUSH_DATA_DNAME "dname" //Device Name
+#define KEY_PUSH_DATA_REP "rep" //Representation
+#define KEY_PUSH_NS_MESSAGE_ID "x.org.iotivity.ns.messageid"
+#define KEY_PUSH_NS_PROVIDER_ID "x.org.iotivity.ns.providerid"
+
+#define MAX_LEN_FILE_ID (10)
+#define MAX_NUM_OICINFO (200)
+#define MAX_NUM_OICFILE (10)
+#define MAX_NUM_OICCONTENT (100)
+#define MAX_NUM_SCHEDULE (15)
+#define MAX_NUM_AP (50)
+#define MAX_NUM_AP 50
+
+#endif // _THINGS_DEF_
--- /dev/null
+###########################################################################
+#
+# Copyright 2017 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.
+#
+###########################################################################
+
+CSRCS += things_logger.c
+
+DEPPATH += --dep-path src/st_things/things_stack/src/common/logging/
+VPATH += :src/st_things/things_stack/src/common/logging/
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 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.
+ *
+ ****************************************************************************/
+
+#ifndef THINGS_LOGGER_H_
+#define THINGS_LOGGER_H_
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include "things_def.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Log Value Macro's */
+#define THINGS_FUNC_ENTRY "IN"
+#define THINGS_FUNC_EXIT "OUT"
+#define THINGS_MEMORY_ERROR "Memory Error"
+#define THINGS_INVALID_PARAM "Invalid Parameter"
+
+#define THINGS_OIC "OIC"
+
+#define PCF(str) str
+
+// Max buffer size used in variable argument log function
+#define MAX_LOG_V_BUFFER_SIZE (256)
+
+// Log levels
+
+typedef enum {
+ THINGS_DEBUG = 0, THINGS_INFO, THINGS_WARNING, THINGS_ERROR, THINGS_FATAL
+} things_log_level_e;
+
+/**
+ * Initialize the logger.
+ */
+void things_log_init();
+
+/**
+ * Called to Free dyamically allocated resources used with custom logging.
+ * Not necessary if default logging is used
+ *
+ */
+void things_log_shutdown();
+
+/**
+ * Set the Version.
+ */
+void things_log_set_version(char *version);
+
+/**
+ * Output a log string with the specified priority level.
+ * Only defined for Linux and Android
+ *
+ * @param level - DEBUG, INFO, WARNING, ERROR, FATAL
+ * @param tag - Module name
+ * @param log_str - log string
+ */
+void things_log(things_log_level_e level, const char *tag, const char *funcName, const int16_t line_num, const char *log_str);
+
+/**
+ * Output a variable argument list log string with the specified priority level.
+ * Only defined for Linux and Android
+ *
+ * @param level - DEBUG, INFO, WARNING, ERROR, FATAL
+ * @param tag - Module name
+ * @param format - variadic log string
+ */
+void things_logv(things_log_level_e level, const char *tag, const char *func_name, const int16_t line_num, const char *format, ...);
+//#endif //#ifdef __TIZEN__
+
+const char *__get_timestamp__();
+
+#ifdef TB_LOG
+#define THINGS_LOG_INIT() things_log_init()
+#define THINGS_LOG_SHUTDOWN() things_log_shutdown()
+#define THINGS_LOG(level, tag, log_str) things_log((level), (tag), __FUNCTION__, __LINE__, (log_str))
+#define THINGS_LOG_D(level, tag, ...) things_logv((level), (tag), __FUNCTION__, __LINE__, __VA_ARGS__)
+#define THINGS_LOG_V(level, tag, ...) things_logv((level), (tag), __FUNCTION__, __LINE__, __VA_ARGS__)
+#define PROFILING_TIME(...)
+#else //TB_LOG
+/*
+ * Merged RELEASE & LOGGING option into RELEASE
+ * THINGS_LOG_D will be disabled in RELEASE mode
+ * THINGS_LOG & THINGS_LOG_V will be enabled in RELEASE mode
+ *
+ */
+#define THINGS_LOG_CONFIG(ctx)
+#define THINGS_LOG_SHUTDOWN()
+
+#define THINGS_LOG(level, tag, log_str) things_log((level), (tag), __FUNCTION__, __LINE__, (log_str))
+#define THINGS_LOG_V(level, tag, ...) things_logv((level), (tag), __FUNCTION__, __LINE__, __VA_ARGS__)
+#define THINGS_LOG_D(level, tag, ...) things_logv((level), (tag), __FUNCTION__, __LINE__, __VA_ARGS__)
+
+#define THINGS_LOG_DEBUG(level, tag, log_str) things_log((level), (tag), __FUNCTION__, __LINE__, (log_str))
+#define THINGS_LOG_INFO(level, tag, log_str) things_log((level), (tag), __FUNCTION__, __LINE__, (log_str))
+#define THINGS_LOG_WARNING(level, tag, log_str) things_log((level), (tag), __FUNCTION__, __LINE__, (log_str))
+#define THINGS_LOG_ERROR(level, tag, log_str) things_log((level), (tag), __FUNCTION__, __LINE__, (log_str))
+#define THINGS_LOG_FATAL(level, tag, log_str) things_log((level), (tag), __FUNCTION__, __LINE__, (log_str))
+
+#define THINGS_LOG_V_DEBUG(level, tag, ...) things_logv((level), (tag), __FUNCTION__, __LINE__, __VA_ARGS__)
+#define THINGS_LOG_V_INFO(level, tag, ...) things_logv((level), (tag), __FUNCTION__, __LINE__, __VA_ARGS__)
+#define THINGS_LOG_V_WARNING(level, tag, ...) things_logv((level), (tag), __FUNCTION__, __LINE__, __VA_ARGS__)
+#define THINGS_LOG_V_ERROR(level, tag, ...) things_logv((level), (tag), __FUNCTION__, __LINE__, __VA_ARGS__)
+#define THINGS_LOG_V_FATAL(level, tag, ...) things_logv((level), (tag), __FUNCTION__, __LINE__, __VA_ARGS__)
+
+#define THINGS_LOG_D_DEBUG(level, tag, ...) things_logv((level), (tag), __FUNCTION__, __LINE__, __VA_ARGS__)
+#define THINGS_LOG_D_INFO(level, tag, ...) things_logv((level), (tag), __FUNCTION__, __LINE__, __VA_ARGS__)
+#define THINGS_LOG_D_WARNING(level, tag, ...) things_logv((level), (tag), __FUNCTION__, __LINE__, __VA_ARGS__)
+#define THINGS_LOG_D_ERROR(level, tag, ...) things_logv((level), (tag), __FUNCTION__, __LINE__, __VA_ARGS__)
+#define THINGS_LOG_D_FATAL(level, tag, ...) things_logv((level), (tag), __FUNCTION__, __LINE__, __VA_ARGS__)
+// Fot set loglevel //
+
+#define PROFILING_TIME(...)
+#define THINGS_LOG_INIT()
+// #define ENABLE_MALLOC_DEBUG
+#endif // TB_LOG
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+#endif /* THINGS_LOGGER_H_ */
--- /dev/null
+/* ****************************************************************
+ *
+ * Copyright 2017 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.
+ *
+ ******************************************************************/
+
+#ifndef _POSIX_C_SOURCE
+#define _POSIX_C_SOURCE 200809L
+#endif
+
+#include <unistd.h>
+
+// if we have unistd.h, we're a Unix system
+#include <time.h>
+#include <sys/time.h>
+
+#include "things_logger.h"
+#include "things_malloc.h"
+#include "string.h"
+
+static const char *LEVEL[] __attribute__((unused)) = {
+ "DEBUG", "INFOR", "WARNING", "ERROR", "FATAL"
+};
+static char ts_buf[64] = { 0 };
+
+char *p_version = NULL;
+things_log_level_e glevel = THINGS_INFO;
+void set_things_log_level(int level)
+{
+ if (level > 4) {
+ return;
+ }
+ int lev = level - 4;
+ glevel = abs(lev);
+}
+
+void things_log_init()
+{
+ /*
+ * Initialize p_version variable
+ */
+ p_version = NULL;
+}
+
+void things_log_shutdown()
+{
+ /*
+ * Free the memory allocated for p_version
+ */
+ things_free(p_version);
+}
+
+void things_log_set_version(char *version)
+{
+ if (NULL != p_version) {
+ things_free(p_version);
+ }
+
+ /*
+ * Allocate memory for p_version and set the version information
+ */
+ p_version = (char *)things_malloc(strlen(version) + 1);
+ if (NULL == p_version) {
+ printf("Error while allocating memory for version");
+ return;
+ }
+ memset(p_version, 0, strlen(version) + 1);
+ things_strncpy(p_version, version, strlen(version));
+}
+
+/**
+ * Output a log string with the specified priority level.
+ * Only defined for Linux and Android
+ *
+ * @param level - DEBUG, INFO, WARNING, ERROR, FATAL
+ * @param tag - Module name
+ * @param logStr - log string
+ */
+void things_log(things_log_level_e level, const char *tag, const char *func_name, const int16_t line_num, const char *logStr)
+{
+ if (!logStr || !tag) {
+ return;
+ }
+ if (level < glevel) {
+ return;
+ }
+
+ struct timeval tv;
+ time_t nowtime = 0;
+ struct tm *nowtm = NULL;
+ char buf[64] = { 0 };
+
+ gettimeofday(&tv, NULL);
+ nowtime = tv.tv_sec;
+ nowtm = localtime(&nowtime);
+ strftime(buf, sizeof buf, "%m/%d %H:%M:%S", nowtm);
+
+ /* If Version information is not NULL, display the Version Information
+ * Logger Format is given below
+ * [<MM/YY H:M:S.uS> <LOGGER_VERSION>] <LOG_LEVEL> <TAG> <API> <LINE_NO> <LOG_STR>
+ */
+ if (p_version) {
+ printf("[%s %s] %s %s %s %d %s\n", buf, p_version, LEVEL[level], tag, func_name, line_num, logStr);
+ } else {
+ printf("T%d [%s] %s %s %s %d %s\n", getpid(), buf, LEVEL[level], tag, func_name, line_num, logStr);
+ }
+}
+
+/**
+ * Output a variable argument list log string with the specified priority level.
+ * Only defined for Linux and Android
+ *
+ * @param level - DEBUG, INFO, WARNING, ERROR, FATAL
+ * @param tag - Module name
+ * @param format - variadic log string
+ */
+void things_logv(things_log_level_e level, const char *tag, const char *func_name, const int16_t line_num, const char *format, ...)
+{
+ if (!format || !tag) {
+ return;
+ }
+ if (level < glevel) {
+ return;
+ }
+ /*
+ * Using Variable arguments to extract each argument and passing it things_log API
+ */
+ char buffer[MAX_LOG_V_BUFFER_SIZE] = { 0 };
+ va_list args;
+ va_start(args, format);
+ vsnprintf(buffer, sizeof buffer - 1, format, args);
+ va_end(args);
+ things_log(level, tag, func_name, line_num, buffer);
+}
+
+//#endif
+
+const char *__get_timestamp__()
+{
+ struct timeval tv;
+ time_t nowtime = 0;
+ struct tm *nowtm = NULL;
+
+ gettimeofday(&tv, NULL);
+ nowtime = tv.tv_sec;
+ nowtm = localtime(&nowtime);
+ strftime(ts_buf, sizeof ts_buf, "%m/%d %H:%M:%S", nowtm);
+
+ return ts_buf;
+}
--- /dev/null
+###########################################################################
+#
+# Copyright 2017 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.
+#
+###########################################################################
+
+CSRCS += things_malloc.c
+
+DEPPATH += --dep-path src/st_things/things_stack/src/common/memory
+VPATH += :src/st_things/things_stack/src/common/memory
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 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.
+ *
+ ****************************************************************************/
+
+#ifndef THINGS_MALLOC_H_
+#define THINGS_MALLOC_H_
+
+#include <stdio.h>
+
+#ifndef ENABLE_THINGS_MALLOC
+
+#define things_malloc(x) malloc(x)
+#define things_free(x) free(x)
+#define things_realloc(x, y) realloc(x, y)
+#define things_calloc(x, y) calloc(x, y)
+
+#else
+
+extern void *things_malloc(size_t size);
+extern void *things_realloc(void *ptr, size_t size);
+extern void *things_calloc(size_t num, size_t size);
+extern void things_free(void *ptr);
+#endif
+
+#endif /* THINGS_MALLOC_H_ */
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 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 <stdlib.h>
+#include "things_malloc.h"
+
+#include "things_logger.h"
+
+#ifdef ENABLE_MALLOC_DEBUG
+#define TAG "[things_malloc]"
+#endif
+
+#ifdef ENABLE_MALLOC_DEBUG
+static uint32_t count;
+#endif
+
+#ifdef ENABLE_THINGS_MALLOC
+void *things_malloc(size_t size)
+{
+ if (0 == size) {
+ return NULL;
+ }
+
+ /* Allocating Memory for given size using malloc API
+ */
+#ifdef ENABLE_MALLOC_DEBUG
+ void *ptr = malloc(size);
+ count++;
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "malloc: ptr=%p, size=%u, count=%u", ptr, size, count);
+ return ptr;
+#else
+ return malloc(size);
+#endif
+}
+
+void *things_calloc(size_t num, size_t size)
+{
+ if (0 == size || 0 == num) {
+ return NULL;
+ }
+
+ /* Allocating Memory for given size using calloc API
+ */
+#ifdef ENABLE_MALLOC_DEBUG
+ void *ptr = calloc(num, size);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "calloc: ptr=%p, num=%u, size=%u", ptr, num, size);
+ return ptr;
+#else
+ return calloc(num, size);
+#endif
+}
+
+void *things_realloc(void *ptr, size_t size)
+{
+ // Override realloc() behavior for NULL pointer which normally would
+ // work as per malloc(), however we suppress the behavior of possibly
+ // returning a non-null unique pointer.
+ if (ptr == NULL) {
+ return things_malloc(size);
+ }
+ // Otherwise leave the behavior up to realloc() itself:
+
+#ifdef ENABLE_MALLOC_DEBUG
+ void *newptr = realloc(ptr, size);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "realloc: ptr=%p, newptr=%p, size=%u", ptr, newptr, size);
+ // Very important to return the correct pointer here, as it only *somtimes*
+ // differs and thus can be hard to notice/test:
+ return newptr;
+#else
+ return realloc(ptr, size);
+#endif
+}
+
+void things_free(void *ptr)
+{
+#ifdef ENABLE_MALLOC_DEBUG
+ // Since things_malloc() did not increment count if it returned NULL,
+ // guard the decrement:
+ if (ptr) {
+ count--;
+ }
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "free: ptr=%p, count=%u", ptr, count);
+#endif
+
+ free(ptr);
+ ptr = NULL;
+}
+#endif
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 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.
+ *
+ ****************************************************************************/
+
+/*
+ * FIPS 180-2 SHA-224/256/384/512 implementation
+ * Last update: 02/02/2007
+ * Issue date: 04/30/2005
+ *
+ * Copyright (C) 2005, 2007 Olivier Gay <olivier.gay@a3.epfl.ch>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Chul Lee(chuls.lee@samsung.com)'s posting:
+ * Modification for naming confilct.
+ * Attach prefix 'SS_' for all function and constants.
+ * Change name of data context to 'SS_SHAxxxContext' (xxx is bit length of digest)
+ */
+
+#ifndef SHA2_H
+#define SHA2_H
+
+#define SS_SHA224_DIGEST_SIZE (224 / 8)
+#define SS_SHA256_DIGEST_SIZE (256 / 8)
+#define SS_SHA384_DIGEST_SIZE (384 / 8)
+#define SS_SHA512_DIGEST_SIZE (512 / 8)
+
+#define SS_SHA256_BLOCK_SIZE (512 / 8)
+#define SS_SHA512_BLOCK_SIZE (1024 / 8)
+#define SS_SHA384_BLOCK_SIZE SS_SHA512_BLOCK_SIZE
+#define SS_SHA224_BLOCK_SIZE SS_SHA256_BLOCK_SIZE
+
+#ifndef SHA2_TYPES
+#define SHA2_TYPES
+typedef unsigned char uint8;
+typedef unsigned int uint32;
+typedef unsigned long long uint64;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+ unsigned int tot_len;
+ unsigned int len;
+ unsigned char block[2 * SS_SHA256_BLOCK_SIZE];
+ uint32 h[8];
+} ss_sha256_ctx;
+
+typedef struct {
+ unsigned int tot_len;
+ unsigned int len;
+ unsigned char block[2 * SS_SHA512_BLOCK_SIZE];
+ uint64 h[8];
+} ss_sha512_ctx;
+
+typedef ss_sha512_ctx ss_sha384_ctx;
+typedef ss_sha256_ctx ss_sha224_ctx;
+
+void ss_sha224_init(ss_sha224_ctx *ctx);
+void ss_sha224_update(ss_sha224_ctx *ctx, const unsigned char *message, unsigned int len);
+void ss_sha224_final(ss_sha224_ctx *ctx, unsigned char *digest);
+void ss_sha224(const unsigned char *message, unsigned int len, unsigned char *digest);
+
+void ss_sha256_init(ss_sha256_ctx *ctx);
+void ss_sha256_update(ss_sha256_ctx *ctx, const unsigned char *message, unsigned int len);
+void ss_sha256_final(ss_sha256_ctx *ctx, unsigned char *digest);
+void ss_sha256(const unsigned char *message, unsigned int len, unsigned char *digest);
+
+void ss_sha384_init(ss_sha384_ctx *ctx);
+void ss_sha384_update(ss_sha384_ctx *ctx, const unsigned char *message, unsigned int len);
+void ss_sha384_final(ss_sha384_ctx *ctx, unsigned char *digest);
+void ss_sha384(const unsigned char *message, unsigned int len, unsigned char *digest);
+
+void ss_sha512_init(ss_sha512_ctx *ctx);
+void ss_sha512_update(ss_sha512_ctx *ctx, const unsigned char *message, unsigned int len);
+void ss_sha512_final(ss_sha512_ctx *ctx, unsigned char *digest);
+void ss_sha512(const unsigned char *message, unsigned int len, unsigned char *digest);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !SHA2_H */
--- /dev/null
+###########################################################################
+#
+# Copyright 2017 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.
+#
+###########################################################################
+
+CSRCS += ss_sha2.c
+
+DEPPATH += --dep-path src/st_things/things_stack/src/common/security/ssCrypto/src
+VPATH += :src/st_things/things_stack/src/common/security/ssCrypto/src
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 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.
+ *
+ ****************************************************************************/
+
+/*
+ * FIPS 180-2 SHA-224/256/384/512 implementation
+ * Last update: 02/02/2007
+ * Issue date: 04/30/2005
+ *
+ * Copyright (C) 2005, 2007 Olivier Gay <olivier.gay@a3.epfl.ch>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Chul Lee(chuls.lee@samsung.com)'s posting:
+ * Modification for naming confilct.
+ * Attach prefix 'SS_' for all function and constants.
+ * Change name of data context to 'SS_SHAxxxContext' (xxx is bit length of digest)
+ */
+
+#if 0
+#define UNROLL_LOOPS /* Enable loops unrolling */
+#endif
+
+#include <string.h>
+
+#include "ss_sha2.h"
+
+#define SS_SHFR(x, n) (x >> n)
+#define SS_ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n)))
+#define SS_ROTL(x, n) ((x << n) | (x >> ((sizeof(x) << 3) - n)))
+#define SS_CH(x, y, z) ((x & y) ^ (~x & z))
+#define SS_MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
+
+#define SS_SHA256_F1(x) (SS_ROTR(x, 2) ^ SS_ROTR(x, 13) ^ SS_ROTR(x, 22))
+#define SS_SHA256_F2(x) (SS_ROTR(x, 6) ^ SS_ROTR(x, 11) ^ SS_ROTR(x, 25))
+#define SS_SHA256_F3(x) (SS_ROTR(x, 7) ^ SS_ROTR(x, 18) ^ SS_SHFR(x, 3))
+#define SS_SHA256_F4(x) (SS_ROTR(x, 17) ^ SS_ROTR(x, 19) ^ SS_SHFR(x, 10))
+
+#define SS_SHA512_F1(x) (SS_ROTR(x, 28) ^ SS_ROTR(x, 34) ^ SS_ROTR(x, 39))
+#define SS_SHA512_F2(x) (SS_ROTR(x, 14) ^ SS_ROTR(x, 18) ^ SS_ROTR(x, 41))
+#define SS_SHA512_F3(x) (SS_ROTR(x, 1) ^ SS_ROTR(x, 8) ^ SS_SHFR(x, 7))
+#define SS_SHA512_F4(x) (SS_ROTR(x, 19) ^ SS_ROTR(x, 61) ^ SS_SHFR(x, 6))
+
+#define SS_UNPACK32(x, str) \
+{ \
+ *((str) + 3) = (uint8) ((x)); \
+ *((str) + 2) = (uint8) ((x) >> 8); \
+ *((str) + 1) = (uint8) ((x) >> 16); \
+ *((str) + 0) = (uint8) ((x) >> 24); \
+}
+
+#define SS_PACK32(str, x) \
+{ \
+ *(x) = ((uint32) *((str) + 3)) \
+ | ((uint32) *((str) + 2) << 8) \
+ | ((uint32) *((str) + 1) << 16) \
+ | ((uint32) *((str) + 0) << 24); \
+}
+
+#define SS_UNPACK64(x, str) \
+{ \
+ *((str) + 7) = (uint8) ((x)); \
+ *((str) + 6) = (uint8) ((x) >> 8); \
+ *((str) + 5) = (uint8) ((x) >> 16); \
+ *((str) + 4) = (uint8) ((x) >> 24); \
+ *((str) + 3) = (uint8) ((x) >> 32); \
+ *((str) + 2) = (uint8) ((x) >> 40); \
+ *((str) + 1) = (uint8) ((x) >> 48); \
+ *((str) + 0) = (uint8) ((x) >> 56); \
+}
+
+#define SS_PACK64(str, x) \
+{ \
+ *(x) = ((uint64) *((str) + 7)) \
+ | ((uint64) *((str) + 6) << 8) \
+ | ((uint64) *((str) + 5) << 16) \
+ | ((uint64) *((str) + 4) << 24) \
+ | ((uint64) *((str) + 3) << 32) \
+ | ((uint64) *((str) + 2) << 40) \
+ | ((uint64) *((str) + 1) << 48) \
+ | ((uint64) *((str) + 0) << 56); \
+}
+
+/* Macros used for loops unrolling */
+
+#define SS_SHA256_SCR(i) \
+{ \
+ w[i] = SS_SHA256_F4(w[i - 2]) + w[i - 7] \
+ + SS_SHA256_F3(w[i - 15]) + w[i - 16]; \
+}
+
+#define SS_SHA512_SCR(i) \
+{ \
+ w[i] = SS_SHA512_F4(w[i - 2]) + w[i - 7] \
+ + SS_SHA512_F3(w[i - 15]) + w[i - 16]; \
+}
+
+#define SS_SHA256_EXP(a, b, c, d, e, f, g, h, j) \
+{ \
+ t1 = wv[h] + SS_SHA256_F2(wv[e]) + SS_CH(wv[e], wv[f], wv[g]) \
+ + ss_sha256_k[j] + w[j]; \
+ t2 = SS_SHA256_F1(wv[a]) + SS_MAJ(wv[a], wv[b], wv[c]); \
+ wv[d] += t1; \
+ wv[h] = t1 + t2; \
+}
+
+#define SS_SHA512_EXP(a, b, c, d, e, f, g, h, j) \
+{ \
+ t1 = wv[h] + SS_SHA512_F2(wv[e]) + SS_CH(wv[e], wv[f], wv[g]) \
+ + ss_sha512_k[j] + w[j]; \
+ t2 = SS_SHA512_F1(wv[a]) + SS_MAJ(wv[a], wv[b], wv[c]); \
+ wv[d] += t1; \
+ wv[h] = t1 + t2; \
+}
+
+uint32 ss_sha224_h0[8] = { 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939,
+ 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4
+ };
+
+uint32 ss_sha256_h0[8] = { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
+ 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
+ };
+
+uint64 ss_sha384_h0[8] = { 0xcbbb9d5dc1059ed8ULL, 0x629a292a367cd507ULL,
+ 0x9159015a3070dd17ULL, 0x152fecd8f70e5939ULL,
+ 0x67332667ffc00b31ULL, 0x8eb44a8768581511ULL,
+ 0xdb0c2e0d64f98fa7ULL, 0x47b5481dbefa4fa4ULL
+ };
+
+uint64 ss_sha512_h0[8] = { 0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
+ 0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
+ 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
+ 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
+ };
+
+uint32 ss_sha256_k[64] = { 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
+ 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+ 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
+ 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
+ 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
+ 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
+ 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
+ 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
+ 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
+ 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
+ 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
+ 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
+ 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
+ };
+
+uint64 ss_sha512_k[80] = { 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
+ 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
+ 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
+ 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
+ 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
+ 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
+ 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
+ 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
+ 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
+ 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
+ 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
+ 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
+ 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
+ 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
+ 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
+ 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
+ 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
+ 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
+ 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
+ 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
+ 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
+ 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
+ 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
+ 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
+ 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
+ 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
+ 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
+ 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
+ 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
+ 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
+ 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
+ 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
+ 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
+ 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
+ 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
+ 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
+ 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
+ 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
+ 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
+ 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
+ };
+
+/* SHA-256 functions */
+
+void ss_sha256_transf(ss_sha256_ctx *ctx, const unsigned char *message, unsigned int block_nb)
+{
+ uint32 w[64];
+ uint32 wv[8];
+ uint32 t1, t2;
+ const unsigned char *sub_block;
+ int i;
+
+#ifndef UNROLL_LOOPS
+ int j;
+#endif
+
+ for (i = 0; i < (int)block_nb; i++) {
+ sub_block = message + (i << 6);
+
+#ifndef UNROLL_LOOPS
+ for (j = 0; j < 16; j++) {
+ SS_PACK32(&sub_block[j << 2], &w[j]);
+ }
+
+ for (j = 16; j < 64; j++) {
+ SS_SHA256_SCR(j);
+ }
+
+ for (j = 0; j < 8; j++) {
+ wv[j] = ctx->h[j];
+ }
+
+ for (j = 0; j < 64; j++) {
+ t1 = wv[7] + SS_SHA256_F2(wv[4]) + SS_CH(wv[4], wv[5], wv[6])
+ + ss_sha256_k[j] + w[j];
+ t2 = SS_SHA256_F1(wv[0]) + SS_MAJ(wv[0], wv[1], wv[2]);
+ wv[7] = wv[6];
+ wv[6] = wv[5];
+ wv[5] = wv[4];
+ wv[4] = wv[3] + t1;
+ wv[3] = wv[2];
+ wv[2] = wv[1];
+ wv[1] = wv[0];
+ wv[0] = t1 + t2;
+ }
+
+ for (j = 0; j < 8; j++) {
+ ctx->h[j] += wv[j];
+ }
+#else
+ SS_PACK32(&sub_block[0], &w[0]);
+ SS_PACK32(&sub_block[4], &w[1]);
+ SS_PACK32(&sub_block[8], &w[2]);
+ SS_PACK32(&sub_block[12], &w[3]);
+ SS_PACK32(&sub_block[16], &w[4]);
+ SS_PACK32(&sub_block[20], &w[5]);
+ SS_PACK32(&sub_block[24], &w[6]);
+ SS_PACK32(&sub_block[28], &w[7]);
+ SS_PACK32(&sub_block[32], &w[8]);
+ SS_PACK32(&sub_block[36], &w[9]);
+ SS_PACK32(&sub_block[40], &w[10]);
+ SS_PACK32(&sub_block[44], &w[11]);
+ SS_PACK32(&sub_block[48], &w[12]);
+ SS_PACK32(&sub_block[52], &w[13]);
+ SS_PACK32(&sub_block[56], &w[14]);
+ SS_PACK32(&sub_block[60], &w[15]);
+
+ SS_SHA256_SCR(16);
+ SS_SHA256_SCR(17);
+ SS_SHA256_SCR(18);
+ SS_SHA256_SCR(19);
+ SS_SHA256_SCR(20);
+ SS_SHA256_SCR(21);
+ SS_SHA256_SCR(22);
+ SS_SHA256_SCR(23);
+ SS_SHA256_SCR(24);
+ SS_SHA256_SCR(25);
+ SS_SHA256_SCR(26);
+ SS_SHA256_SCR(27);
+ SS_SHA256_SCR(28);
+ SS_SHA256_SCR(29);
+ SS_SHA256_SCR(30);
+ SS_SHA256_SCR(31);
+ SS_SHA256_SCR(32);
+ SS_SHA256_SCR(33);
+ SS_SHA256_SCR(34);
+ SS_SHA256_SCR(35);
+ SS_SHA256_SCR(36);
+ SS_SHA256_SCR(37);
+ SS_SHA256_SCR(38);
+ SS_SHA256_SCR(39);
+ SS_SHA256_SCR(40);
+ SS_SHA256_SCR(41);
+ SS_SHA256_SCR(42);
+ SS_SHA256_SCR(43);
+ SS_SHA256_SCR(44);
+ SS_SHA256_SCR(45);
+ SS_SHA256_SCR(46);
+ SS_SHA256_SCR(47);
+ SS_SHA256_SCR(48);
+ SS_SHA256_SCR(49);
+ SS_SHA256_SCR(50);
+ SS_SHA256_SCR(51);
+ SS_SHA256_SCR(52);
+ SS_SHA256_SCR(53);
+ SS_SHA256_SCR(54);
+ SS_SHA256_SCR(55);
+ SS_SHA256_SCR(56);
+ SS_SHA256_SCR(57);
+ SS_SHA256_SCR(58);
+ SS_SHA256_SCR(59);
+ SS_SHA256_SCR(60);
+ SS_SHA256_SCR(61);
+ SS_SHA256_SCR(62);
+ SS_SHA256_SCR(63);
+
+ wv[0] = ctx->h[0];
+ wv[1] = ctx->h[1];
+ wv[2] = ctx->h[2];
+ wv[3] = ctx->h[3];
+ wv[4] = ctx->h[4];
+ wv[5] = ctx->h[5];
+ wv[6] = ctx->h[6];
+ wv[7] = ctx->h[7];
+
+ SS_SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 0);
+ SS_SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 1);
+ SS_SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 2);
+ SS_SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 3);
+ SS_SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 4);
+ SS_SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 5);
+ SS_SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 6);
+ SS_SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 7);
+ SS_SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 8);
+ SS_SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 9);
+ SS_SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 10);
+ SS_SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 11);
+ SS_SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 12);
+ SS_SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 13);
+ SS_SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 14);
+ SS_SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 15);
+ SS_SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 16);
+ SS_SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 17);
+ SS_SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 18);
+ SS_SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 19);
+ SS_SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 20);
+ SS_SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 21);
+ SS_SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 22);
+ SS_SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 23);
+ SS_SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 24);
+ SS_SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 25);
+ SS_SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 26);
+ SS_SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 27);
+ SS_SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 28);
+ SS_SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 29);
+ SS_SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 30);
+ SS_SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 31);
+ SS_SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 32);
+ SS_SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 33);
+ SS_SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 34);
+ SS_SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 35);
+ SS_SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 36);
+ SS_SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 37);
+ SS_SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 38);
+ SS_SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 39);
+ SS_SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 40);
+ SS_SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 41);
+ SS_SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 42);
+ SS_SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 43);
+ SS_SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 44);
+ SS_SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 45);
+ SS_SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 46);
+ SS_SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 47);
+ SS_SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 48);
+ SS_SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 49);
+ SS_SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 50);
+ SS_SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 51);
+ SS_SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 52);
+ SS_SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 53);
+ SS_SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 54);
+ SS_SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 55);
+ SS_SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 56);
+ SS_SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 57);
+ SS_SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 58);
+ SS_SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 59);
+ SS_SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 60);
+ SS_SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 61);
+ SS_SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 62);
+ SS_SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 63);
+
+ ctx->h[0] += wv[0];
+ ctx->h[1] += wv[1];
+ ctx->h[2] += wv[2];
+ ctx->h[3] += wv[3];
+ ctx->h[4] += wv[4];
+ ctx->h[5] += wv[5];
+ ctx->h[6] += wv[6];
+ ctx->h[7] += wv[7];
+#endif /* !UNROLL_LOOPS */
+ }
+}
+
+void ss_sha256(const unsigned char *message, unsigned int len, unsigned char *digest)
+{
+ ss_sha256_ctx ctx;
+
+ ss_sha256_init(&ctx);
+ ss_sha256_update(&ctx, message, len);
+ ss_sha256_final(&ctx, digest);
+}
+
+void ss_sha256_init(ss_sha256_ctx *ctx)
+{
+#ifndef UNROLL_LOOPS
+ int i;
+ for (i = 0; i < 8; i++) {
+ ctx->h[i] = ss_sha256_h0[i];
+ }
+#else
+ ctx->h[0] = ss_sha256_h0[0];
+ ctx->h[1] = ss_sha256_h0[1];
+ ctx->h[2] = ss_sha256_h0[2];
+ ctx->h[3] = ss_sha256_h0[3];
+ ctx->h[4] = ss_sha256_h0[4];
+ ctx->h[5] = ss_sha256_h0[5];
+ ctx->h[6] = ss_sha256_h0[6];
+ ctx->h[7] = ss_sha256_h0[7];
+#endif /* !UNROLL_LOOPS */
+
+ ctx->len = 0;
+ ctx->tot_len = 0;
+}
+
+void ss_sha256_update(ss_sha256_ctx *ctx, const unsigned char *message, unsigned int len)
+{
+ unsigned int block_nb;
+ unsigned int new_len, rem_len, tmp_len;
+ const unsigned char *shifted_message;
+
+ tmp_len = SS_SHA256_BLOCK_SIZE - ctx->len;
+ rem_len = len < tmp_len ? len : tmp_len;
+
+ memcpy(&ctx->block[ctx->len], message, rem_len);
+
+ if (ctx->len + len < SS_SHA256_BLOCK_SIZE) {
+ ctx->len += len;
+ return;
+ }
+
+ new_len = len - rem_len;
+ block_nb = new_len / SS_SHA256_BLOCK_SIZE;
+
+ shifted_message = message + rem_len;
+
+ ss_sha256_transf(ctx, ctx->block, 1);
+ ss_sha256_transf(ctx, shifted_message, block_nb);
+
+ rem_len = new_len % SS_SHA256_BLOCK_SIZE;
+
+ memcpy(ctx->block, &shifted_message[block_nb << 6], rem_len);
+
+ ctx->len = rem_len;
+ ctx->tot_len += (block_nb + 1) << 6;
+}
+
+void ss_sha256_final(ss_sha256_ctx *ctx, unsigned char *digest)
+{
+ unsigned int block_nb;
+ unsigned int pm_len;
+ unsigned int len_b;
+
+#ifndef UNROLL_LOOPS
+ int i;
+#endif
+
+ block_nb = (1 + ((SS_SHA256_BLOCK_SIZE - 9)
+ < (ctx->len % SS_SHA256_BLOCK_SIZE)));
+
+ len_b = (ctx->tot_len + ctx->len) << 3;
+ pm_len = block_nb << 6;
+
+ memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
+ ctx->block[ctx->len] = 0x80;
+ SS_UNPACK32(len_b, ctx->block + pm_len - 4);
+
+ ss_sha256_transf(ctx, ctx->block, block_nb);
+
+#ifndef UNROLL_LOOPS
+ for (i = 0; i < 8; i++) {
+ SS_UNPACK32(ctx->h[i], &digest[i << 2]);
+ }
+#else
+ SS_UNPACK32(ctx->h[0], &digest[0]);
+ SS_UNPACK32(ctx->h[1], &digest[4]);
+ SS_UNPACK32(ctx->h[2], &digest[8]);
+ SS_UNPACK32(ctx->h[3], &digest[12]);
+ SS_UNPACK32(ctx->h[4], &digest[16]);
+ SS_UNPACK32(ctx->h[5], &digest[20]);
+ SS_UNPACK32(ctx->h[6], &digest[24]);
+ SS_UNPACK32(ctx->h[7], &digest[28]);
+#endif /* !UNROLL_LOOPS */
+}
+
+/* SHA-512 functions */
+
+void ss_sha512_transf(ss_sha512_ctx *ctx, const unsigned char *message, unsigned int block_nb)
+{
+ uint64 w[80];
+ uint64 wv[8];
+ uint64 t1, t2;
+ const unsigned char *sub_block;
+ int i, j;
+
+ for (i = 0; i < (int)block_nb; i++) {
+ sub_block = message + (i << 7);
+
+#ifndef UNROLL_LOOPS
+ for (j = 0; j < 16; j++) {
+ SS_PACK64(&sub_block[j << 3], &w[j]);
+ }
+
+ for (j = 16; j < 80; j++) {
+ SS_SHA512_SCR(j);
+ }
+
+ for (j = 0; j < 8; j++) {
+ wv[j] = ctx->h[j];
+ }
+
+ for (j = 0; j < 80; j++) {
+ t1 = wv[7] + SS_SHA512_F2(wv[4]) + SS_CH(wv[4], wv[5], wv[6])
+ + ss_sha512_k[j] + w[j];
+ t2 = SS_SHA512_F1(wv[0]) + SS_MAJ(wv[0], wv[1], wv[2]);
+ wv[7] = wv[6];
+ wv[6] = wv[5];
+ wv[5] = wv[4];
+ wv[4] = wv[3] + t1;
+ wv[3] = wv[2];
+ wv[2] = wv[1];
+ wv[1] = wv[0];
+ wv[0] = t1 + t2;
+ }
+
+ for (j = 0; j < 8; j++) {
+ ctx->h[j] += wv[j];
+ }
+#else
+ SS_PACK64(&sub_block[0], &w[0]);
+ SS_PACK64(&sub_block[8], &w[1]);
+ SS_PACK64(&sub_block[16], &w[2]);
+ SS_PACK64(&sub_block[24], &w[3]);
+ SS_PACK64(&sub_block[32], &w[4]);
+ SS_PACK64(&sub_block[40], &w[5]);
+ SS_PACK64(&sub_block[48], &w[6]);
+ SS_PACK64(&sub_block[56], &w[7]);
+ SS_PACK64(&sub_block[64], &w[8]);
+ SS_PACK64(&sub_block[72], &w[9]);
+ SS_PACK64(&sub_block[80], &w[10]);
+ SS_PACK64(&sub_block[88], &w[11]);
+ SS_PACK64(&sub_block[96], &w[12]);
+ SS_PACK64(&sub_block[104], &w[13]);
+ SS_PACK64(&sub_block[112], &w[14]);
+ SS_PACK64(&sub_block[120], &w[15]);
+
+ SS_SHA512_SCR(16);
+ SS_SHA512_SCR(17);
+ SS_SHA512_SCR(18);
+ SS_SHA512_SCR(19);
+ SS_SHA512_SCR(20);
+ SS_SHA512_SCR(21);
+ SS_SHA512_SCR(22);
+ SS_SHA512_SCR(23);
+ SS_SHA512_SCR(24);
+ SS_SHA512_SCR(25);
+ SS_SHA512_SCR(26);
+ SS_SHA512_SCR(27);
+ SS_SHA512_SCR(28);
+ SS_SHA512_SCR(29);
+ SS_SHA512_SCR(30);
+ SS_SHA512_SCR(31);
+ SS_SHA512_SCR(32);
+ SS_SHA512_SCR(33);
+ SS_SHA512_SCR(34);
+ SS_SHA512_SCR(35);
+ SS_SHA512_SCR(36);
+ SS_SHA512_SCR(37);
+ SS_SHA512_SCR(38);
+ SS_SHA512_SCR(39);
+ SS_SHA512_SCR(40);
+ SS_SHA512_SCR(41);
+ SS_SHA512_SCR(42);
+ SS_SHA512_SCR(43);
+ SS_SHA512_SCR(44);
+ SS_SHA512_SCR(45);
+ SS_SHA512_SCR(46);
+ SS_SHA512_SCR(47);
+ SS_SHA512_SCR(48);
+ SS_SHA512_SCR(49);
+ SS_SHA512_SCR(50);
+ SS_SHA512_SCR(51);
+ SS_SHA512_SCR(52);
+ SS_SHA512_SCR(53);
+ SS_SHA512_SCR(54);
+ SS_SHA512_SCR(55);
+ SS_SHA512_SCR(56);
+ SS_SHA512_SCR(57);
+ SS_SHA512_SCR(58);
+ SS_SHA512_SCR(59);
+ SS_SHA512_SCR(60);
+ SS_SHA512_SCR(61);
+ SS_SHA512_SCR(62);
+ SS_SHA512_SCR(63);
+ SS_SHA512_SCR(64);
+ SS_SHA512_SCR(65);
+ SS_SHA512_SCR(66);
+ SS_SHA512_SCR(67);
+ SS_SHA512_SCR(68);
+ SS_SHA512_SCR(69);
+ SS_SHA512_SCR(70);
+ SS_SHA512_SCR(71);
+ SS_SHA512_SCR(72);
+ SS_SHA512_SCR(73);
+ SS_SHA512_SCR(74);
+ SS_SHA512_SCR(75);
+ SS_SHA512_SCR(76);
+ SS_SHA512_SCR(77);
+ SS_SHA512_SCR(78);
+ SS_SHA512_SCR(79);
+
+ wv[0] = ctx->h[0];
+ wv[1] = ctx->h[1];
+ wv[2] = ctx->h[2];
+ wv[3] = ctx->h[3];
+ wv[4] = ctx->h[4];
+ wv[5] = ctx->h[5];
+ wv[6] = ctx->h[6];
+ wv[7] = ctx->h[7];
+
+ j = 0;
+
+ do {
+ SS_SHA512_EXP(0, 1, 2, 3, 4, 5, 6, 7, j);
+ j++;
+ SS_SHA512_EXP(7, 0, 1, 2, 3, 4, 5, 6, j);
+ j++;
+ SS_SHA512_EXP(6, 7, 0, 1, 2, 3, 4, 5, j);
+ j++;
+ SS_SHA512_EXP(5, 6, 7, 0, 1, 2, 3, 4, j);
+ j++;
+ SS_SHA512_EXP(4, 5, 6, 7, 0, 1, 2, 3, j);
+ j++;
+ SS_SHA512_EXP(3, 4, 5, 6, 7, 0, 1, 2, j);
+ j++;
+ SS_SHA512_EXP(2, 3, 4, 5, 6, 7, 0, 1, j);
+ j++;
+ SS_SHA512_EXP(1, 2, 3, 4, 5, 6, 7, 0, j);
+ j++;
+ } while (j < 80);
+
+ ctx->h[0] += wv[0];
+ ctx->h[1] += wv[1];
+ ctx->h[2] += wv[2];
+ ctx->h[3] += wv[3];
+ ctx->h[4] += wv[4];
+ ctx->h[5] += wv[5];
+ ctx->h[6] += wv[6];
+ ctx->h[7] += wv[7];
+#endif /* !UNROLL_LOOPS */
+ }
+}
+
+void ss_sha512(const unsigned char *message, unsigned int len, unsigned char *digest)
+{
+ ss_sha512_ctx ctx;
+
+ ss_sha512_init(&ctx);
+ ss_sha512_update(&ctx, message, len);
+ ss_sha512_final(&ctx, digest);
+}
+
+void ss_sha512_init(ss_sha512_ctx *ctx)
+{
+#ifndef UNROLL_LOOPS
+ int i;
+ for (i = 0; i < 8; i++) {
+ ctx->h[i] = ss_sha512_h0[i];
+ }
+#else
+ ctx->h[0] = ss_sha512_h0[0];
+ ctx->h[1] = ss_sha512_h0[1];
+ ctx->h[2] = ss_sha512_h0[2];
+ ctx->h[3] = ss_sha512_h0[3];
+ ctx->h[4] = ss_sha512_h0[4];
+ ctx->h[5] = ss_sha512_h0[5];
+ ctx->h[6] = ss_sha512_h0[6];
+ ctx->h[7] = ss_sha512_h0[7];
+#endif /* !UNROLL_LOOPS */
+
+ ctx->len = 0;
+ ctx->tot_len = 0;
+}
+
+void ss_sha512_update(ss_sha512_ctx *ctx, const unsigned char *message, unsigned int len)
+{
+ unsigned int block_nb;
+ unsigned int new_len, rem_len, tmp_len;
+ const unsigned char *shifted_message;
+
+ tmp_len = SS_SHA512_BLOCK_SIZE - ctx->len;
+ rem_len = len < tmp_len ? len : tmp_len;
+
+ memcpy(&ctx->block[ctx->len], message, rem_len);
+
+ if (ctx->len + len < SS_SHA512_BLOCK_SIZE) {
+ ctx->len += len;
+ return;
+ }
+
+ new_len = len - rem_len;
+ block_nb = new_len / SS_SHA512_BLOCK_SIZE;
+
+ shifted_message = message + rem_len;
+
+ ss_sha512_transf(ctx, ctx->block, 1);
+ ss_sha512_transf(ctx, shifted_message, block_nb);
+
+ rem_len = new_len % SS_SHA512_BLOCK_SIZE;
+
+ memcpy(ctx->block, &shifted_message[block_nb << 7], rem_len);
+
+ ctx->len = rem_len;
+ ctx->tot_len += (block_nb + 1) << 7;
+}
+
+void ss_sha512_final(ss_sha512_ctx *ctx, unsigned char *digest)
+{
+ unsigned int block_nb;
+ unsigned int pm_len;
+ unsigned int len_b;
+
+#ifndef UNROLL_LOOPS
+ int i;
+#endif
+
+ block_nb = 1 + ((SS_SHA512_BLOCK_SIZE - 17)
+ < (ctx->len % SS_SHA512_BLOCK_SIZE));
+
+ len_b = (ctx->tot_len + ctx->len) << 3;
+ pm_len = block_nb << 7;
+
+ memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
+ ctx->block[ctx->len] = 0x80;
+ SS_UNPACK32(len_b, ctx->block + pm_len - 4);
+
+ ss_sha512_transf(ctx, ctx->block, block_nb);
+
+#ifndef UNROLL_LOOPS
+ for (i = 0; i < 8; i++) {
+ SS_UNPACK64(ctx->h[i], &digest[i << 3]);
+ }
+#else
+ SS_UNPACK64(ctx->h[0], &digest[0]);
+ SS_UNPACK64(ctx->h[1], &digest[8]);
+ SS_UNPACK64(ctx->h[2], &digest[16]);
+ SS_UNPACK64(ctx->h[3], &digest[24]);
+ SS_UNPACK64(ctx->h[4], &digest[32]);
+ SS_UNPACK64(ctx->h[5], &digest[40]);
+ SS_UNPACK64(ctx->h[6], &digest[48]);
+ SS_UNPACK64(ctx->h[7], &digest[56]);
+#endif /* !UNROLL_LOOPS */
+}
+
+/* SHA-384 functions */
+
+void ss_sha384(const unsigned char *message, unsigned int len, unsigned char *digest)
+{
+ ss_sha384_ctx ctx;
+
+ ss_sha384_init(&ctx);
+ ss_sha384_update(&ctx, message, len);
+ ss_sha384_final(&ctx, digest);
+}
+
+void ss_sha384_init(ss_sha384_ctx *ctx)
+{
+#ifndef UNROLL_LOOPS
+ int i;
+ for (i = 0; i < 8; i++) {
+ ctx->h[i] = ss_sha384_h0[i];
+ }
+#else
+ ctx->h[0] = ss_sha384_h0[0];
+ ctx->h[1] = ss_sha384_h0[1];
+ ctx->h[2] = ss_sha384_h0[2];
+ ctx->h[3] = ss_sha384_h0[3];
+ ctx->h[4] = ss_sha384_h0[4];
+ ctx->h[5] = ss_sha384_h0[5];
+ ctx->h[6] = ss_sha384_h0[6];
+ ctx->h[7] = ss_sha384_h0[7];
+#endif /* !UNROLL_LOOPS */
+
+ ctx->len = 0;
+ ctx->tot_len = 0;
+}
+
+void ss_sha384_update(ss_sha384_ctx *ctx, const unsigned char *message, unsigned int len)
+{
+ unsigned int block_nb;
+ unsigned int new_len, rem_len, tmp_len;
+ const unsigned char *shifted_message;
+
+ tmp_len = SS_SHA384_BLOCK_SIZE - ctx->len;
+ rem_len = len < tmp_len ? len : tmp_len;
+
+ memcpy(&ctx->block[ctx->len], message, rem_len);
+
+ if (ctx->len + len < SS_SHA384_BLOCK_SIZE) {
+ ctx->len += len;
+ return;
+ }
+
+ new_len = len - rem_len;
+ block_nb = new_len / SS_SHA384_BLOCK_SIZE;
+
+ shifted_message = message + rem_len;
+
+ ss_sha512_transf(ctx, ctx->block, 1);
+ ss_sha512_transf(ctx, shifted_message, block_nb);
+
+ rem_len = new_len % SS_SHA384_BLOCK_SIZE;
+
+ memcpy(ctx->block, &shifted_message[block_nb << 7], rem_len);
+
+ ctx->len = rem_len;
+ ctx->tot_len += (block_nb + 1) << 7;
+}
+
+void ss_sha384_final(ss_sha384_ctx *ctx, unsigned char *digest)
+{
+ unsigned int block_nb;
+ unsigned int pm_len;
+ unsigned int len_b;
+
+#ifndef UNROLL_LOOPS
+ int i;
+#endif
+
+ block_nb = (1 + ((SS_SHA384_BLOCK_SIZE - 17)
+ < (ctx->len % SS_SHA384_BLOCK_SIZE)));
+
+ len_b = (ctx->tot_len + ctx->len) << 3;
+ pm_len = block_nb << 7;
+
+ memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
+ ctx->block[ctx->len] = 0x80;
+ SS_UNPACK32(len_b, ctx->block + pm_len - 4);
+
+ ss_sha512_transf(ctx, ctx->block, block_nb);
+
+#ifndef UNROLL_LOOPS
+ for (i = 0; i < 6; i++) {
+ SS_UNPACK64(ctx->h[i], &digest[i << 3]);
+ }
+#else
+ SS_UNPACK64(ctx->h[0], &digest[0]);
+ SS_UNPACK64(ctx->h[1], &digest[8]);
+ SS_UNPACK64(ctx->h[2], &digest[16]);
+ SS_UNPACK64(ctx->h[3], &digest[24]);
+ SS_UNPACK64(ctx->h[4], &digest[32]);
+ SS_UNPACK64(ctx->h[5], &digest[40]);
+#endif /* !UNROLL_LOOPS */
+}
+
+/* SHA-224 functions */
+
+void ss_sha224(const unsigned char *message, unsigned int len, unsigned char *digest)
+{
+ ss_sha224_ctx ctx;
+
+ ss_sha224_init(&ctx);
+ ss_sha224_update(&ctx, message, len);
+ ss_sha224_final(&ctx, digest);
+}
+
+void ss_sha224_init(ss_sha224_ctx *ctx)
+{
+#ifndef UNROLL_LOOPS
+ int i;
+ for (i = 0; i < 8; i++) {
+ ctx->h[i] = ss_sha224_h0[i];
+ }
+#else
+ ctx->h[0] = ss_sha224_h0[0];
+ ctx->h[1] = ss_sha224_h0[1];
+ ctx->h[2] = ss_sha224_h0[2];
+ ctx->h[3] = ss_sha224_h0[3];
+ ctx->h[4] = ss_sha224_h0[4];
+ ctx->h[5] = ss_sha224_h0[5];
+ ctx->h[6] = ss_sha224_h0[6];
+ ctx->h[7] = ss_sha224_h0[7];
+#endif /* !UNROLL_LOOPS */
+
+ ctx->len = 0;
+ ctx->tot_len = 0;
+}
+
+void ss_sha224_update(ss_sha224_ctx *ctx, const unsigned char *message, unsigned int len)
+{
+ unsigned int block_nb;
+ unsigned int new_len, rem_len, tmp_len;
+ const unsigned char *shifted_message;
+
+ tmp_len = SS_SHA224_BLOCK_SIZE - ctx->len;
+ rem_len = len < tmp_len ? len : tmp_len;
+
+ memcpy(&ctx->block[ctx->len], message, rem_len);
+
+ if (ctx->len + len < SS_SHA224_BLOCK_SIZE) {
+ ctx->len += len;
+ return;
+ }
+
+ new_len = len - rem_len;
+ block_nb = new_len / SS_SHA224_BLOCK_SIZE;
+
+ shifted_message = message + rem_len;
+
+ ss_sha256_transf(ctx, ctx->block, 1);
+ ss_sha256_transf(ctx, shifted_message, block_nb);
+
+ rem_len = new_len % SS_SHA224_BLOCK_SIZE;
+
+ memcpy(ctx->block, &shifted_message[block_nb << 6], rem_len);
+
+ ctx->len = rem_len;
+ ctx->tot_len += (block_nb + 1) << 6;
+}
+
+void ss_sha224_final(ss_sha224_ctx *ctx, unsigned char *digest)
+{
+ unsigned int block_nb;
+ unsigned int pm_len;
+ unsigned int len_b;
+
+#ifndef UNROLL_LOOPS
+ int i;
+#endif
+
+ block_nb = (1 + ((SS_SHA224_BLOCK_SIZE - 9)
+ < (ctx->len % SS_SHA224_BLOCK_SIZE)));
+
+ len_b = (ctx->tot_len + ctx->len) << 3;
+ pm_len = block_nb << 6;
+
+ memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
+ ctx->block[ctx->len] = 0x80;
+ SS_UNPACK32(len_b, ctx->block + pm_len - 4);
+
+ ss_sha256_transf(ctx, ctx->block, block_nb);
+
+#ifndef UNROLL_LOOPS
+ for (i = 0; i < 7; i++) {
+ SS_UNPACK32(ctx->h[i], &digest[i << 2]);
+ }
+#else
+ SS_UNPACK32(ctx->h[0], &digest[0]);
+ SS_UNPACK32(ctx->h[1], &digest[4]);
+ SS_UNPACK32(ctx->h[2], &digest[8]);
+ SS_UNPACK32(ctx->h[3], &digest[12]);
+ SS_UNPACK32(ctx->h[4], &digest[16]);
+ SS_UNPACK32(ctx->h[5], &digest[20]);
+ SS_UNPACK32(ctx->h[6], &digest[24]);
+#endif /* !UNROLL_LOOPS */
+}
--- /dev/null
+###########################################################################
+#
+# Copyright 2017 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.
+#
+###########################################################################
+
+CSRCS += things_hashmap.c things_list.c things_network.c things_ping.c things_queue.c things_string_util.c things_thread.c things_wait_handler.c things_rtos_util.c
+
+DEPPATH += --dep-path src/st_things/things_stack/src/common/utils
+VPATH += :src/st_things/things_stack/src/common/utils
\ No newline at end of file
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 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.
+ *
+ ****************************************************************************/
+
+#ifndef _THINGS_HASHMAP_H
+#define _THINGS_HASHMAP_H
+
+/** Hashmap structure (forward declaration) */
+typedef struct {
+ void *data;
+ int flags;
+ long key;
+} h_entry_s;
+
+typedef struct hashmap_s {
+ h_entry_s *table;
+ long size, count;
+} hashmap_s;
+
+// struct s_hashmap;
+// typedef struct s_hashmap hashmap;
+
+/** Creates a new hashmap near the given size. */
+extern struct hashmap_s *hashmap_create(int startsize);
+
+/** Inserts a new element into the hashmap. */
+extern void hashmap_insert(struct hashmap_s *, const void *data, unsigned long key);
+
+/** Returns the element for the key. */
+extern void *hashmap_get(struct hashmap_s *, unsigned long key);
+
+/** Returns the number of saved elements. */
+extern long hashmap_count(struct hashmap_s *);
+
+/** Removes the hashmap structure. */
+extern void hashmap_delete(struct hashmap_s *);
+
+extern unsigned long hashmap_get_hashval(unsigned char *str);
+
+#endif //_THINGS_HASHMAP_H
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 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.
+ *
+ ****************************************************************************/
+
+#ifndef _THINGS_LIST_H_
+#define _THINGS_LIST_H_
+
+#include <pthread.h>
+
+#include "octypes.h"
+#include "things_node.h"
+
+typedef int (*key_compare)(void *src_key, const void *dest_key);
+
+typedef struct list_s {
+ things_node_s *head;
+ things_node_s *tail;
+
+ // size of this list
+ int size;
+
+ // begin
+ things_node_s *(*begin)(struct list_s *);
+ // pop
+ void *(*pop)(struct list_s *p_list);
+ // end
+ things_node_s *(*end)(struct list_s *);
+ // size
+ int (*list_size)(struct list_s *);
+ // front
+ things_node_s *(*front)(struct list_s *);
+ // insert
+ void (*insert)(struct list_s *, void *);
+ // next
+ // Node* (*get_next) (oic_node_s*);
+ // erase
+ void *(*erase)(struct list_s *, void *);
+ void *(*erase_by_key)(struct list_s *, key_compare, const void *key);
+ // clear
+ void (*clear)(struct list_s *);
+ // find
+ things_node_s *(*find_by_key)(struct list_s *, key_compare, const void *key);
+ pthread_mutex_t q_mutex; // = PTHREAD_MUTEX_INITIALIZER;
+} list_s;
+
+//-----------------------------------------------------------------------------
+// Function prototype
+//-----------------------------------------------------------------------------
+/**
+ * Create and initiate a Queue
+ */
+list_s *create_list(void);
+
+void terminate_list(list_s *list);
+
+#endif // _OICLIST_H_
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 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.
+ *
+ ****************************************************************************/
+
+#ifndef _THINGS_NETWORK_H_
+#define _THINGS_NETWORK_H_
+
+#include "cacommon.h"
+#include "things_api.h"
+
+#define MAX_ESSID (36)
+#define MAX_SECUIRTYKEY (64)
+#define MAX_TYPE_AUTH (16)
+#define MAX_TYPE_ENC (16)
+#define MAX_CHANNEL (8)
+#define MAX_LEVEL_SIGNAL (12)
+#define MAX_BSSID (20)
+
+typedef struct access_point_info_s {
+ char e_ssid[MAX_ESSID]; // mandatory
+ char security_key[MAX_SECUIRTYKEY]; // mandatory
+ char auth_type[MAX_TYPE_AUTH]; // mandatory (None | WEP | WPA-PSK | WPA2-PSK)
+ char enc_type[MAX_TYPE_ENC]; // mandatory (WEP-64 | WEP-128 | TKIP | AES | TKIP_AES)
+ char channel[MAX_CHANNEL]; // optional
+ char signal_level[MAX_LEVEL_SIGNAL]; // optional
+ char bss_id[MAX_BSSID]; // optional
+} access_point_info_s;
+
+bool things_is_connected_ap(void);
+
+int things_is_net_initialize(void);
+
+void things_wifi_state_changed_cb_init(void);
+
+int things_wifi_state_changed_cb(int state, char *ap_name, char *ip_addr);
+
+void things_adapter_state_cb(CATransportAdapter_t adapter, bool enabled);
+
+void things_tcp_session_state_cb(const CAEndpoint_t *info, bool connected);
+
+int things_set_ap_connection(access_point_info_s *APinfo);
+
+int things_get_ap_list(access_point_info_s ***p_info, int *p_count);
+
+typedef int (*things_set_ap_connection_func_type)(access_point_info_s *p_info, char *p_cmd_id);
+
+typedef int (*things_get_ap_search_list_func_type)(access_point_info_s ***p_info, int *p_count);
+
+/*
+ * If Easy-Setup is Reseted, then need to recover about Current Connected-AP info.
+ * This Function serve to recover Connected-AP info with Customized-method.
+ */
+void things_apply_current_ap(void);
+
+#endif /* _THINGS_NETWORK_H_ */
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 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.
+ *
+ ****************************************************************************/
+
+#ifndef _THINGS_NODE_H_
+#define _THINGS_NODE_H_
+
+typedef struct things_node_s {
+ int req; // 0 : Message, 1 : MsgInfo
+ void *item;
+ struct things_node_s *next;
+
+ // struct OicNode* (*Next)(struct OicNode*);
+} things_node_s;
+
+#endif
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 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.
+ *
+ ****************************************************************************/
+
+#ifndef THINGS_CLOUD_PING_H_
+#define THINGS_CLOUD_PING_H_
+
+typedef enum ping_state_e {
+ PING_ST_INIT = 0, // Ping initialization
+ PING_ST_ISCLOUD = 1, // remote client is Cloud CIserver
+ PING_ST_SIGNIN = (1 << 1), // Sign-IN complete
+ PING_ST_TCPCONNECT = (1 << 2), // TCP session connected
+ PING_ST_STARTTHREAD = (1 << 3), // Ping-Thread created
+ PING_ST_DISCOVERY = (1 << 4), // Doing discovery /oic/ping resource in Cloud
+ PING_ST_REQUEST = (1 << 5), // Doing common-ping request to Cloud
+ PING_ST_INTUPDATE = (1 << 6), // Doing interval-update request to Cloud
+ PING_ST_INTUPDATED = (1 << 7), // Success interval-update request to Cloud
+ PING_ST_TIMEOUT = (1 << 8), // Occurred Time-out with regard to any request
+ PING_ALL_FLAG = 0xFFFFFFFF
+} ping_state_e;
+
+bool oic_ping_init(void);
+
+bool oic_ping_terminate(void);
+
+bool oic_ping_set_mask(const char *remote_addr, uint16_t port, ping_state_e state);
+
+bool oic_ping_unset_mask(const char *remote_addr, ping_state_e state);
+
+#endif /* THINGS_CLOUD_PING_H_ */
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 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.
+ *
+ ****************************************************************************/
+
+#ifndef _OICQUEUE_H_
+#define _OICQUEUE_H_
+
+#include <pthread.h>
+
+#include "things_node.h"
+
+typedef struct queue_s {
+ things_node_s *head;
+ things_node_s *tail;
+
+ void (*push)(struct queue_s *, void *, int); // add item to tail
+ // get item from head and remove it from queue
+ void *(*pop)(struct queue_s *, int *);
+ // get item from head but keep it in queue
+ void *(*peek)(struct queue_s *, int *);
+
+ int (*length)(struct queue_s *);
+ // Remove node
+ // size of this queue
+ int size;
+
+ pthread_mutex_t q_mutex; // = PTHREAD_MUTEX_INITIALIZER;
+} queue_s;
+
+#endif // _OICQUEUE_H_
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 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.
+ *
+ ****************************************************************************/
+
+#ifndef THINGS_RTOS_UTIL_H_
+#define THINGS_RTOS_UTIL_H_
+#include "pthread.h"
+typedef enum {
+ THINGS_STACK_PING_THREAD = 0,
+ THINGS_STACK_WAITHANDLER_THREAD,
+ THINGS_STACK_RESETLOOP_THREAD,
+ THINGS_STACK_CICONNETION_INIT_THREAD,
+ THINGS_STACK_CICONNETION_WAIT_THREAD,
+ THINGS_STACK_WIFI_PROV_SET_THREAD,
+ THINGS_STACK_CLOUD_REFRESH_THREAD,
+ THINGS_STACK_MESSAGE_HANDLING_THREAD,
+ THINGS_STACK_PRESENCE_NOTI_THREAD,
+ THINGS_STACK_SERVEREXCETUE_LOOP_THREAD,
+ THINGS_STACK_BASE_TIME_OUT_THREAD,
+ THINGS_STACK_OICABORT_THREAD,
+ THINGS_STACK_WIFI_JOIN,
+ THINGS_STACK_MAX_INDEX,
+} things_stack_thread_name;
+
+int pthread_create_rtos(FAR pthread_t *thread, FAR const pthread_attr_t *attr, pthread_startroutine_t start_routine, pthread_addr_t arg, things_stack_thread_name eThreadname);
+
+#endif /* THINGS_RTOS_UTIL_H_ */
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 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.
+ *
+ ****************************************************************************/
+
+#ifndef THIGNS_STRING_UTIL_H
+#define THIGNS_STRING_UTIL_H
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#define MAX_BUF_LEN 512
+#define MAX_INPUT_QUERY_LEN 100
+
+int compare_strings(const char *src, const char *dst);
+int duplicate_string(const char *src, char **dst);
+void concat_string(char **target, char *attach);
+int hex_string_to_int(const char *hex, int *num);
+int get_id_value_from_query(char id_value[], char *input_query, int size);
+char *things_strcat(char *dest, size_t dest_size, const char *src);
+char *things_strncpy(char *destination, const char *source, size_t num);
+
+#endif
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 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.
+ *
+ ****************************************************************************/
+
+#ifndef THINGS_THREAD_MANAGER_H_
+#define THINGS_THREAD_MANAGER_H_
+
+#include <pthread.h>
+
+int things_thread_create(pthread_t *__newthread, pthread_attr_t *__attr, void *(*__start_routine)(void *), void *__arg);
+
+#endif /* OIC_THREAD_MANAGER_H_ */
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 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.
+ *
+ ****************************************************************************/
+
+#ifndef _THINGS_WAIT_HANDLER_H_
+#define _THINGS_WAIT_HANDLER_H_
+
+#include <octypes.h>
+
+#define DEFAULT_TIMEOUT 60 // default 20 second wait.
+
+typedef struct timeout_s {
+ int cur_counter; // current time-out counter
+ int cur_num; // current time-out number
+ int ori_num; // initial time-out number
+} timeout_s;
+
+typedef void *(*check_time_out_call_func)(timeout_s *param);
+
+OCDoHandle get_request_handle(void);
+
+int cas_request_handle(OCDoHandle EqualVal, OCDoHandle writeHandleVal);
+
+bool is_empty_request_handle(void);
+
+OCDoHandle add_request_handle(OCDoHandle HandleVal);
+
+void del_all_request_handle(void);
+
+long long next_time_out(const long long ori_num, const long long cur_num); // PDF Gaussian Distribution Time-Out Calculator.
+
+unsigned long int create_time_out_process(OCDoHandle hadler, check_time_out_call_func call_func, timeout_s *time_out);
+
+#endif /* _THINGS_WAIT_HANDLER_H_ */
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 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 "things_hashmap.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+/* this should be prime */
+#define TABLE_STARTSIZE 1021
+
+#define ACTIVE 1
+
+static unsigned long is_prime(unsigned long val)
+{
+ int i = 0, p = 0, exp = 0, a = 0;
+
+ for (i = 9; i--;) {
+ a = (rand() % (val - 4)) + 2;
+ p = 1;
+ exp = val - 1;
+ while (exp) {
+ if (exp & 1) {
+ p = (p * a) % val;
+ }
+
+ a = (a * a) % val;
+ exp >>= 1;
+ }
+
+ if (p != 1) {
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static int find_prime_greater_than(int val)
+{
+ if (val & 1) {
+ val += 2;
+ } else {
+ val++;
+ }
+
+ while (!is_prime(val)) {
+ val += 2;
+ }
+
+ return val;
+}
+
+static void rehash(struct hashmap_s *hm)
+{
+ long size = hm->size;
+ h_entry_s *table = hm->table;
+
+ hm->size = find_prime_greater_than(size << 1);
+ hm->table = (h_entry_s *) calloc(sizeof(h_entry_s), hm->size);
+ hm->count = 0;
+
+ while (--size >= 0) {
+ if (table[size].flags == ACTIVE) {
+ hashmap_insert(hm, table[size].data, table[size].key);
+ }
+ }
+
+ free(table);
+}
+
+struct hashmap_s *hashmap_create(int startsize)
+{
+ struct hashmap_s *hm = (struct hashmap_s *)malloc(sizeof(struct hashmap_s));
+
+ if (!startsize) {
+ startsize = TABLE_STARTSIZE;
+ } else {
+ startsize = find_prime_greater_than(startsize - 2);
+ }
+
+ hm->table = (h_entry_s *) calloc(sizeof(h_entry_s), startsize);
+ hm->size = startsize;
+ hm->count = 0;
+
+ return hm;
+}
+
+void hashmap_insert(struct hashmap_s *hash, const void *data, unsigned long key)
+{
+ long index, i, step;
+
+ if (hash->size <= hash->count) {
+ rehash(hash);
+ }
+
+ do {
+ index = key % hash->size;
+ step = (key % (hash->size - 2)) + 1;
+
+ for (i = 0; i < hash->size; i++) {
+ if (hash->table[index].flags & ACTIVE) {
+ if (hash->table[index].key == key) {
+ hash->table[index].data = (void *)data;
+ return;
+ }
+ } else {
+ hash->table[index].flags |= ACTIVE;
+ hash->table[index].data = (void *)data;
+ hash->table[index].key = key;
+ ++hash->count;
+ return;
+ }
+
+ index = (index + step) % hash->size;
+ }
+
+ /* it should not be possible that we EVER come this far, but unfortunately
+ not every generated prime number is prime (Carmichael numbers...) */
+ rehash(hash);
+ } while (1);
+}
+
+void *hashmap_get(struct hashmap_s *hash, unsigned long key)
+{
+ if (hash->count) {
+ long index = 0, i = 0, step = 0;
+ index = key % hash->size;
+ step = (key % (hash->size - 2)) + 1;
+
+ for (i = 0; i < hash->size; i++) {
+ if (hash->table[index].key == key) {
+ if (hash->table[index].flags & ACTIVE) {
+ return hash->table[index].data;
+ }
+ break;
+ } else if (!hash->table[index].data) {
+ break;
+ }
+
+ index = (index + step) % hash->size;
+ }
+ }
+
+ return 0;
+}
+
+long hashmap_count(struct hashmap_s *hash)
+{
+ return hash->count;
+}
+
+void hashmap_delete(struct hashmap_s *hash)
+{
+ if (hash != NULL) {
+ free(hash->table);
+ }
+ free(hash);
+}
+
+/*
+ * Reference : http://www.cse.yorku.ca/~oz/hash.html
+ */
+unsigned long hashmap_get_hashval(unsigned char *str)
+{
+ unsigned long hash = 5381;
+ int c = 0;
+
+ while (c = *str++) {
+ hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
+ }
+
+ return hash;
+}
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 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.
+ *
+ ****************************************************************************/
+
+#define _POSIX_C_SOURCE 200809L
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include "things_logger.h"
+#include "oic_malloc.h"
+#include "things_list.h"
+
+#define TAG "[things_list]"
+
+static void *erase(list_s *p_list, things_node_s *p_prev_node, things_node_s *p_del_node);
+
+// begin
+things_node_s *begin(list_s *p_list)
+{
+// THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+// THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_EXIT);
+ return p_list->head;
+}
+
+void *pop(list_s *p_list)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+
+ void *item = NULL;
+ if (p_list == NULL) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "p_list is NULL.");
+ return NULL;
+ }
+
+ pthread_mutex_lock(&(p_list->q_mutex));
+ things_node_s *node = p_list->begin(p_list);
+ if (node != NULL) {
+ item = erase(p_list, NULL, node);
+ }
+ pthread_mutex_unlock(&(p_list->q_mutex));
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_EXIT);
+ return item;
+}
+
+// end
+things_node_s *end(list_s *p_list)
+{
+// THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+// THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_EXIT);
+ return p_list->tail;
+}
+
+// size
+int list_size(list_s *p_list)
+{
+// THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+
+ pthread_mutex_lock(&(p_list->q_mutex));
+ int n_size = p_list->list_size;
+ pthread_mutex_unlock(&(p_list->q_mutex));
+
+// THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_EXIT);
+ return n_size;
+}
+
+// front
+things_node_s *front(list_s *p_list)
+{
+// THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+// THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_EXIT);
+ return p_list->begin(p_list);
+}
+
+static void link_node(list_s *p_list, things_node_s *p_prev_node, things_node_s *p_new_node)
+{
+// THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+
+// pthread_mutex_lock(&(p_list->q_mutex));
+ if (NULL == p_prev_node) {
+ p_list->head = p_new_node;
+ // Invalid Param
+ // THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_INVALID_PARAM);
+ // return;
+ } else {
+ p_prev_node->next = p_new_node;
+ }
+ p_list->size++;
+
+// pthread_mutex_unlock(&(p_list->q_mutex));
+// THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_EXIT);
+}
+
+// insert
+void insert(list_s *p_list, void *item)
+{
+// THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+ things_node_s *p_new_node = (things_node_s *) OICMalloc(sizeof(things_node_s));
+ if (NULL == p_new_node) {
+ //THINGS_LOG_ERROR(THINGS_ERROR, TAG, THINGS_MEMORY_ERROR);
+ return;
+ }
+ p_new_node->item = item;
+ p_new_node->next = NULL;
+
+ pthread_mutex_lock(&(p_list->q_mutex));
+ things_node_s *p_node = p_list->begin(p_list);
+ if (NULL != p_node) {
+ while (p_node->next) {
+ // THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "p_node->item->key = %s", (char*)(((RequestInfo*)p_node->item)->frameId));
+ p_node = p_node->next;
+ }
+
+ link_node(p_list, p_node, p_new_node);
+ } else {
+ p_list->head = p_new_node;
+ }
+
+ p_list->tail = p_new_node;
+ pthread_mutex_unlock(&(p_list->q_mutex));
+// THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_EXIT);
+}
+
+// erase
+static void *erase(list_s *p_list, things_node_s *p_prev_node, things_node_s *p_del_node)
+{
+// THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+
+ if (p_del_node == p_list->head) {
+ p_list->head = p_del_node->next;
+ p_prev_node = p_list->head;
+ } else {
+ p_prev_node->next = p_del_node->next;
+ }
+
+ if (p_del_node == p_list->tail) {
+ p_list->tail = p_prev_node;
+ }
+
+ void *item = p_del_node->item;
+ p_del_node->item = NULL;
+ p_del_node->next = NULL;
+ OICFree(p_del_node);
+ p_list->size--;
+
+// THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_EXIT);
+ return item;
+}
+
+void *erase_by_key(list_s *p_list, key_compare compare, const void *key)
+{
+// THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+ void *item = NULL;
+
+ pthread_mutex_lock(&(p_list->q_mutex));
+ things_node_s *p_node = p_list->begin(p_list);
+
+ if (NULL != p_node) {
+ // Matched key with head's key.
+ if (compare(p_node->item, key)) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Delete Head");
+ item = erase(p_list, p_list->head, p_node);
+ } else {
+ while (p_node->next) {
+ if (compare(p_node->next->item, key)) {
+ item = erase(p_list, p_node, p_node->next);
+ // THINGS_LOG_D(THINGS_DEBUG, TAG, "src key = %s dst_key = %s", pSrc_key, dst_key);
+ // exit(0);
+ break;
+ }
+
+ p_node = p_node->next;
+ }
+ }
+ }
+
+ pthread_mutex_unlock(&(p_list->q_mutex));
+// THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_EXIT);
+ return item;
+}
+
+// clear
+void clear(list_s *p_list)
+{
+// THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+
+ pthread_mutex_lock(&(p_list->q_mutex));
+ things_node_s *p_node = p_list->begin(p_list);
+ if (NULL != p_node) {
+ while (p_node->next) {
+ erase(p_list, p_node, p_node->next);
+ // p_node = p_node->next;
+ }
+ }
+
+ p_list->head = p_list->tail = NULL;
+ pthread_mutex_unlock(&(p_list->q_mutex));
+
+// THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_EXIT);
+}
+
+// find
+things_node_s *find_by_key(list_s *p_list, key_compare compare, const void *key)
+{
+// THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+
+ pthread_mutex_lock(&(p_list->q_mutex));
+ things_node_s *p_node = p_list->begin(p_list);
+
+ if (NULL != p_node) {
+ while (p_node) {
+ if (compare(p_node->item, key)) {
+ break;
+ }
+ p_node = p_node->next;
+ }
+ }
+ pthread_mutex_unlock(&(p_list->q_mutex));
+
+// THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_EXIT);
+ return p_node;
+}
+
+list_s *create_list(void)
+{
+ // THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+ list_s *list = (list_s *) OICMalloc(sizeof(list_s));
+ if (list == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "memory allocation is failed.");
+ return NULL;
+ }
+
+ list->size = 0;
+ list->head = NULL;
+ list->tail = NULL;
+
+ list->begin = &begin;
+ list->pop = &pop;
+ list->end = &end;
+ list->list_size = &list_size;
+ list->front = &front;
+ list->insert = &insert;
+ list->erase_by_key = &erase_by_key;
+ list->clear = &clear;
+ list->find_by_key = &find_by_key;
+
+ pthread_mutex_init(&(list->q_mutex), NULL);
+
+ // THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_EXIT);
+ return list;
+}
+
+void terminate_list(list_s *list)
+{
+ if (list == NULL) {
+ return;
+ }
+
+ list->clear(list);
+ pthread_mutex_destroy(&(list->q_mutex));
+ OICFree(list);
+}
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 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.
+ *
+ ****************************************************************************/
+
+#define _POSIX_C_SOURCE 200809L
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+
+#include "things_logger.h"
+#include "things_malloc.h"
+#include "things_api.h"
+#include "inc/things_network.h"
+
+#include "resource_handler.h"
+#include "cloud_manager.h"
+#include "easysetup_manager.h"
+#include "things_ping.h"
+
+#define TAG "[things_network]"
+
+static things_get_ap_search_list_func_type gGetAPSearchList = NULL;
+static things_set_ap_connection_func_type gSetAPConnection = NULL;
+
+static int app_state = -1;
+static char *app_ap_name = NULL;
+static char *app_ip_addr = NULL;
+volatile static bool is_connected_target_ap = false;
+
+#define IP_NULL_VAL "0.0.0.0"
+
+/*******************************************************************
+ *
+ * state : 0 --> disconnect
+ * 1 --> connected
+ *
+ *******************************************************************/
+static int check_cb_skip(int state, char *ap_name, char *ip_addr)
+{
+ int ret = 0;
+
+ if (state != 0 && state != 1) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "invalid state value.(%d)", state);
+ return 0;
+ }
+
+ if (app_state == -1) {
+ app_state = 0;
+ app_ap_name = (char *)things_malloc(sizeof(char) * 1);
+ app_ap_name[0] = 0;
+ app_ip_addr = (char *)things_malloc(sizeof(char) * 1);
+ app_ip_addr[0] = 0;
+ }
+ // Process skip checking.
+ if ((state == 1 && ((ap_name == NULL || strlen(ap_name) == 0) || (ip_addr == NULL || strlen(ip_addr) == 0 || strncmp(ip_addr, IP_NULL_VAL, strlen(IP_NULL_VAL)) == 0))) || (state != 1 && state != 0)) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "invalid value.(state=%d, AP_SSID=%s, IP=%s)", state, ap_name, ip_addr);
+ return 0;
+ }
+
+ if (app_state != state) {
+ ret = 1;
+ } else if (state == 1 && (strncmp(ap_name, app_ap_name, strlen(app_ap_name)) != 0 || strncmp(ip_addr, app_ip_addr, strlen(app_ip_addr)) != 0)) {
+ ret = 1;
+ }
+
+ if (ret == 1) {
+ // Update contents
+ app_state = state;
+ if (ap_name) {
+ things_free(app_ap_name);
+ app_ap_name = strdup(ap_name);
+ }
+
+ if (ip_addr) {
+ things_free(app_ip_addr);
+ app_ip_addr = strdup(ip_addr);
+ }
+ }
+
+ return ret;
+}
+
+void things_wifi_state_changed_cb_init(void) // when Soft-AP on, Not called Disconnected Call-Back Func. So, it's alternate.
+{
+ if (app_state == -1) {
+ app_state = 0;
+ app_ap_name = (char *)things_malloc(sizeof(char) * 1);
+ app_ap_name[0] = 0;
+ app_ip_addr = (char *)things_malloc(sizeof(char) * 1);
+ app_ip_addr[0] = 0;
+ } else {
+ app_ap_name[0] = 0;
+ app_ip_addr[0] = 0;
+ }
+
+ is_connected_target_ap = false;
+ ci_retry_stop_by_wifi_cb(false);
+}
+
+/*****************************************************************************
+ *
+ * It's called from st_things Application when WiFi state changed.
+ *
+ * state : 1 -> Connected to WiFi AP.
+ * 0 -> Disconnected from WiFi AP.
+ * ap_name : AP SSID.
+ * ip_addr : IP address.
+ *
+ *****************************************************************************/
+int things_wifi_state_changed_cb(int state, char *ap_name, char *ip_addr)
+{
+ bool Retry1Stop0 = false;
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "state=%d, ap_name=%s, ip_name=%s", state, ap_name, ip_addr);
+
+ if (things_is_net_initialize() == 0) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "gGetSoftAPState is NULL.");
+ return 0;
+ }
+
+ if (check_cb_skip(state, ap_name, ip_addr) != 1) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Call-back process skiped.");
+ return 0;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "app_state=%d, app_ap_name=%s, app_ip_addr=%s", app_state, app_ap_name, app_ip_addr);
+
+ // Process.
+ if (state == 1) { // [Info] Always, when Soft-AP enabling, Call-Back State maintain disconnected. So, Soft-AP Check is not need.
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "AP CONNECTED.");
+ is_connected_target_ap = true;
+
+ set_ssid_in_wifi_resource(app_ap_name);
+ Retry1Stop0 = true; // Re-Try with Last failed Access info.
+ esm_wifi_prov_check_cb(state, app_ap_name, app_ip_addr);
+ } else {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "AP DISCONNECTED.");
+ is_connected_target_ap = false;
+ set_ssid_in_wifi_resource(NULL);
+ }
+
+ // Call Retry or forceStop Connection
+ ci_retry_stop_by_wifi_cb(Retry1Stop0);
+
+ return 1;
+}
+
+/*****************************************************************************
+ *
+ * It's called from Iotivity Framework when Adaptor state changed.
+ *
+ * adapter : Adapter Type.
+ * enabled : true -> connected.
+ * false-> disconnected.
+ *
+ *****************************************************************************/
+void things_adapter_state_cb(CATransportAdapter_t adapter, bool enabled)
+{
+ (void)adapter;
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "IN");
+
+ if (enabled) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "CONNECTED but Not Guarantee to be Communication-Available");
+ } else {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "AP DISCONNECTED.");
+ is_connected_target_ap = false;
+ set_ssid_in_wifi_resource(NULL);
+ ci_retry_stop_by_wifi_cb(false);
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "OUT");
+}
+
+/*****************************************************************************
+ *
+ * It's called from Iotivity Framework when TCP session state changed.
+ *
+ * info : information about remote-peer.
+ * connected : true -> connected
+ * false-> disconnected
+ *
+ *****************************************************************************/
+void things_tcp_session_state_cb(const CAEndpoint_t *info, bool connected)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Enter.");
+
+ if (info == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "[IoTivity Error] invalid call-back parameter.(info is null.)");
+ return;
+ }
+
+ if (info->adapter != CA_ADAPTER_TCP) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Don't support adapter type.(%d)", info->adapter);
+ return;
+ }
+
+ if (strlen(info->addr) == 0 || info->port == 0) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "[IoTivity Error] invalid call-back parameter.(addrIP=%s, port=%d)", info->addr, info->port);
+ return;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "IP = %s, port = %d", info->addr, info->port);
+
+ if (connected == true) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "CONNECTED");
+ oic_ping_set_mask(info->addr, info->port, PING_ST_TCPCONNECT);
+ return;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "DISCONNECTED");
+ oic_ping_unset_mask(info->addr, PING_ST_SIGNIN | PING_ST_TCPCONNECT);
+
+ if (ci_retry_stop_by_tcp_cb(info->addr, info->port) == -1) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "[Error] System Error.");
+ return;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Exit.");
+}
+
+int things_set_ap_connection(access_point_info_s *APinfo)
+{
+ if (things_is_net_initialize() == 0 || APinfo == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Not yet Initialized or APinfo(0x%X) is NULL.", APinfo);
+ return 0;
+ }
+
+ return gSetAPConnection(APinfo, "0");
+}
+
+int things_get_ap_list(access_point_info_s ***p_info, int *p_count)
+{
+ if (things_is_net_initialize() == 0 || p_info == NULL || p_count == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Can't Call GetAPSearchList(p_info=0x%X, p_count=0x%X).", p_info, p_count);
+ return 0;
+ }
+
+ return gGetAPSearchList(p_info, p_count);
+}
+
+/*******************************************************************
+ *
+ * st_things API Function register
+ *
+ *******************************************************************/
+void things_register_set_ap_conn_func(things_set_ap_connection_func_type func)
+{
+ gSetAPConnection = func;
+}
+
+void things_register_get_ap_list_func(things_get_ap_search_list_func_type func)
+{
+ gGetAPSearchList = func;
+}
+
+/*****************************************************************************
+ *
+ * Ready Check All of Network APIs.
+ *
+ * return : 0 --> Not Ready.
+ * 1 --> Initialize Success.
+ * -1 --> Initialize Failed.
+ *
+ *****************************************************************************/
+int things_is_net_initialize(void)
+{
+ if (gSetAPConnection == NULL || gGetAPSearchList == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "[Error] Not Initialized Network API.");
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "[Error] gSetAPConnection = 0x%X, gGetAPSearchList = 0x%X", gSetAPConnection, gGetAPSearchList);
+ return 0;
+ }
+
+ return 1;
+}
+
+bool things_is_connected_ap(void)
+{
+ return is_connected_target_ap;
+}
+
+/*
+ * If Easy-Setup is Reseted, then need to recover about Current Connected-AP info.
+ * This Function serve to recover Connected-AP info with Customized-method.
+ */
+void things_apply_current_ap(void)
+{
+ if (app_state == 1) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Connected AP.(AP_name=%s) Update AP info.", app_ap_name);
+ set_ssid_in_wifi_resource(app_ap_name);
+ } else {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "DisConnected AP. So, Clear rested-AP info.");
+ set_ssid_in_wifi_resource(NULL);
+ }
+}
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 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.
+ *
+ ****************************************************************************/
+
+#define OICPING_ENABLE 1
+
+#include <stdbool.h>
+#include <unistd.h>
+#include <pthread.h>
+#include "ocpayload.h"
+#include "octypes.h"
+#include "es_common.h"
+#include "things_malloc.h"
+#include "things_logger.h"
+#include "things_list.h"
+#include "things_ping.h"
+
+#ifdef __ST_THINGS_RTOS__
+#include "things_rtos_util.h"
+#endif
+
+#ifdef OICPING_ENABLE
+#include "oickeepalive.h"
+#endif
+#include "resource_handler.h"
+#include "cloud_manager.h"
+
+#include "things_thread.h"
+
+#define TAG "[things_ping]"
+
+#define DEFAULT_CONTEXT_VALUE 0x99
+#define PING_UNIT 60 // 60 seconds is minimum value of ping.
+#define NET_TROUBLE_DELAY 5 // 5 seconds
+#define MAX_INTERVAL_EA 4 // Cloud Support 4 EA Interval class.
+
+#define KEEPALIVE_RESOURCE_URI "/oic/ping"
+
+typedef void *(*pthread_func_type)(void *);
+typedef struct things_ping_s {
+ pthread_mutex_t mutex_state; // mutex for State variable.
+ ping_state_e bit_mask_state; // State of Ping
+
+ pthread_mutex_t mutex_thread; // mutex for handle_thread variable.
+ pthread_t handle_thread; // Ping-Thread Handler
+ bool continue_thread; // Continue Ping-Thread Flag.
+ char *addr; // IP address of remote
+ uint16_t port; // Port number for remote
+
+ pthread_mutex_t mutex_int; // mutex for interval variable.
+ int64_t interval[MAX_INTERVAL_EA]; // Interval EA (unit : minute , max : 60)
+ int int_seq; // sequence of interval
+} things_ping_s;
+
+static list_s *list = NULL;
+static const char INTERVAL_ARRAY[] = "inarray";
+static const char INTERVAL[] = "in";
+things_ping_s *pPing = NULL; //SKKIM for ping command
+
+static void *thd_ping_loop(things_ping_s *ping);
+static OCStackApplicationResult discover_ping_resource_handler(void *ctx, OCDoHandle handle, OCClientResponse *client_response);
+static OCStackApplicationResult ping_request_handler(void *ctx, OCDoHandle handle, OCClientResponse *client_response);
+static OCStackApplicationResult ping_update_request_handler(void *ctx, OCDoHandle handle, OCClientResponse *client_response);
+
+static things_ping_s *create_things_ping_s(const char *remoteAddr, const uint16_t port);
+static void terminate_things_ping_s(things_ping_s *ping);
+//static int is_state_key_equal(things_ping_s *ping, const ping_state_e value);
+static int is_ip_key_equal(things_ping_s *ping, const char *targetIP);
+static void check_ping_thread(things_ping_s *ping);
+static void set_mask(things_ping_s *ping, ping_state_e state);
+static bool get_mask(things_ping_s *ping, ping_state_e state);
+static bool cas_mask(things_ping_s *ping, ping_state_e preState, bool preStateThen, ping_state_e postState);
+static void unset_mask(things_ping_s *ping, ping_state_e state);
+static int find_resource_oic_ping(things_ping_s *ping);
+static int send_things_ping_request(things_ping_s *ping);
+static bool set_interval_send_update(things_ping_s *ping, int64_t *intervals, int intEA);
+static bool set_interval(things_ping_s *ping, int64_t *intervals, int intEA, ping_state_e confirmState);
+static bool set_def_interval(things_ping_s *ping);
+static bool things_ping_create_thread(things_ping_s *ping);
+static bool things_ping_destroy_thread(things_ping_s *ping);
+static void things_rep_payload_value_print(OCRepPayloadValue *value);
+static char *make_host_addr(const char *ip, const uint16_t port);
+static OCStackResult send_keep_alive_update_request(const char *host, int64_t *intervals, int intEA, OCCallbackData *cb);
+
+#ifdef OICPING_ENABLE
+bool oic_ping_init(void)
+{
+ THINGS_LOG(THINGS_DEBUG, TAG, "Enter.");
+
+ bool res = false;
+
+ if (list == NULL) {
+ if ((list = create_list()) == NULL) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "memory allocation is failed.");
+ return res;
+ }
+
+ res = true;
+ } else {
+ res = true;
+ }
+
+ pPing = NULL;
+ THINGS_LOG(THINGS_DEBUG, TAG, "Exit.");
+ return res;
+}
+
+bool oic_ping_terminate(void)
+{
+ THINGS_LOG(THINGS_DEBUG, TAG, "Enter.");
+
+ things_ping_s *ping = NULL;
+
+ if (list) {
+ THINGS_LOG(THINGS_DEBUG, TAG, "things_ping_s terminate.");
+ while ((ping = (things_ping_s *) list->pop(list)) != NULL) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Terminate ping.(%s)", ping->addr);
+ if (cas_mask(ping, PING_ST_STARTTHREAD, true, PING_ST_INIT) == true) {
+ things_ping_destroy_thread(ping);
+ }
+ terminate_things_ping_s(ping);
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Terminate ping-list.");
+ terminate_list(list);
+ list = NULL;
+ }
+
+ THINGS_LOG(THINGS_DEBUG, TAG, "Exit.");
+ return true;
+}
+
+bool oic_ping_set_mask(const char *remoteAddr, uint16_t port, ping_state_e state)
+{
+ THINGS_LOG(THINGS_DEBUG, TAG, "Enter.");
+
+ things_node_s *node = NULL;
+ things_ping_s *ping = NULL;
+
+ if (remoteAddr == NULL || strlen(remoteAddr) == 0) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Invalid arguments.(remoteAddr=%s, state=%d)", remoteAddr, state);
+ return false;
+ }
+
+ if (list == NULL) {
+ THINGS_LOG_D(THINGS_INFO, TAG, "OICPing Module is not initialized.");
+ return false;
+ }
+
+ node = list->find_by_key(list, (key_compare) is_ip_key_equal, remoteAddr);
+ if (node == NULL) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Not Found things_node_s for remote(%s). So, Create Node.", remoteAddr);
+ if ((ping = create_things_ping_s(remoteAddr, port)) == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "memory allocation is failed.");
+ return false;
+ }
+ list->insert(list, (void *)ping);
+ } else {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Found things_node_s for remote(%s).", remoteAddr);
+ ping = node->item;
+ }
+
+ if (ping == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Not exist things_ping_s in remoteAddr_Node.(%s)", remoteAddr);
+ return false;
+ }
+
+ if (port != 0) {
+ ping->port = port;
+ }
+
+ set_mask(ping, state);
+ check_ping_thread(ping);
+
+ THINGS_LOG(THINGS_DEBUG, TAG, "Exit.");
+ return true;
+}
+
+bool oic_ping_unset_mask(const char *remoteAddr, ping_state_e state)
+{
+ THINGS_LOG(THINGS_DEBUG, TAG, "Enter.");
+ things_node_s *node = NULL;
+ things_ping_s *ping = NULL;
+
+ if (remoteAddr == NULL || strlen(remoteAddr) == 0) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Invalid arguments.(remoteAddr=%s, state=%d)", remoteAddr, state);
+ return false;
+ }
+
+ if (list == NULL) {
+ THINGS_LOG_D(THINGS_INFO, TAG, "OICPing Module is not initialized.");
+ return false;
+ }
+
+ node = list->find_by_key(list, (key_compare) is_ip_key_equal, remoteAddr);
+ if (node == NULL) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Not Found things_node_s for remote(%s).", remoteAddr);
+ return false;
+
+ } else {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Found things_node_s for remote(%s).", remoteAddr);
+ ping = node->item;
+ }
+
+ if (ping == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Not exist things_ping_s in remoteAddr_Node.(%s)", remoteAddr);
+ return false;
+ }
+
+ unset_mask(ping, state);
+
+ check_ping_thread(ping);
+ THINGS_LOG(THINGS_DEBUG, TAG, "Exit.");
+ return true;
+}
+
+#else
+bool oic_ping_init(void)
+{
+ return true;
+}
+
+bool oic_ping_terminate(void)
+{
+ return true;
+}
+
+bool oic_ping_set_mask(const char *remoteAddr, uint16_t port, ping_state_e state)
+{
+ return true;
+}
+
+bool oic_ping_unset_mask(const char *remoteAddr, ping_state_e state)
+{
+ return true;
+}
+
+#endif
+
+/***************************************************************************************
+ *
+ * Interval Ping-Thread Definition Function.
+ *
+ ***************************************************************************************/
+static void *__attribute__((optimize("O0"))) thd_ping_loop(things_ping_s *ping)
+{
+ THINGS_LOG(THINGS_DEBUG, TAG, "Enter.");
+
+ int sleepMinute = 0;
+
+ if (ping == NULL || ping->addr == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "[Error]: Invalid arguments.(pint=0x%X)", ping);
+ return NULL;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "IP=%s, handle=0x%X, State=0x%X", ping->addr, ping->handle_thread, ping->bit_mask_state);
+
+ pthread_mutex_lock(&ping->mutex_int);
+ for (int i = 0; i < MAX_INTERVAL_EA; i++) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Interval[%d]=%lld", i, ping->interval[i]);
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Intseq= %d", ping->int_seq);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "ContinuThread= %d", ping->continue_thread);
+
+ if (ping->interval[0] == (int64_t) 0 || ping->continue_thread == true) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "[Error]: Invalid Interval-Time or Already Run-Thread for this ping.(interval[0]=%lld, continueFlag=%d)", ping->interval[0], ping->continue_thread);
+ pthread_mutex_unlock(&ping->mutex_int);
+ return NULL;
+ }
+ pthread_mutex_unlock(&ping->mutex_int);
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Start FindResource for /oic/ping to Cloud(%s)", ping->addr);
+ do { // /oic/ping Resource Finding Start
+ int sleepTime = 1;
+ sleepTime = find_resource_oic_ping(ping);
+ sleep(sleepTime);
+ } while (!ping->continue_thread);
+
+ pPing = ping;
+ int sleepDelay = 10;
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Start common-Ping request for /oic/ping to Cloud(%s)", ping->addr);
+ while (ping->continue_thread) { // common-ping request Sending Start
+
+ if (sleepMinute == 0) {
+ sleepMinute = send_things_ping_request(ping);
+ }
+
+ if (sleepMinute) {
+#ifdef __ST_THINGS_RTOS__
+ int sleepCount = PING_UNIT - NET_TROUBLE_DELAY - sleepDelay;
+ sleepDelay = 0;
+ int cCount = 0;
+ while (1) {
+ if (cCount > sleepCount) {
+ break;
+ }
+
+ sleep(1);
+
+ if (ping->continue_thread == false) {
+ sleepMinute = 0;
+ break;
+ }
+ cCount++;
+ }
+#else
+ sleep(PING_UNIT - NET_TROUBLE_DELAY);
+#endif
+
+ sleepMinute--;
+ } else {
+ sleep(1);
+ }
+
+ if (get_mask(ping, PING_ST_INTUPDATED) == true) {
+ sleepMinute = 0;
+ unset_mask(ping, PING_ST_INTUPDATED);
+ }
+ }
+
+ unset_mask(ping, PING_ST_STARTTHREAD | PING_ST_DISCOVERY | PING_ST_REQUEST | PING_ST_INTUPDATE | PING_ST_TIMEOUT);
+ ping->continue_thread = false;
+ set_def_interval(ping);
+ pPing = NULL;
+ THINGS_LOG(THINGS_DEBUG, TAG, "Exit.");
+ return (void *)1;
+}
+
+//void CommandPing() //SKKIM for ping command
+//{
+// if (pPing != NULL) {
+// send_things_ping_request(pPing);
+// }
+//}
+
+static OCStackApplicationResult discover_ping_resource_handler(void *ctx, OCDoHandle handle, OCClientResponse *client_response)
+{
+ THINGS_LOG(THINGS_DEBUG, TAG, "Enter.");
+
+ int64_t *interval = NULL;
+ size_t dimensions[MAX_REP_ARRAY_DEPTH] = { 0, 0, 0 };
+ things_ping_s *ping = (things_ping_s *) ctx;
+
+ if (ctx == (void *)DEFAULT_CONTEXT_VALUE || ctx == NULL || ping->addr == NULL) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "content value is invalid.(ctx=0x%X)", ctx);
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+
+ if (client_response) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "ctx=0x%X", ctx);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "StackResult: %s(%d)", get_result(client_response->result), client_response->result);
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Device =============> Discovered @ %s:%d", client_response->devAddr.addr, client_response->devAddr.port);
+
+ if (strncmp(ping->addr, client_response->devAddr.addr, strlen(client_response->devAddr.addr)) != 0) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "[Error]: Mismatching address.(ping->addr=%s, recvAddr=%s)", ping->addr, client_response->devAddr.addr);
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+ // Parsing payload.
+ if (client_response->payload != NULL && client_response->payload->type == PAYLOAD_TYPE_REPRESENTATION) {
+ OCRepPayloadValue *val = ((OCRepPayload *) client_response->payload)->values;
+ while (val != NULL) {
+ things_rep_payload_value_print(val);
+ val = val->next;
+ }
+
+ OCRepPayloadGetIntArray(((const OCRepPayload *)client_response->payload), INTERVAL_ARRAY, &interval, dimensions);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "dimension=[%d, %d, %d]", dimensions[0], dimensions[1], dimensions[2]);
+ for (int i = 0; i < dimensions[0]; i++) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "interval[%d]=%d", i, interval[i]);
+ }
+ }
+ // Result processing.
+ switch (client_response->result) {
+ case OC_STACK_OK:
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Discovery Success.");
+ if (interval == NULL || interval[0] == 0 || dimensions[0] == 0) {
+ THINGS_LOG_D(THINGS_INFO, TAG, "Invalid received remote interval or dimensions.");
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+
+ if (set_interval(ping, interval, dimensions[0], PING_ST_DISCOVERY) == true) {
+ ping->continue_thread = true;
+ }
+ break;
+ case OC_STACK_TIMEOUT:
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Occurred Time-Out Event.");
+ set_mask(ping, PING_ST_TIMEOUT);
+ break;
+ default:
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Not Support StackResult: %s(%d)", get_result(client_response->result), client_response->result);
+ break;
+ }
+ } else {
+ THINGS_LOG_D(THINGS_INFO, TAG, "discover_ping_resource_handler received Null client_response");
+ }
+ /*! Added by st_things for memory Leak fix
+ */
+ if (NULL != interval) {
+ things_free(interval);
+ }
+
+ THINGS_LOG(THINGS_DEBUG, TAG, "Exit.");
+ return OC_STACK_DELETE_TRANSACTION;
+}
+
+static OCStackApplicationResult ping_request_handler(void *ctx, OCDoHandle handle, OCClientResponse *client_response)
+{
+ THINGS_LOG(THINGS_DEBUG, TAG, "Enter.");
+
+ things_ping_s *ping = (things_ping_s *) ctx;
+
+ if (ctx == (void *)DEFAULT_CONTEXT_VALUE || ctx == NULL || ping->addr == NULL) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "content value is invalid.(ctx=0x%X)", ctx);
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+
+ if (client_response) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "ctx=0x%X", ctx);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "StackResult: %s(%d)", get_result(client_response->result), client_response->result);
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Device =============> Discovered @ %s:%d", client_response->devAddr.addr, client_response->devAddr.port);
+
+ if (strncmp(ping->addr, client_response->devAddr.addr, strlen(client_response->devAddr.addr)) != 0) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "[Error]: Mismatching address.(ping->addr=%s, recvAddr=%s)", ping->addr, client_response->devAddr.addr);
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+ // Parsing payload.
+ if (client_response->payload != NULL && client_response->payload->type == PAYLOAD_TYPE_REPRESENTATION) {
+ OCRepPayloadValue *val = ((OCRepPayload *) client_response->payload)->values;
+ while (val != NULL) {
+ things_rep_payload_value_print(val);
+ val = val->next;
+ }
+ }
+ // Result processing.
+ switch (client_response->result) {
+ case OC_STACK_OK:
+ THINGS_LOG_D(THINGS_INFO, TAG, "common-ping request Success.");
+ if (get_mask(ping, PING_ST_REQUEST) == true && get_mask(ping, PING_ST_TIMEOUT) == false) {
+ unset_mask(ping, PING_ST_REQUEST);
+ }
+ break;
+ case OC_STACK_TIMEOUT:
+ THINGS_LOG_D(THINGS_WARNING, TAG, "Occurred Time-Out Event.");
+ set_mask(ping, PING_ST_TIMEOUT);
+ break;
+ default:
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "Not Support StackResult: %s(%d)", get_result(client_response->result), client_response->result);
+ break;
+ }
+ } else {
+ THINGS_LOG_D(THINGS_WARNING, TAG, "ping_request_handler received Null client_response");
+ }
+
+ THINGS_LOG(THINGS_DEBUG, TAG, "Exit.");
+ return OC_STACK_DELETE_TRANSACTION;
+}
+
+static OCStackApplicationResult ping_update_request_handler(void *ctx, OCDoHandle handle, OCClientResponse *client_response)
+{
+ THINGS_LOG(THINGS_DEBUG, TAG, "Enter.");
+
+ int64_t *interval = NULL;
+ size_t dimensions[MAX_REP_ARRAY_DEPTH] = { 0, 0, 0 };
+ things_ping_s *ping = (things_ping_s *) ctx;
+ (void *)handle;
+
+ if (ctx == (void *)DEFAULT_CONTEXT_VALUE || ctx == NULL || ping->addr == NULL) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "content value is invalid.(ctx=0x%X)", ctx);
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+
+ if (client_response) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "ctx=0x%X", ctx);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "StackResult: %s(%d)", get_result(client_response->result), client_response->result);
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Device =============> Discovered @ %s:%d", client_response->devAddr.addr, client_response->devAddr.port);
+
+ if (strncmp(ping->addr, client_response->devAddr.addr, strlen(client_response->devAddr.addr)) != 0) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "[Error]: Mismatching address.(ping->addr=%s, recvAddr=%s)", ping->addr, client_response->devAddr.addr);
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+ // Parsing payload.
+ if (client_response->payload != NULL && client_response->payload->type == PAYLOAD_TYPE_REPRESENTATION) {
+ OCRepPayloadValue *val = ((OCRepPayload *) client_response->payload)->values;
+ while (val != NULL) {
+ things_rep_payload_value_print(val);
+ val = val->next;
+ }
+
+ OCRepPayloadGetIntArray(((const OCRepPayload *)client_response->payload), INTERVAL_ARRAY, &interval, dimensions);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "dimension=[%d, %d, %d]", dimensions[0], dimensions[1], dimensions[2]);
+ for (int i = 0; i < dimensions[0]; i++) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "interval[%d]=%d", i, interval[i]);
+ }
+ }
+ // Result processing.
+ switch (client_response->result) {
+ case OC_STACK_RESOURCE_CHANGED:
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "update-Ping request Success.");
+ if (set_interval(ping, interval, dimensions[0], PING_ST_INTUPDATE) == true) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Success Apply Interval.");
+ }
+ break;
+ case OC_STACK_TIMEOUT:
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Occurred Time-Out Event.");
+ set_mask(ping, PING_ST_TIMEOUT);
+ break;
+ default:
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Not Support StackResult: %s(%d)", get_result(client_response->result), client_response->result);
+ break;
+ }
+ } else {
+ THINGS_LOG_D(THINGS_INFO, TAG, "ping_update_request_handler received Null client_response");
+ }
+ /*! Added by st_things for memory Leak fix
+ */
+ if (NULL != interval) {
+ OICFree(interval);
+ }
+ THINGS_LOG(THINGS_DEBUG, TAG, "Exit.");
+ return OC_STACK_DELETE_TRANSACTION;
+}
+
+/***************************************************************************************
+ *
+ * Interval Function Definition Collection.
+ *
+ ***************************************************************************************/
+static things_ping_s *create_things_ping_s(const char *remoteAddr, const uint16_t port)
+{
+ things_ping_s *ping = NULL;
+
+ if (remoteAddr == NULL || strlen(remoteAddr) == 0) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "remote addr is NULL.");
+ return NULL;
+ }
+
+ ping = (things_ping_s *) things_malloc(sizeof(things_ping_s));
+ if (ping == NULL) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "memory allocation is failed.");
+ return NULL;
+ }
+
+ ping->addr = strdup(remoteAddr);
+ ping->port = port;
+ ping->continue_thread = false;
+ pthread_mutex_init(&ping->mutex_int, NULL);
+ pthread_mutex_init(&ping->mutex_state, NULL);
+ pthread_mutex_init(&ping->mutex_thread, NULL);
+
+ pthread_mutex_lock(&ping->mutex_thread);
+ ping->handle_thread = 0;
+ pthread_mutex_unlock(&ping->mutex_thread);
+
+ set_def_interval(ping);
+
+ set_mask(ping, PING_ST_INIT);
+ return ping;
+}
+
+static void terminate_things_ping_s(things_ping_s *ping)
+{
+ THINGS_LOG(THINGS_DEBUG, TAG, "Enter.");
+
+ if (ping == NULL) {
+ THINGS_LOG(THINGS_DEBUG, TAG, "ping is NULL.");
+ return;
+ }
+
+ THINGS_LOG(THINGS_DEBUG, TAG, "ping thread destroy check.");
+ if (get_mask(ping, PING_ST_TCPCONNECT) == false && get_mask(ping, PING_ST_STARTTHREAD) == true) { // need to destroy ping-thread.
+ things_ping_destroy_thread(ping);
+ }
+
+ set_mask(ping, PING_ST_INIT);
+
+ pthread_mutex_destroy(&ping->mutex_int);
+ pthread_mutex_destroy(&ping->mutex_state);
+ pthread_mutex_destroy(&ping->mutex_thread);
+
+ if (ping->addr) {
+ THINGS_LOG(THINGS_DEBUG, TAG, "ping->addr memory free.");
+ things_free(ping->addr);
+ ping->addr = NULL;
+ }
+
+ things_free(ping);
+
+ THINGS_LOG(THINGS_DEBUG, TAG, "Exit.");
+}
+
+//static int is_state_key_equal(things_ping_s *ping, const ping_state_e value)
+//{
+// int res = 0;
+// if (ping == NULL || ping->addr == NULL) {
+// THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Invalid arguments.(ping=0x%X, targetIP=%s)", ping);
+// return res;
+// }
+//
+// if (get_mask(ping, value) == true) {
+// THINGS_LOG_D(THINGS_DEBUG, TAG, "Found ping-struct(%s) for State(%d)", ping->addr, value);
+// res = 1;
+// }
+//
+// return res;
+//}
+
+static int is_ip_key_equal(things_ping_s *ping, const char *targetIP)
+{
+ int res = 0;
+ if (ping == NULL || ping->addr == NULL || targetIP == NULL || strlen(targetIP) == 0) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Invalid arguments.(ping=0x%X, targetIP=%s)", ping, targetIP);
+ return res;
+ }
+
+ if (strncmp(ping->addr, targetIP, strlen(targetIP)) == 0) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Found ping-struct(%s) for targetIP(%s)", ping->addr, targetIP);
+ res = 1;
+ }
+
+ return res;
+}
+
+static void check_ping_thread(things_ping_s *ping)
+{
+ THINGS_LOG(THINGS_DEBUG, TAG, "Enter.");
+
+ if (ping == NULL || ping->addr == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Invalid arguments.(ping=0x%X)", ping);
+ return;
+ }
+
+ if (list == NULL) {
+ THINGS_LOG_D(THINGS_INFO, TAG, "OICPing Module is not initialized.");
+ return;
+ }
+
+ if (get_mask(ping, PING_ST_TCPCONNECT) == true && get_mask(ping, PING_ST_STARTTHREAD) == false) { // need to create ping-thread.
+ if (get_mask(ping, PING_ST_ISCLOUD) == false || (get_mask(ping, PING_ST_ISCLOUD) == true && get_mask(ping, PING_ST_SIGNIN) == true)) { // create thread
+ things_ping_create_thread(ping);
+ }
+ }
+
+ if (get_mask(ping, PING_ST_TCPCONNECT) == false && get_mask(ping, PING_ST_STARTTHREAD) == true) { // need to destroy ping-thread.
+ things_ping_destroy_thread(ping);
+ }
+
+ if (get_mask(ping, PING_ST_ISCLOUD | PING_ST_SIGNIN | PING_ST_TCPCONNECT) == false) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Not need things_ping_s, So, Terminate things_ping_s.(IP=%s)", ping->addr);
+ if ((ping = list->erase_by_key(list, is_ip_key_equal, ping->addr)) != NULL) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Erase node-element Success in List.");
+ terminate_things_ping_s(ping);
+ }
+ }
+
+ THINGS_LOG(THINGS_DEBUG, TAG, "Exit.");
+}
+
+static void set_mask(things_ping_s *ping, ping_state_e state)
+{
+ THINGS_LOG(THINGS_DEBUG, TAG, "Enter.");
+ if (ping == NULL) {
+ return;
+ }
+
+ pthread_mutex_lock(&ping->mutex_state);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "(B) bit_mask_state = 0x%X", ping->bit_mask_state);
+ if (state != PING_ST_INIT) {
+ ping->bit_mask_state |= state;
+ } else {
+ ping->bit_mask_state = state;
+ }
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "(A) bit_mask_state = 0x%X", ping->bit_mask_state);
+ pthread_mutex_unlock(&ping->mutex_state);
+
+ THINGS_LOG(THINGS_DEBUG, TAG, "Exit.");
+}
+
+static bool get_mask(things_ping_s *ping, ping_state_e state)
+{
+ bool res = true;
+
+ if (ping == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "ping is NULL.");
+ return false;
+ }
+
+ pthread_mutex_lock(&ping->mutex_state);
+ res = (ping->bit_mask_state & state) != 0 ? true : false;
+ pthread_mutex_unlock(&ping->mutex_state);
+
+ return res;
+}
+
+static bool cas_mask(things_ping_s *ping, ping_state_e preState, bool preStateThen, ping_state_e postState)
+{
+ bool res = false;
+
+ if (ping == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "ping is NULL.");
+ return false;
+ }
+
+ pthread_mutex_lock(&ping->mutex_state);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "(B) bit_mask_state = 0x%X", ping->bit_mask_state);
+ bool state = (ping->bit_mask_state & preState) != 0 ? true : false;
+ if (state == preStateThen) {
+ if (postState != PING_ST_INIT) {
+ ping->bit_mask_state |= postState;
+ } else {
+ ping->bit_mask_state = postState;
+ }
+ res = true;
+ }
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "(A) bit_mask_state = 0x%X", ping->bit_mask_state);
+ pthread_mutex_unlock(&ping->mutex_state);
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "result = %d", res);
+ return res;
+}
+
+static void unset_mask(things_ping_s *ping, ping_state_e state)
+{
+ THINGS_LOG(THINGS_DEBUG, TAG, "Enter.");
+ if (ping == NULL) {
+ return;
+ }
+
+ pthread_mutex_lock(&ping->mutex_state);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "(B) bit_mask_state = 0x%X", ping->bit_mask_state);
+ if (state != PING_ST_INIT) {
+ ping->bit_mask_state &= (~state);
+ } else {
+ ping->bit_mask_state = state;
+ }
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "(A) bit_mask_state = 0x%X", ping->bit_mask_state);
+ pthread_mutex_unlock(&ping->mutex_state);
+
+ THINGS_LOG(THINGS_DEBUG, TAG, "Exit.");
+}
+
+#ifdef OICPING_ENABLE
+static int find_resource_oic_ping(things_ping_s *ping)
+{
+ THINGS_LOG(THINGS_DEBUG, TAG, "Enter.");
+
+ int sleepTime = 1; // seconds
+ OCDoHandle g_req_handle = NULL;
+ OCCallbackData cb;
+ char *hostAddr = NULL;
+
+ cb.cb = discover_ping_resource_handler;
+ cb.cd = NULL;
+ cb.context = (void *)ping;
+
+ if (ping == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "ping struct is NULL.");
+ return sleepTime;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "cb.context=0x%X", cb.context);
+
+ if ((hostAddr = make_host_addr(ping->addr, ping->port)) == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Memory Allocation is failed.");
+ return sleepTime;
+ }
+
+ while (cas_mask(ping, PING_ST_REQUEST | PING_ST_INTUPDATE | PING_ST_TIMEOUT, false, PING_ST_DISCOVERY) == false) {
+ sleep(1); // sleep 1 second
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Send OCFindKeepAliveResouce request to %s.", hostAddr);
+ if (OCFindKeepAliveResource(&g_req_handle, hostAddr, &cb) == OC_STACK_OK) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Waiting for /oic/ping Cloud-response.(%s)", ping->addr);
+ sleepTime = 5;
+ } else {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "[Error]: Ping Resource Discovery-request is failed.");
+ unset_mask(ping, PING_ST_DISCOVERY);
+ }
+ /*! Added by st_things for memory Leak fix
+ */
+ if (hostAddr) {
+ things_free(hostAddr);
+ }
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Exit.(sleepTime=%d)", sleepTime);
+ return sleepTime;
+}
+
+static int send_things_ping_request(things_ping_s *ping)
+{
+ THINGS_LOG(THINGS_DEBUG, TAG, "Enter.");
+
+ int sleepTime = 0; // minute
+ OCDoHandle g_req_handle = NULL;
+ OCStackResult result = OC_STACK_ERROR;
+ OCCallbackData cb;
+ int64_t interval = 0;
+ char *hostAddr = NULL;
+ OCRepPayload *payload = NULL;
+
+ cb.cb = ping_request_handler;
+ cb.cd = NULL;
+ cb.context = (void *)ping;
+
+ if (ping == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "ping struct is NULL.");
+ return sleepTime;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "cb.context=0x%X", cb.context);
+
+ if ((hostAddr = make_host_addr(ping->addr, ping->port)) == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "hostAddr Memory Allocation is failed.");
+ return sleepTime;
+ }
+
+ payload = OCRepPayloadCreate();
+ if (!payload) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "payload Memory Allocation is failed.");
+ /*! Added by st_things for memory Leak fix
+ */
+ if (hostAddr) {
+ things_free(hostAddr);
+ }
+ return sleepTime;
+ }
+
+ while (cas_mask(ping, PING_ST_DISCOVERY | PING_ST_INTUPDATE | PING_ST_TIMEOUT, false, PING_ST_REQUEST) == false) {
+ sleep(1); // sleep 1 second
+ }
+
+ pthread_mutex_lock(&ping->mutex_int);
+ interval = ping->interval[ping->int_seq];
+ // period send request to Cloud for interval hand-shaking /oic/ping resource.
+ OCRepPayloadSetPropInt(payload, INTERVAL, interval);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "interval = %lld", interval);
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Send OCSendKeepAliveRequest request to %s.", hostAddr);
+ if ((result = OCSendKeepAliveRequest(&g_req_handle, hostAddr, payload, &cb)) == OC_STACK_OK)
+// if( (result= SendKeepAliveRequest(hostAddr, interval, &cb)) == OC_STACK_OK )
+ {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Sending Success about common-Ping request.");
+ do {
+ ping->int_seq = (ping->int_seq + 1) % MAX_INTERVAL_EA;
+ } while (ping->interval[ping->int_seq] == 0);
+
+ sleepTime = interval;
+ }
+ unset_mask(ping, PING_ST_INTUPDATED);
+ pthread_mutex_unlock(&ping->mutex_int);
+
+ if (result != OC_STACK_OK) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "[Error]: Sending about common-Ping request is failed.");
+ unset_mask(ping, PING_ST_REQUEST);
+ OCRepPayloadDestroy(payload);
+ }
+ /*! Added by st_things for memory Leak fix
+ */
+ if (hostAddr) {
+ things_free(hostAddr);
+ }
+ THINGS_LOG(THINGS_DEBUG, TAG, "Exit.");
+ return sleepTime;
+}
+
+static bool set_interval_send_update(things_ping_s *ping, int64_t *intervals, int intEA)
+{
+ THINGS_LOG(THINGS_DEBUG, TAG, "Enter.");
+
+// int i = 0;
+ bool res = false;
+ OCStackResult result = OC_STACK_ERROR;
+ OCCallbackData cb;
+ char *hostAddr = NULL;
+
+ cb.cb = ping_update_request_handler;
+ cb.cd = NULL;
+ cb.context = (void *)ping;
+
+ if (ping == NULL || intervals == NULL || intEA == 0) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Invalid arguments.(ping=%0x%X, intervals=0x%X, intEA=%d)", ping, intervals, intEA);
+ return false;
+ }
+
+ if (get_mask(ping, PING_ST_ISCLOUD) == false) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Interval Update & Sending update-Ping request is Support only for Cloud.");
+ return false;
+ }
+
+ if (intEA > MAX_INTERVAL_EA) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "intEA is over %d. So, fix to %d", MAX_INTERVAL_EA, MAX_INTERVAL_EA);
+ intEA = MAX_INTERVAL_EA;
+ }
+
+ if (get_mask(ping, PING_ST_STARTTHREAD) == false || ping->continue_thread == false) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Ping-Thread is not ready.");
+ return false;
+ }
+
+ if ((hostAddr = make_host_addr(ping->addr, ping->port)) == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Memory Allocation is failed.");
+ return false;
+ }
+
+ while (cas_mask(ping, PING_ST_DISCOVERY | PING_ST_REQUEST | PING_ST_TIMEOUT, false, PING_ST_INTUPDATE) == false) {
+ sleep(1); // sleep 1 second
+ }
+
+// pthread_mutex_lock( &ping->mutex_int );
+ result = send_keep_alive_update_request(hostAddr, intervals, intEA, &cb);
+// if( (result = send_keep_alive_update_request(host, intervals, intEA, &cb)) == OC_STACK_OK ) // send interval-update request to Cloud. & set State.
+// {
+// memset(ping->interval, 0, sizeof(int64_t)*MAX_INTERVAL_EA);
+// for(i=0; i < intEA; i++)
+// {
+// ping->interval[i] = intervals[i];
+// }
+// ping->int_seq = 0;
+// res = true;
+// }
+// pthread_mutex_unlock( &ping->mutex_int );
+
+ if (result != OC_STACK_OK) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "[Error]: Sending about update-Ping request is failed.");
+ unset_mask(ping, PING_ST_INTUPDATE);
+ } else {
+ THINGS_LOG(THINGS_DEBUG, TAG, "Success Sending update-Ping request.");
+ res = true;
+ }
+ /*! Added by st_things for memory Leak fix
+ */
+ if (hostAddr) {
+ things_free(hostAddr);
+ }
+
+ THINGS_LOG(THINGS_DEBUG, TAG, "Exit.");
+ return res;
+}
+#else
+static int find_resource_oic_ping(things_ping_s *ping)
+{
+ return 1;
+}
+
+static int send_things_ping_request(things_ping_s *ping)
+{
+ return 1;
+}
+
+static bool set_interval_send_update(things_ping_s *ping, int64_t *intervals, int intEA)
+{
+ return true;
+}
+#endif
+
+static bool set_interval(things_ping_s *ping, int64_t *intervals, int intEA, ping_state_e confirmState)
+{
+ THINGS_LOG(THINGS_DEBUG, TAG, "Enter.");
+
+ int i = 0;
+ bool res = false;
+
+ if (ping == NULL || intervals == NULL || intEA == 0) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Invalid arguments.(ping=%0x%X, intervals=0x%X, intEA=%d)", ping, intervals, intEA);
+ return false;
+ }
+
+ if (intEA > MAX_INTERVAL_EA) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "intEA is over %d. So, fix to %d", MAX_INTERVAL_EA, MAX_INTERVAL_EA);
+ intEA = MAX_INTERVAL_EA;
+ }
+
+ if (confirmState == PING_ST_INIT) {
+ confirmState = PING_ALL_FLAG;
+ }
+
+ pthread_mutex_lock(&ping->mutex_int);
+ if (get_mask(ping, confirmState) == true && get_mask(ping, PING_ST_TIMEOUT) == false) {
+ memset(ping->interval, 0, sizeof(int64_t) * MAX_INTERVAL_EA);
+ for (i = 0; i < intEA; i++) {
+ ping->interval[i] = intervals[i];
+ }
+ ping->int_seq = 0;
+ res = true;
+
+ if (confirmState != PING_ALL_FLAG) {
+ unset_mask(ping, confirmState);
+ }
+
+ if (confirmState == PING_ST_INTUPDATE) {
+ set_mask(ping, PING_ST_INTUPDATED);
+ }
+ }
+ pthread_mutex_unlock(&ping->mutex_int);
+
+ THINGS_LOG(THINGS_DEBUG, TAG, "Exit.");
+ return res;
+}
+
+static bool set_def_interval(things_ping_s *ping)
+{
+ if (ping == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "ping is NULL.");
+ return false;
+ }
+
+ pthread_mutex_lock(&ping->mutex_int);
+ memset(ping->interval, 0, sizeof(int64_t) * MAX_INTERVAL_EA);
+ ping->interval[0] = (int64_t) 1;
+ ping->interval[1] = (int64_t) 2;
+ ping->interval[2] = (int64_t) 4;
+ ping->interval[3] = (int64_t) 8;
+ ping->int_seq = 0;
+ pthread_mutex_unlock(&ping->mutex_int);
+
+ return true;
+}
+
+static bool things_ping_create_thread(things_ping_s *ping)
+{
+ THINGS_LOG(THINGS_DEBUG, TAG, "Enter.");
+
+ bool res = false;
+
+ if (ping == NULL || ping->addr == NULL || ping->port == 0) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Invalid arguments.(ping=0x%X)", ping);
+ if (ping) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Invalid arguments.(addr=%s, port=%d)", ping->addr, ping->port);
+ }
+ return res;
+ }
+
+ pthread_mutex_lock(&ping->mutex_thread);
+ if (ping->handle_thread == 0) {
+#ifdef __ST_THINGS_RTOS__
+ if (pthread_create_rtos(&ping->handle_thread, NULL, (pthread_func_type) thd_ping_loop, ping, THINGS_STACK_PING_THREAD) != 0)
+#else
+ if (things_thread_create(&ping->handle_thread, NULL, (pthread_func_type) thd_ping_loop, ping) != 0)
+#endif
+ {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Create thd_ping_loop thread is failed.");
+ ping->handle_thread = 0;
+ goto GOTO_OUT;
+ }
+
+ set_mask(ping, PING_ST_STARTTHREAD);
+ res = true;
+ }
+GOTO_OUT:
+ pthread_mutex_unlock(&ping->mutex_thread);
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Exit.(result=%d)", res);
+ return res;
+}
+
+static bool things_ping_destroy_thread(things_ping_s *ping)
+{
+ THINGS_LOG(THINGS_DEBUG, TAG, "Enter.");
+
+ bool res = false;
+
+ if (ping == NULL || ping->addr == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Invalid arguments.(ping=0x%X)", ping);
+ return res;
+ }
+
+ pthread_mutex_lock(&ping->mutex_thread);
+ if (ping->handle_thread) {
+#ifdef __ST_THINGS_RTOS__
+ ping->continue_thread = false;
+ sleep(2); /* wait till thread exit */
+ pthread_detach(ping->handle_thread);
+#else /* there is problem in artik during thread_cancel hence avoiding it */
+ pthread_cancel(ping->handle_thread);
+ pthread_detach(ping->handle_thread);
+#endif
+ ping->handle_thread = 0;
+ ping->continue_thread = false;
+ set_def_interval(ping);
+
+ unset_mask(ping, PING_ST_STARTTHREAD | PING_ST_DISCOVERY | PING_ST_REQUEST | PING_ST_INTUPDATE | PING_ST_TIMEOUT);
+ res = true;
+ }
+ pthread_mutex_unlock(&ping->mutex_thread);
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Exit.(result=%d)", res);
+ return res;
+}
+
+static void things_rep_payload_value_print(OCRepPayloadValue *value)
+{
+ switch (value->type) {
+ case OCREP_PROP_INT:
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Key: %s, Value: %lld, int", value->name, value->i);
+ break;
+ case OCREP_PROP_DOUBLE:
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Key: %s, Value: %f, double", value->name, value->d);
+ break;
+ case OCREP_PROP_STRING:
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Key: %s, Value: %s, string", value->name, value->str);
+ break;
+ case OCREP_PROP_BOOL:
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Key: %s, Value: %d, bool", value->name, value->b);
+ break;
+ case OCREP_PROP_BYTE_STRING:
+ THINGS_LOG_V(THINGS_DEBUG, TAG, "Key: %s(binary) size : %d", value->name, value->ocByteStr.len);
+ //OCPrintByteValue( value->ocByteStr.bytes, value->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!
+ THINGS_LOG_V(THINGS_DEBUG, TAG, "Key: %s(OCRep):%s", value->name, value->obj->uri);
+ break;
+ case OCREP_PROP_ARRAY:
+ switch (value->arr.type) {
+ case OCREP_PROP_INT:
+ THINGS_LOG_V(THINGS_DEBUG, TAG, "Key: %s(int array):%zu x %zu x %zu", value->name, value->arr.dimensions[0], value->arr.dimensions[1], value->arr.dimensions[2]);
+ for (size_t iter = 0; iter < value->arr.dimensions[0]; iter++) {
+ THINGS_LOG_V(THINGS_DEBUG, TAG, "Key: \t(int):%d", value->arr.iArray[iter]);
+ }
+ break;
+ case OCREP_PROP_DOUBLE:
+ THINGS_LOG_V(THINGS_DEBUG, TAG, "Key: %s(double array):%zu x %zu x %zu", value->name, value->arr.dimensions[0], value->arr.dimensions[1], value->arr.dimensions[2]);
+ for (size_t iter = 0; iter < value->arr.dimensions[0]; iter++) {
+ THINGS_LOG_V(THINGS_DEBUG, TAG, "Key: \t(double):%f", value->arr.dArray[iter]);
+ }
+ break;
+ case OCREP_PROP_BOOL:
+ THINGS_LOG_V(THINGS_DEBUG, TAG, "Key: %s(bool array):%zu x %zu x %zu", value->name, value->arr.dimensions[0], value->arr.dimensions[1], value->arr.dimensions[2]);
+ for (size_t iter = 0; iter < value->arr.dimensions[0]; iter++) {
+ THINGS_LOG_V(THINGS_DEBUG, TAG, "Key: \t(bool):%s", value->arr.bArray[iter] ? "true" : "false");
+ }
+ break;
+ case OCREP_PROP_STRING:
+ THINGS_LOG_V(THINGS_DEBUG, TAG, "Key: %s(string array):%zu x %zu x %zu", value->name, value->arr.dimensions[0], value->arr.dimensions[1], value->arr.dimensions[2]);
+ for (size_t iter = 0; iter < value->arr.dimensions[0]; iter++) {
+ THINGS_LOG_V(THINGS_DEBUG, TAG, "Key: \t(string):%s", value->arr.strArray[iter]);
+ }
+ break;
+ case OCREP_PROP_BYTE_STRING:
+ THINGS_LOG_V(THINGS_DEBUG, TAG, "Key: %s(byte array):%zu x %zu x %zu", value->name, value->arr.dimensions[0], value->arr.dimensions[1], value->arr.dimensions[2]);
+ break;
+ default:
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Key: %s <-- Unknown/unsupported array type!", value->name);
+ break;
+ }
+ break;
+ default:
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Un supported val Type.(0x%d)", value->type);
+ break;
+ }
+}
+
+#include "cloud_manager.h"
+
+static char *make_host_addr(const char *ip, const uint16_t port)
+{
+ THINGS_LOG(THINGS_DEBUG, TAG, "Enter.");
+
+ char *host = NULL;
+ int length = 0;
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "ip=%s, port=%d", ip, port);
+ if (ip == NULL || strlen(ip) == 0 || port == 0) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Invalid arguments.");
+ return NULL;
+ }
+
+ length = strlen(ip) + 7 + strlen(DEFAULT_COAP_TCP_HOST);
+ if ((host = (char *)things_malloc(sizeof(char) * length)) == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "memory allocation is failed.");
+ return NULL;
+ }
+ // Update Cloud Address.
+ memset(host, 0, length);
+ if (snprintf(host, length, "%s%s:%d", DEFAULT_COAP_TCP_HOST, ip, port) >= length) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "[Error] host buffer is overflowed.");
+ things_free(host);
+ host = NULL;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "host = %s", host);
+
+ THINGS_LOG(THINGS_DEBUG, TAG, "Exit.");
+ return host;
+}
+
+static OCStackResult send_keep_alive_update_request(const char *host, int64_t *intervals, int intEA, OCCallbackData *cb)
+{
+ OCDoHandle g_req_handle = NULL;
+ OCStackResult result = OC_STACK_ERROR;
+ char targetUri[MAX_URI_LENGTH * 2] = { 0, };
+ OCRepPayload *payload = NULL;
+ size_t dimensions[MAX_REP_ARRAY_DEPTH] = { 0, 0, 0 };
+
+ if (host == NULL || strlen(host) == 0 || intervals == NULL || intEA == 0) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "Invalid event_data.(host=%s, intervals=0x%X, intEA=%d)", host, intervals, intEA);
+ result = OC_STACK_NO_MEMORY;
+ goto no_memory;
+ }
+
+ snprintf(targetUri, MAX_URI_LENGTH * 2, "%s%s", host, KEEPALIVE_RESOURCE_URI);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "oicping Update Request to : %s", targetUri);
+
+ payload = OCRepPayloadCreate();
+ if (!payload) {
+ result = OC_STACK_NO_MEMORY;
+ goto no_memory;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "intEA=%d", intEA);
+ for (int i = 0; i < intEA; i++) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "intervals[%d]=%d", i, intervals[i]);
+ }
+
+ dimensions[0] = (size_t) intEA;
+ OCRepPayloadSetIntArray(payload, INTERVAL_ARRAY, intervals, dimensions);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "key : %s", INTERVAL_ARRAY);
+
+//#if defined (__WITH_DTLS__) || defined(__WITH_TLS__)
+// CASelectCipherSuite(0x35, (1 << 4));
+//#endif
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Send OCSendKeepAliveRequest request to %s.", host);
+ result = OCSendKeepAliveRequest(&g_req_handle, host, payload, cb);
+// result = OCDoResource(&g_req_handle, OC_REST_POST, targetUri,
+// NULL, (OCPayload *) payload, CT_ADAPTER_TCP,
+// OC_HIGH_QOS, cb, NULL, 0);
+
+ if (result != OC_STACK_OK) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "oicping Update Request Sending is failed.(URI: %s)", targetUri);
+ OCRepPayloadDestroy(payload);
+ }
+
+no_memory:
+ return result;
+}
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 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.
+ *
+ ****************************************************************************/
+
+#define _POSIX_C_SOURCE 200809L
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include "things_queue.h"
+#include "things_logger.h"
+#include "things_malloc.h"
+
+//#include "oicrequest.h"
+
+#define TAG "[things_queue]"
+
+/**
+ * Push an item into queue, if this is the first item,
+ * both queue->head and queue->tail will point to it,
+ * otherwise the oldtail->next and tail will point to it.
+ */
+void enQueue(queue_s *queue, void *item, int req)
+{
+
+ if (queue == NULL || item == NULL) {
+ return;
+ }
+
+ pthread_mutex_lock(&(queue->q_mutex));
+ // Create a new node
+ things_node_s *n = (things_node_s *) things_malloc(sizeof(things_node_s));
+ if (NULL == n) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, THINGS_MEMORY_ERROR);
+ return;
+ }
+ n->item = item;
+ n->req = req;
+ n->next = NULL;
+
+ if (queue->head == NULL) { // no head
+ queue->head = n;
+ } else {
+ queue->tail->next = n;
+ }
+ queue->tail = n;
+ queue->size++;
+
+ pthread_mutex_unlock(&(queue->q_mutex));
+}
+
+/**
+ * Return and remove the first item.
+ */
+void *deQueue(queue_s *queue, int *req)
+{
+
+ if (queue == NULL || queue->head == NULL) {
+ return NULL;
+ }
+
+ pthread_mutex_lock(&(queue->q_mutex));
+
+ // get the first item
+ things_node_s *head = queue->head;
+
+ void *item = head->item;
+ *req = head->req;
+ // move head pointer to next node, decrease size
+ queue->head = head->next;
+ queue->size--;
+ // free the memory of original head
+ things_free(head);
+
+ pthread_mutex_unlock(&(queue->q_mutex));
+
+ return item;
+}
+
+/**
+ * Return but not remove the first item.
+ */
+void *peek(queue_s *queue, int *req)
+{
+
+ pthread_mutex_lock(&(queue->q_mutex));
+
+ things_node_s *head = queue->head;
+ *req = head->req;
+
+ pthread_mutex_unlock(&(queue->q_mutex));
+
+ return head->item;
+}
+
+/**
+ * Return but not remove the first item.
+ */
+int getLength(queue_s *queue)
+{
+
+ pthread_mutex_lock(&(queue->q_mutex));
+
+ int length = queue->size;
+
+ pthread_mutex_unlock(&(queue->q_mutex));
+
+ return length;
+}
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 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.
+ *
+ ****************************************************************************/
+
+#define _POSIX_C_SOURCE 200809L
+
+#include <pthread.h>
+#include <sched.h>
+
+#include "things_rtos_util.h"
+
+#define TAG "[things_rtos_util]"
+
+static char thingsStackthreadName[THINGS_STACK_MAX_INDEX][40] = { {"THINGS_STACK_PING"}, /*THINGS_STACK_PING_THREAD */
+ {"THINGS_STACK_WAITHANDLER"}, /*THINGS_STACK_WAITHANDLER_THREAD */
+ {"THINGS_STACK_RESETLOOP"}, /*THINGS_STACK_RESETLOOP_THREAD */
+ {"THINGS_STACK_CICONN_INIT"}, /*THINGS_STACK_CICONNETION_INIT_THREAD */
+ {"THINGS_STACK_CICONN_WAIT"}, /*THINGS_STACK_CICONNETION_WAIT_THREAD */
+ {"THINGS_STACK_WIFIPROV_SET"}, /*THINGS_STACK_WIFI_PROV_SET_THREAD */
+ {"THINGS_STACK_CLOUD_REFRESH"}, /*THINGS_STACK_CLOUD_REFRESH_THREAD */
+ {"THINGS_STACK_MSG_HANDLING"}, /*THINGS_STACK_MESSAGE_HANDLING_THREAD */
+ {"THINGS_STACK_PRESENCE_NOTI"}, /*THINGS_STACK_PRESENCE_NOTI_THREAD */
+ {"THINGS_STACK_SERVEREXCE_LOOP"}, /*THINGS_STACK_SERVEREXCETUE_LOOP_THREAD */
+ {"THINGS_STACK_BASE_TIME_OUT"}, /*THINGS_STACK_BASE_TIME_OUT_THREAD */
+ {"THINGS_STACK_OICABORT"},
+ {"THINGS_STACK_MAX_INDEX"} /*THINGS_STACK_MAX_INDEX */
+};
+
+/**
+ *
+ * @param ethreadName
+ * @param pstThread
+ * @return
+ */
+char *GetPthreadAttrDetails(things_stack_thread_name ethreadName, pthread_attr_t *pstThread)
+{
+ if (ethreadName >= THINGS_STACK_MAX_INDEX) {
+ ethreadName = THINGS_STACK_MAX_INDEX;
+ }
+
+ if (pstThread != NULL) {
+ pthread_attr_init(pstThread);
+ struct sched_param sparam;
+ pthread_attr_init(pstThread);
+ pthread_attr_setschedpolicy(pstThread, SCHED_RR);
+ sparam.sched_priority = PTHREAD_DEFAULT_PRIORITY;
+ pthread_attr_setschedparam(pstThread, &sparam);
+
+ pthread_attr_setstacksize(pstThread, 8193); /**Default Stack Size**/
+ switch (ethreadName) {
+ case THINGS_STACK_RESETLOOP_THREAD:
+ case THINGS_STACK_PING_THREAD:
+ case THINGS_STACK_CICONNETION_INIT_THREAD:
+ case THINGS_STACK_CLOUD_REFRESH_THREAD:
+ case THINGS_STACK_PRESENCE_NOTI_THREAD:
+ case THINGS_STACK_WAITHANDLER_THREAD:
+ pthread_attr_setstacksize(pstThread, 4 * 1024);
+ break;
+
+ case THINGS_STACK_CICONNETION_WAIT_THREAD:
+ pthread_attr_setstacksize(pstThread, 6 * 1024);
+ break;
+ case THINGS_STACK_SERVEREXCETUE_LOOP_THREAD:
+ case THINGS_STACK_MESSAGE_HANDLING_THREAD:
+ pthread_attr_setstacksize(pstThread, 6 * 1024);
+ /* its the main process thread for all request */
+ break;
+
+ default:
+ pthread_attr_setstacksize(pstThread, 8193);
+ break;
+ }
+ }
+
+ return thingsStackthreadName[ethreadName];
+
+}
+
+int pthread_create_rtos(FAR pthread_t *thread, FAR const pthread_attr_t *attr, pthread_startroutine_t start_routine, pthread_addr_t arg, things_stack_thread_name eThreadname)
+{
+ pthread_attr_t stPtr;
+ char *pchTname = GetPthreadAttrDetails(eThreadname, &stPtr);
+ int ret = pthread_create(thread, &stPtr, start_routine, (void *)arg);
+ if (ret == 0) {
+ pthread_setname_np(*thread, pchTname);
+ pthread_detach(*thread);
+ }
+ return ret;
+}
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 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 <stdio.h>
+#include <string.h>
+
+#include "things_string_util.h"
+#include "things_malloc.h"
+#include "things_logger.h"
+
+#define TAG "[things_string_util]"
+
+int compare_strings(const char *src, const char *dst)
+{
+ if ((NULL == src) || (NULL == dst)) {
+ return -1;
+ }
+
+ int srcLen = strlen(src);
+ int dstLen = strlen(dst);
+
+ if (srcLen != dstLen) {
+ return -1;
+ }
+
+ return strncmp(src, dst, dstLen);
+}
+
+int duplicate_string(const char *src, char **dst)
+{
+ if (NULL == src) {
+ return 0;
+ } else {
+ int len = strlen(src);
+ *dst = (char *)things_malloc(len + 1);
+ if (NULL == *dst) {
+ printf("memory allocation failed!\n");
+ return 0;
+ }
+
+ memset(*dst, 0, len + 1);
+ things_strncpy(*dst, src, len);
+ }
+ return 1;
+}
+
+// Memory Leakage Should be check
+void concat_string(char **target, char *attach)
+{
+ char buf[MAX_BUF_LEN] = { 0 };
+
+ if (attach == NULL) {
+ return;
+ }
+
+ if (*target != NULL) {
+ things_strncpy(buf, *target, strlen(*target) + 1);
+ things_free(*target);
+ *target = NULL;
+ }
+
+ if (MAX_BUF_LEN >= (strlen(buf) + strlen(attach))) {
+ strncat(buf, attach, MAX_BUF_LEN);
+ } else {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Something went wrong");
+ return;
+ }
+
+ *target = (char *)things_malloc(strlen(buf) + 1);
+ if (NULL == *target) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, THINGS_MEMORY_ERROR);
+ return;
+ }
+ things_strncpy(*target, buf, strlen(buf) + 1);
+}
+
+int hex_string_to_int(const char *hex, int *num)
+{
+ return sscanf(hex, "%x", num);
+}
+
+int get_id_value_from_query(char idvalue[], char *inputQuery, int size)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Input query => %s", inputQuery);
+
+ char seperators[] = "?;#&";
+
+ if (NULL == inputQuery) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Input query is NULL");
+ return 0;
+ }
+
+ if (size > MAX_INPUT_QUERY_LEN) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Input size bigger than maximum query size(%d)", MAX_INPUT_QUERY_LEN);
+ return 0;
+ }
+
+ /*[Jaehong] (Need to consider trim to remove space in query) */
+ // Remove empty space
+ char queries[MAX_INPUT_QUERY_LEN + 1] = { 0, };
+ int index = 0;
+ for (int i = 0; i < strlen(inputQuery); i++) {
+ if (*(inputQuery + i) == ' ') {
+ continue;
+ }
+ queries[index] = *(inputQuery + i);
+ index++;
+ }
+
+ // Get Query start with "id="
+ char *idQuery = strstr(queries, "id=");
+ if (NULL == idQuery) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "There is no \"id=\" in input query");
+ return 0;
+ }
+ // Seperate idQuery with seperators [?, ;, #]
+ for (int i = 0; i < strlen(idQuery); i++) {
+ if (*(idQuery + i) == '?' || *(idQuery + i) == ';' || *(idQuery + i) == '#' || *(idQuery + i) == '&') {
+ strtok(idQuery, seperators);
+ break;
+ }
+ }
+
+ // Get id data after "id=" and validation check.
+ for (int i = 3, k = 0; i < strlen(idQuery); i++) {
+ if (idQuery[i] >= '0' && idQuery[i] <= '9') {
+ idvalue[k++] = idQuery[i];
+ } else {
+ idvalue[0] = '\0';
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+char *things_strcat(char *dest, size_t destSize, const char *src)
+{
+ if (dest == NULL || src == NULL || destSize == 0) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "dest(0x%X) or src(0x%X) or dest_size=%d is NULL.", dest, src, destSize);
+ return NULL;
+ }
+
+ if (strlen(src) >= (destSize - strlen(dest))) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Source Size(%d) is over than Dest-FreeSize(%d).", strlen(src), destSize - strlen(dest) - 1);
+ return NULL;
+ }
+
+ return strncat(dest, src, strlen(src));
+}
+
+char *things_strncpy(char *destination, const char *source, size_t num)
+{
+ if (NULL == source) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Input String is NULL");
+ return NULL;
+ }
+
+ return strncpy(destination, source, num);
+}
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 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 <stdio.h>
+#include <stdlib.h>
+
+#include "things_logger.h"
+#include "things_malloc.h"
+
+#include "things_thread.h"
+
+#define TAG "[things_thread]"
+
+int things_thread_create(pthread_t *__newthread, pthread_attr_t *__attr, void *(*__start_routine)(void *), void *__arg)
+{
+ THINGS_LOG(THINGS_DEBUG, TAG, "Enter.");
+ int ret = 0;
+#ifndef __ST_THINGS_RTOS__
+ int ret = -1;
+ pthread_attr_t attr;
+ pthread_attr_t *pAttr;
+
+ if (__newthread == NULL || __start_routine == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Input invalied.(mandatory var: __newthread=0x%X, __start_routine=0x%X", __newthread, __start_routine);
+ return ret;
+ }
+
+ pAttr = __attr;
+
+ if (__attr == NULL) {
+ if (pthread_attr_init(&attr) != 0) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "pthread_attr_init() is failed.");
+ return ret;
+ }
+
+ if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "pthread_attr_setdetachstate() is failed.");
+ return ret;
+ }
+
+ pAttr = &attr;
+ }
+
+ ret = pthread_create(__newthread, pAttr, __start_routine, __arg);
+
+ if (__attr == NULL) {
+ if (pthread_attr_destroy(&attr) != 0) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "pthread_attr_destroy() is failed.");
+ }
+ }
+
+ THINGS_LOG(THINGS_DEBUG, TAG, "Exit.");
+#endif
+ return ret;
+}
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright 2017 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.
+ *
+ ****************************************************************************/
+
+#define _POSIX_C_SOURCE 200809L
+#include <stdbool.h>
+#include <stdlib.h>
+#include <pthread.h>
+
+#include "things_malloc.h"
+#include "things_logger.h"
+#include "things_wait_handler.h"
+
+#include "things_thread.h"
+#ifdef __ST_THINGS_RTOS__
+#include "things_rtos_util.h"
+#endif
+
+#define TAG "[waithandler]"
+
+#define MAX_RANDOM_NUM 2999
+
+#define MAX_SENDHANDLES 25
+
+typedef void *(*PthreadFunc)(void *param);
+
+typedef struct TimeOutManager_s {
+ timeout_s timeout;
+ pthread_t gthreadId;
+ OCDoHandle handleVal;
+ check_time_out_call_func funcName;
+} TimeOutManager_s;
+
+static int iSendHandle = 0;
+static OCDoHandle gSendHandle[MAX_SENDHANDLES] = { NULL, };
+
+static pthread_mutex_t gREQmutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t gTimeOutmutex = PTHREAD_MUTEX_INITIALIZER;
+
+OCDoHandle get_request_handle(void)
+{
+ int i = 0;
+ OCDoHandle result = NULL;
+
+ pthread_mutex_lock(&gREQmutex);
+ for (i = iSendHandle - 1; i >= 0; i--) { // latest gSendHandle Value return.
+ if (gSendHandle[i] != NULL) {
+ result = gSendHandle[i];
+ break;
+ }
+ }
+ pthread_mutex_unlock(&gREQmutex);
+
+ return result;
+}
+
+int cas_request_handle(OCDoHandle EqualVal, OCDoHandle writeHandleVal)
+{
+ int i = 0;
+ int res = 0;
+
+ pthread_mutex_lock(&gREQmutex);
+ for (i = iSendHandle - 1; i >= 0; i--) { // latest gSendHandle Value check.
+ if (gSendHandle[i] == EqualVal) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Found request handler.(%d th : 0x%X)", i, gSendHandle[i]);
+ gSendHandle[i] = writeHandleVal;
+ res = 1;
+ break;
+ }
+ }
+ pthread_mutex_unlock(&gREQmutex);
+
+ return res;
+}
+
+bool is_empty_request_handle(void)
+{
+ bool isEmpty = false;
+
+ pthread_mutex_lock(&gREQmutex);
+ if (iSendHandle < MAX_SENDHANDLES) {
+ isEmpty = true;
+ }
+ pthread_mutex_unlock(&gREQmutex);
+
+ return isEmpty;
+}
+
+OCDoHandle add_request_handle(OCDoHandle HandleVal)
+{
+ OCDoHandle result = NULL;
+
+ pthread_mutex_lock(&gREQmutex);
+ if (iSendHandle >= MAX_SENDHANDLES) {
+ THINGS_LOG_V(THINGS_INFO, TAG, "gSendHandle array is Full.");
+ } else {
+ gSendHandle[iSendHandle] = HandleVal;
+ result = gSendHandle[iSendHandle];
+ iSendHandle++;
+ }
+ pthread_mutex_unlock(&gREQmutex);
+
+ return result;
+}
+
+void del_all_request_handle(void)
+{
+ int i = 0;
+
+ pthread_mutex_lock(&gREQmutex);
+ for (i = 0; i < iSendHandle; i++) {
+ gSendHandle[i] = NULL;
+ }
+ iSendHandle = 0;
+ pthread_mutex_unlock(&gREQmutex);
+}
+
+/************************************************************
+ *
+ * Thread for Time-Out Process for Handle base
+ *
+ * Time-Out : DEFAULT_TIMEOUT sec.
+ *
+ ************************************************************/
+static void *HandleBaseTimeOutLoop(TimeOutManager_s *pTimeOutManager)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Enter.");
+
+ static int cntTimeOutThread = 0;
+
+ pthread_mutex_lock(&gTimeOutmutex);
+ cntTimeOutThread++;
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[HD Start] Count of Time-Out thread is %d.", cntTimeOutThread);
+ pthread_mutex_unlock(&gTimeOutmutex);
+
+ sleep(1);
+
+ if (pTimeOutManager == NULL || pTimeOutManager->gthreadId < 0 || pTimeOutManager->funcName == NULL || pTimeOutManager->timeout.cur_counter <= 0) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Parameter is invalid.");
+ if (pTimeOutManager) {
+ things_free(pTimeOutManager);
+ }
+
+ return 0;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "handleVal=0x%X, timeCounter=%d, funcName=0x%X", pTimeOutManager->handleVal, pTimeOutManager->timeout.cur_counter, pTimeOutManager->funcName);
+
+ while (get_request_handle() != NULL && pTimeOutManager->handleVal == get_request_handle()) { // get_request_handle() != NULL will guarantee for Connecting to AP.
+ sleep(1);
+
+ if (--pTimeOutManager->timeout.cur_counter == 0) {
+ if (cas_request_handle(pTimeOutManager->handleVal, NULL) == 1) { // cas_request_handle(handle, NULL) == 1 will guarantee that AP is connected and handle is latest important request.
+ pTimeOutManager->funcName(&pTimeOutManager->timeout);
+ }
+ pTimeOutManager->handleVal = (void *)(-1);
+ }
+ }
+
+ things_free(pTimeOutManager);
+ pthread_mutex_lock(&gTimeOutmutex);
+ cntTimeOutThread--;
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[HD End] Count of Time-Out thread is %d.", cntTimeOutThread);
+ pthread_mutex_unlock(&gTimeOutmutex);
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Exit.");
+
+ return 0;
+}
+
+long long next_time_out(const long long ori_num, const long long cur_num)
+{
+ long long x = 0;
+ long long nextT = -1;
+
+ if (ori_num <= 0 || cur_num <= 0) {
+ THINGS_LOG_V(THINGS_INFO, TAG, "Not Enabled PDF re-try.");
+ return nextT;
+ }
+
+ while (cur_num >= nextT) {
+ x = (long long)rand() * (long long)(MAX_RANDOM_NUM + 1);
+// pkes x = x / (long long)((unsigned int)MAX_RAND+(unsigned int)1);
+ x = x / (long long)((unsigned int)RAND_MAX + (unsigned int)1);
+ x = x + 500;
+
+ if (x < 500 || x > MAX_RANDOM_NUM + 500) {
+ THINGS_LOG_V(THINGS_INFO, TAG, "X value invalid.");
+ break;
+ }
+
+ nextT = ((long long)ori_num * ((long long)10000000000000 + x * x * x * x)) / (long long)10000000000000;
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Gaussian next Time-Out Number: nextT = %lld", nextT);
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "next Time-Out: %lld", nextT);
+ return nextT;
+}
+
+unsigned long int create_time_out_process(OCDoHandle hadler, check_time_out_call_func CallFunc, timeout_s *timeOut)
+{
+ TimeOutManager_s *pTimeOutManager = NULL;
+
+ if ((pTimeOutManager = (TimeOutManager_s *) things_malloc(sizeof(TimeOutManager_s))) == NULL || CallFunc == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Memory allocation is failed.");
+ return 0;
+ }
+
+ pTimeOutManager->gthreadId = NULL;
+ pTimeOutManager->handleVal = hadler;
+ pTimeOutManager->funcName = CallFunc;
+ if (timeOut == NULL) {
+ pTimeOutManager->timeout.cur_counter = DEFAULT_TIMEOUT; // default second.
+ pTimeOutManager->timeout.ori_num = DEFAULT_TIMEOUT; // default second.
+ pTimeOutManager->timeout.cur_num = DEFAULT_TIMEOUT; // default second.
+ } else {
+ pTimeOutManager->timeout.cur_counter = timeOut->cur_counter;
+ pTimeOutManager->timeout.ori_num = timeOut->ori_num;
+ pTimeOutManager->timeout.cur_num = timeOut->cur_num;
+ }
+
+#ifdef __ST_THINGS_RTOS__
+ if (pthread_create_rtos(&pTimeOutManager->gthreadId, NULL, (PthreadFunc) HandleBaseTimeOutLoop, (void *)pTimeOutManager, THINGS_STACK_WAITHANDLER_THREAD) != 0)
+#else
+ if (things_thread_create(&pTimeOutManager->gthreadId, NULL, (PthreadFunc) HandleBaseTimeOutLoop, (void *)pTimeOutManager) != 0)
+#endif
+ {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Create thread is failed.");
+ things_free(pTimeOutManager);
+ return 0;
+ }
+
+ return pTimeOutManager->gthreadId;
+}
--- /dev/null
+###########################################################################
+#
+# Copyright 2017 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.
+#
+###########################################################################
+
+CSRCS += things_rtos_apis.c things_stack.c
+
+DEPPATH += --dep-path src/st_things/things_stack/src/stack
+VPATH += :src/st_things/things_stack/src/stack
\ No newline at end of file
--- /dev/null
+/* ****************************************************************
+ *
+ * Copyright 2017 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 <pthread.h>
+
+#include "things_api.h"
+#include "things_def.h"
+#include "things_logger.h"
+#include "things_req_handler.h"
+#include "octypes.h"
+#include "ocpayload.h"
+#include "things_malloc.h"
+#include "oic_string.h"
+#include "things_server_builder.h"
+
+#ifdef __ST_THINGS_RTOS__
+
+#define TAG "[thingsstacknew]"
+
+extern things_request_handler_s *g_req_handler;
+extern things_server_builder_s *g_server_builder;
+
+#endif
--- /dev/null
+/* ****************************************************************
+ *
+ * Copyright 2017 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.
+ *
+ ******************************************************************/
+
+#define _POSIX_C_SOURCE 200809L
+#define _BSD_SOURCE // for the usleep
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <pthread.h>
+#include "ocpayload.h"
+#include "octypes.h"
+#include "ocstack.h"
+#include "things_api.h"
+#include "things_types.h"
+#include "things_def.h"
+#include "things_common.h"
+#include "things_logger.h"
+#include "things_malloc.h"
+#include "things_string_util.h"
+
+#include "things_resource.h"
+#include "things_server_builder.h"
+#include "things_security_manager.h"
+#include "things_req_handler.h"
+
+#include "things_data_manager.h"
+
+#include "../common/utils/inc/things_network.h"
+#include "easysetup_manager.h"
+#include "cloud_manager.h"
+#include "cloud_evtpend.h"
+
+#include <wifi_manager/wifi_manager.h>
+
+#include "things_thread.h"
+#ifdef __ST_THINGS_RTOS__
+#include "things_rtos_util.h"
+#endif
+
+#define TAG "[things_stack]"
+
+typedef void *(*pthread_func_type)(void *);
+
+volatile static int g_quit_flag = 0;
+volatile static int is_things_module_inited = 0;
+
+typedef struct s_abort_s {
+ pthread_t *h_thread;
+ things_es_enrollee_abort_e level;
+} s_abort_s;
+
+typedef struct reset_args_s {
+ things_resource_s *remote_owner;
+ things_es_enrollee_reset_e resetType;
+} reset_args_s;
+
+things_abort_easysetup_func_type g_abort_easysetup = NULL;
+
+things_server_builder_s *g_server_builder = NULL;
+things_request_handler_s *g_req_handler = NULL;
+
+things_reset_confirm_func_type g_confirm_reset_start = NULL;
+things_sec_otm_state_func_type g_otm_event_handler = NULL;
+
+static pthread_mutex_t g_app_cb_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t g_things_stop_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static pthread_mutex_t g_wifi_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t g_wifi_cond;
+static wifi_manager_scan_info_s *g_wifi_scan_info;
+static int g_wifi_scan_count;
+
+#define WIFI_SCAN_SIGNAL \
+do { \
+ pthread_mutex_lock(&g_wifi_mutex); \
+ pthread_cond_signal(&g_wifi_cond); \
+ pthread_mutex_unlock(&g_wifi_mutex); \
+} while (0)
+
+#define WIFI_SCAN_WAIT \
+do { \
+ pthread_mutex_lock(&g_wifi_mutex); \
+ pthread_cond_wait(&g_wifi_cond, &g_wifi_mutex); \
+ pthread_mutex_unlock(&g_wifi_mutex); \
+} while (0)
+
+static bool b_reset_continue_flag = false;
+static bool b_thread_things_reset = false;
+static pthread_t h_thread_things_reset = NULL;
+static pthread_t h_thread_things_wifi_join = NULL;
+static pthread_mutex_t m_thread_oic_reset = PTHREAD_MUTEX_INITIALIZER;
+static volatile rst_state_e m_reset_bit_mask = RST_COMPLETE;
+
+static void *t_things_reset_loop(reset_args_s *args);
+static void *t_things_abort_loop(s_abort_s *contents);
+
+const char *things_get_sw_version()
+{
+ return OIC_STACK_FIRMWARE_VERSION;
+}
+
+const char *things_get_device_id_string()
+{
+ return OCGetServerInstanceIDString();
+}
+
+int things_set_device_name(int dev_num, char *name)
+{
+ int res = 0;
+ if (!is_things_module_inited) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Stack not initialized");
+ } else {
+ if (dev_num > 0) {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "Dev Num %d Not Supported Yet", dev_num);
+ } else {
+ if (NULL != name && strlen(name) > 0) {
+ OCStackResult result = OCSetPropertyValue(PAYLOAD_TYPE_DEVICE,
+ OC_RSRVD_DEVICE_NAME,
+ name);
+ if (result == OC_STACK_OK) {
+ res = 1;
+ } else {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "Set Device Name Failed : %d ", result);
+ }
+ } else {
+ THINGS_LOG_D_ERROR(THINGS_ERROR, TAG, "Invalid Device Name : %s ", name);
+ }
+ }
+ }
+
+ return res;
+}
+
+// This logic will be refactored later to reflact whole easy-setup states..
+int things_get_easysetup_state(void)
+{
+ bool isOwned = false;
+ // 1. check the owned state
+ if (OC_STACK_OK != OCGetDeviceOwnedState(&isOwned)) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Failed to get device owned state, Informing as UNOWNED~!!!!");
+ isOwned = false;
+ }
+ // 2. check the resource publish state if necessary..
+
+ // 3. anything else to check???
+
+ return (isOwned == true);
+}
+
+int things_register_easysetup_state_func(things_get_easysetup_state_func_type func)
+{
+ int res = 0;
+
+ if (func != NULL) {
+ es_register_notify_easysetup_state((void *)func);
+ res = 1;
+ }
+
+ return res;
+}
+
+static void *__attribute__((optimize("O0"))) t_things_wifi_join_loop(void *args)
+{
+ wifi_manager_info_s wifi_info;
+ wifi_manager_get_info(&wifi_info);
+
+ char cur_device_ip_address[18 + 1];
+ wifi_net_ip4_addr_to_ip4_str(wifi_info.ip4_address, cur_device_ip_address);
+
+ things_wifi_changed_call_func(1, wifi_info.ssid, cur_device_ip_address);
+}
+
+void things_wifi_sta_connected(void)
+{
+ THINGS_LOG_D(THINGS_INFO, TAG, "T%d --> %s", getpid(), __FUNCTION__);
+
+ pthread_create_rtos(&h_thread_things_wifi_join, NULL, (pthread_func_type) t_things_wifi_join_loop, NULL, THINGS_STACK_WIFI_JOIN);
+ pthread_detach(h_thread_things_wifi_join);
+}
+
+void things_wifi_sta_disconnected(void)
+{
+ THINGS_LOG_D(THINGS_INFO, TAG, "T%d --> %s", getpid(), __FUNCTION__);
+}
+
+void things_wifi_soft_ap_sta_joined(void)
+{
+ THINGS_LOG_D(THINGS_INFO, TAG, "T%d --> %s", getpid(), __FUNCTION__);
+
+}
+
+void things_wifi_soft_ap_sta_left(void)
+{
+ THINGS_LOG_D(THINGS_INFO, TAG, "T%d --> %s", getpid(), __FUNCTION__);
+}
+
+void things_wifi_scan_done(wifi_manager_scan_info_s **scan_result, int res)
+{
+ THINGS_LOG_D(THINGS_INFO, TAG, "T%d --> %s", getpid(), __FUNCTION__);
+ /* Make sure you copy the scan results onto a local data structure.
+ * It will be deleted soon eventually as you exit this function.
+ */
+//TO DO
+}
+
+static const wifi_manager_cb_s wifi_callbacks = {
+ things_wifi_sta_connected,
+ things_wifi_sta_disconnected,
+ things_wifi_soft_ap_sta_joined,
+ things_wifi_soft_ap_sta_left,
+ things_wifi_scan_done,
+};
+
+typedef int8_t INT8;
+
+bool try_connect_home_ap(wifi_manager_ap_config_s *connect_config)
+{
+ wifi_manager_result_e result = WIFI_MANAGER_SUCCESS;
+
+ int retry_count = 0;
+
+ for (; retry_count < 3; retry_count++) {
+ result = wifi_manager_connect_ap(connect_config);
+
+ if (result == WIFI_MANAGER_SUCCESS) {
+ break;
+ } else {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Failed to connect WiFi");
+ }
+ }
+
+ if (retry_count == 3) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Failed to connect WiFi 3 times");
+ return false;
+ }
+
+ return true;
+}
+
+bool try_turn_on_soft_ap()
+{
+ wifi_manager_info_s info;
+ wifi_manager_get_info(&info);
+
+ if (info.mode != SOFTAP_MODE) {
+ wifi_manager_softap_config_s *ap_config = dm_get_softap_wifi_config();
+ if (wifi_manager_set_mode(SOFTAP_MODE, ap_config) != WIFI_MANAGER_SUCCESS) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Failed to change to SOFTAP mode");
+ return false;
+ }
+ }
+ THINGS_LOG(THINGS_INFO, TAG, "In SOFTAP mode");
+ return true;
+}
+
+bool things_handle_stop_soft_ap(wifi_manager_ap_config_s *connect_config)
+{
+ wifi_manager_result_e result = WIFI_MANAGER_SUCCESS;
+ wifi_manager_info_s info;
+ wifi_manager_get_info(&info);
+
+ if (info.mode == SOFTAP_MODE) {
+ if (wifi_manager_set_mode(STA_MODE, NULL) != WIFI_MANAGER_SUCCESS) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Failed to change to STA mode)");
+ return false;
+ }
+ usleep(100000);
+ }
+
+ int retry_count = 0;
+
+ for (; retry_count < 3; retry_count++) {
+ result = wifi_manager_connect_ap(connect_config);
+
+ if (result == WIFI_MANAGER_SUCCESS) {
+ break;
+ } else {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Failed to connect WiFi");
+ }
+ }
+
+ if (retry_count == 3) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Failed to connect WiFi 3 times");
+ return false;
+ }
+
+ if (connect_config != NULL) {
+ save_acces_point_info(connect_config);
+ }
+
+ return true;
+}
+
+INT8 things_wifi_connection_cb(access_point_info_s *p_info, char *p_cmd_id)
+{
+ THINGS_LOG_D(THINGS_INFO, TAG, "T%d --> %s", getpid(), __FUNCTION__);
+
+ if (p_info == NULL) {
+ THINGS_LOG_D(THINGS_INFO, TAG, "Invalid params");
+ return -1;
+ }
+
+ wifi_manager_ap_config_s connect_config;
+
+ strncpy(connect_config.ssid, p_info->e_ssid, sizeof(connect_config.ssid));
+ connect_config.ssid_length = strlen(connect_config.ssid);
+ strncpy(connect_config.passphrase, p_info->security_key, sizeof(connect_config.passphrase));
+
+ connect_config.passphrase_length = strlen(connect_config.passphrase);
+
+ THINGS_LOG_D(THINGS_INFO, TAG, "[%s] ssid : %s", __FUNCTION__, connect_config.ssid);
+ THINGS_LOG_D(THINGS_INFO, TAG, "[%s] passphrase : %s", __FUNCTION__, connect_config.passphrase);
+
+ // set auth type
+ if (strncmp(p_info->auth_type, "WEP", strlen("WEP")) == 0) {
+ connect_config.ap_auth_type = WIFI_MANAGER_AUTH_WEP_SHARED;
+ } else if (strncmp(p_info->auth_type, "WPA-PSK", strlen("WPA-PSK")) == 0) {
+ connect_config.ap_auth_type = WIFI_MANAGER_AUTH_WPA_PSK;
+ } else if (strncmp(p_info->auth_type, "WPA2-PSK", strlen("WPA2-PSK")) == 0) {
+ connect_config.ap_auth_type = WIFI_MANAGER_AUTH_WPA2_PSK;
+ }
+ // set encryption crypto type
+ if (strncmp(p_info->enc_type, "WEP-64", strlen("WEP-64")) == 0) {
+ connect_config.ap_crypto_type = WIFI_MANAGER_CRYPTO_WEP_64;
+ } else if (strncmp(p_info->enc_type, "WEP-128", strlen("WEP-128")) == 0) {
+ connect_config.ap_crypto_type = WIFI_MANAGER_CRYPTO_WEP_128;
+ } else if (strncmp(p_info->enc_type, "TKIP", strlen("TKIP")) == 0) {
+ connect_config.ap_crypto_type = WIFI_MANAGER_CRYPTO_TKIP;
+ } else if (strncmp(p_info->enc_type, "AES", strlen("AES")) == 0) {
+ connect_config.ap_crypto_type = WIFI_MANAGER_CRYPTO_AES;
+ } else if (strncmp(p_info->enc_type, "TKIP_AES", strlen("TKIP_AES")) == 0) {
+ connect_config.ap_crypto_type = WIFI_MANAGER_CRYPTO_TKIP_AND_AES;
+ }
+
+ int ret = things_handle_stop_soft_ap(&connect_config);
+ if (ret != 1) {
+ return -1;
+ }
+
+ return 1;
+}
+
+access_point_info_s *create_access_info()
+{
+ access_point_info_s *info = (access_point_info_s *) things_malloc(sizeof(access_point_info_s));
+ memset(info->e_ssid, 0, MAX_ESSID);
+ memset(info->security_key, 0, MAX_SECUIRTYKEY);
+ memset(info->auth_type, 0, MAX_TYPE_AUTH);
+ memset(info->enc_type, 0, MAX_TYPE_ENC);
+ memset(info->channel, 0, MAX_CHANNEL);
+ memset(info->signal_level, 0, MAX_LEVEL_SIGNAL);
+ memset(info->bss_id, 0, MAX_BSSID);
+ return info;
+}
+
+int things_wifi_search_cb(access_point_info_s *** p_info, int *p_count)
+{
+ THINGS_LOG_V(THINGS_INFO, TAG, THINGS_FUNC_ENTRY);
+//TO DO
+ (*p_count) = 0;
+
+ return 1;
+
+}
+
+static void otm_event_cb(const char *addr, uint16_t port, const char *uuid, int event)
+{
+ switch (event) {
+ case OIC_OTM_READY:
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "OIC_OTM_READY");
+ break;
+ case OIC_OTM_STARTED:
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "OIC_OTM_STARTED");
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[%s:%d][%s]", addr, port, uuid);
+ break;
+ case OIC_OTM_DONE:
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "OIC_OTM_DONE");
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "[%s:%d][%s]", addr, port, uuid);
+ break;
+ case OIC_OTM_ERROR:
+ THINGS_LOG_D(THINGS_ERROR, TAG, "OIC_OTM_ERROR");
+ break;
+ default:
+ THINGS_LOG_D(THINGS_ERROR, TAG, "Unknown");
+ break;
+ }
+ if (g_otm_event_handler) {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Call the registered funcation...");
+ g_otm_event_handler(addr, port, uuid, event);
+ }
+}
+
+int things_initialize_stack(const char *json_path, bool *easysetup_completed)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+
+ if (is_things_module_inited) {
+ THINGS_LOG(THINGS_ERROR, TAG, "Stack already initialized");
+ return 0;
+ }
+
+ things_log_init();
+ things_log_set_version(OIC_STACK_FIRMWARE_VERSION);
+
+ if (!dm_init_module(json_path)) {
+ THINGS_LOG(THINGS_ERROR, TAG, "dm_init_module() failed");
+ return 0;
+ }
+ is_things_module_inited = 1;
+
+ *easysetup_completed = dm_is_there_things_cloud();
+
+ return 1;
+}
+
+int things_send_push_message(const char *push_uri, void *payload)
+{
+ if (payload == NULL) {
+ THINGS_LOG(THINGS_ERROR, TAG, "payload is NULL");
+ return 0;
+ }
+ if (!push_notification_to_cloud(push_uri, (OCRepPayload *) payload)) {
+ THINGS_LOG_D(THINGS_ERROR, TAG, "push_notification_to_cloud() failed");
+ return 0;
+ }
+ return 1;
+}
+
+int things_deinitialize_stack()
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+
+ dm_termiate_module();
+
+ is_things_module_inited = 0;
+
+ return 1;
+}
+
+int things_start_stack()
+{
+ things_register_set_ap_connection_func(things_wifi_connection_cb);
+ things_register_get_ap_list_func(things_wifi_search_cb);
+
+ if (wifi_manager_init(&wifi_callbacks) != WIFI_MANAGER_SUCCESS) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Failed to initialize WiFi manager");
+ return 0;
+ }
+ THINGS_LOG_D(THINGS_INFO, TAG, "THINGS_STACK version : %s", OIC_STACK_FIRMWARE_VERSION);
+
+ if (dm_get_easysetup_connectivity_type() == es_conn_type_softap) {
+ if (dm_is_there_things_cloud() == false) {
+ if (!try_turn_on_soft_ap()) {
+ return 0;
+ }
+ } else { // Alread Owned.
+ wifi_manager_ap_config_s *ap_config = dm_get_homeap_wifi_config();
+ try_connect_home_ap(ap_config);
+ }
+ } else if (dm_get_easysetup_connectivity_type() == es_conn_type_ble) {
+ //TO DO
+ } else {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "es_conn_type_Unknown");
+ return 0;
+ }
+
+ // 2. Enable Security Features
+#ifdef __SECURED__
+ int auty_type = AUTH_UNKNOW;
+ switch (dm_get_ownership_transfer_method()) {
+ case 1: // PIN
+ auty_type = AUTH_RANDOM_PIN;
+ break;
+ case 2: // USER_CONFIRM
+ auty_type = AUTH_CERTIFICATE_CONFIRM;
+ break;
+ case 3: // BOTH
+ auty_type = AUTH_RANDOM_PIN + AUTH_CERTIFICATE_CONFIRM;
+ break;
+ }
+
+ if (0 != sm_init_things_security(auty_type, dm_get_svrdb_file_path())) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Failed to initialize OICSecurity features");
+ things_stop();
+ return 0;
+ }
+ sm_set_otm_event_handler(otm_event_cb);
+#endif
+ g_req_handler = get_handler_instance();
+ if (NULL == g_req_handler) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Failed to initialize Request Handler");
+ things_stop();
+ return 0;
+ }
+ // Will be refactored to received callbacks for GET/PUT/POST/DELETE/OBSERVE ..
+ g_req_handler->init_module();
+
+ // 4. Initiate Server Builder
+ g_server_builder = get_builder_instance();
+ if (NULL == g_server_builder) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Failed to initialize Resource Server");
+ things_stop();
+ return 0;
+ }
+
+ g_server_builder->init_module(g_server_builder, g_req_handler->entity_handler);
+
+#ifdef __SECURED__
+ //5. Generate MAC based device UUID
+ if (0 != sm_generate_mac_based_device_id(false)) {
+ THINGS_LOG(THINGS_WARNING, TAG, "Failed to generate MAC based device_id");
+ things_stop();
+ return 0;
+ }
+#endif
+
+ // 6. Register Device-ID & Resources
+ if (dm_register_device_id() == false) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Failed to register Device ID");
+ things_stop();
+ return 0;
+ }
+
+ if (!dm_register_resource(g_server_builder)) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Failed to register Resource");
+ things_stop();
+ return 0;
+ }
+ // 7. Initiate Easy-Setup & Login to Cloud
+ if (ESM_OK != esm_init_easysetup(0, g_server_builder)) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Failed to initialize Easy-Setup Module");
+ things_stop();
+ return 0;
+ }
+ // Register Callback
+ esm_register_cloud_cb(cloud_data_cb_esm);
+
+ if (es_cloud_init(g_server_builder) == NULL) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Failed to initialize Cloud");
+ things_stop();
+ return 0;
+ }
+
+ is_things_module_inited = 1;
+
+ g_quit_flag = 0;
+
+ THINGS_LOG_D(THINGS_INFO, TAG, "Stack Initialization Success");
+ return 1;
+}
+
+int things_reset(void *remote_owner, things_es_enrollee_reset_e resetType)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+
+ if (resetType == RST_AUTO_RESET) {
+ try_turn_on_soft_ap();
+ }
+
+ int res = -1;
+
+ if (b_thread_things_reset) {
+ return 0;
+ }
+
+ if (resetType >= RST_ENUM_EOF || resetType < RST_NEED_CONFIRM) {
+ THINGS_LOG_D(THINGS_INFO, TAG, "Not support things_es_enrollee_reset_e value(%d). So, Set value with RST_NEED_CONFIRM", resetType);
+ resetType = RST_NEED_CONFIRM;
+ }
+
+ if (g_confirm_reset_start == NULL) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Reset-Start confirmation Function is not registered. It's mandatory");
+ return res;
+ }
+
+ pthread_mutex_lock(&m_thread_oic_reset);
+ if (b_thread_things_reset == false) {
+ b_thread_things_reset = true;
+ reset_args_s *args = (reset_args_s *) things_malloc(sizeof(reset_args_s));
+ if (args == NULL) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Failed to allocate reset_args_s memory");
+ b_thread_things_reset = false;
+ res = -1;
+ goto GOTO_OUT;
+ }
+ args->remote_owner = (things_resource_s *) remote_owner;
+ args->resetType = resetType;
+
+ b_reset_continue_flag = true;
+#ifdef __ST_THINGS_RTOS__
+ if (pthread_create_rtos(&h_thread_things_reset, NULL, (pthread_func_type) t_things_reset_loop, args, THINGS_STACK_RESETLOOP_THREAD) != 0)
+#else
+ if (things_thread_create(&h_thread_things_reset, NULL, (pthread_func_type) t_things_reset_loop, args) != 0)
+#endif
+ {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Failed to create thread");
+ h_thread_things_reset = 0;
+ things_free(args);
+ args = NULL;
+ b_thread_things_reset = false;
+ res = -1;
+ goto GOTO_OUT;
+ }
+ pthread_detach(h_thread_things_reset);
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Reset Thread handler = 0x%X", h_thread_things_reset);
+ res = 1;
+ } else {
+ THINGS_LOG(THINGS_INFO, TAG, "Already run Reset-Process.");
+ res = 0;
+ }
+
+GOTO_OUT:
+ pthread_mutex_unlock(&m_thread_oic_reset);
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_EXIT);
+
+ return res;
+}
+
+int things_stop(void)
+{
+ pthread_mutex_lock(&g_things_stop_mutex);
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+ g_quit_flag = 1;
+ is_things_module_inited = 0;
+
+ pthread_mutex_lock(&m_thread_oic_reset);
+ if (b_thread_things_reset == true) {
+ b_reset_continue_flag = false;
+ h_thread_things_reset = 0;
+ b_thread_things_reset = false;
+ }
+ pthread_mutex_unlock(&m_thread_oic_reset);
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Terminate Cloud Session Managing");
+ es_cloud_terminate();
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Terminate EasySetup");
+ esm_terminate_easysetup();
+
+ if (g_server_builder != NULL) {
+ g_server_builder->deinit_module(g_server_builder);
+ release_builder_instance(g_server_builder);
+ g_server_builder = NULL;
+ }
+ if (g_req_handler != NULL) {
+ g_req_handler->deinit_module();
+ release_handler_instance(g_req_handler);
+ g_req_handler = NULL;
+ }
+ // Need to add memory release for the Queue..
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_EXIT);
+
+ pthread_mutex_unlock(&g_things_stop_mutex);
+ return 1;
+}
+
+int things_register_confirm_reset_start_func(things_reset_confirm_func_type func)
+{
+ if (func != NULL) {
+ g_confirm_reset_start = func;
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+int things_notify_observers(const char *uri)
+{
+ if (g_req_handler == NULL) {
+ THINGS_LOG(THINGS_ERROR, TAG, "g_req_handler is NULL");
+ return 0;
+ }
+ return g_req_handler->notify_things_observers(uri);
+}
+
+int things_register_update_dev_prov_data_func(things_update_dev_prov_data_func_type func)
+{
+ if (func != NULL) {
+ esm_register_update_dev_prov_data_func(func);
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+int things_register_set_ap_connection_func(things_set_ap_connection_func_type func)
+{
+ // Stack (Easy-setup) can request device to access specific AP
+ // with this registered callback
+ if (func != NULL) {
+ things_register_set_ap_conn_func(func);
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+int things_wifi_changed_call_func(int state, char *ap_name, char *ip_addr)
+{
+ int ret = 0;
+
+ if (is_things_module_inited == 0) {
+ return ret;
+ }
+
+ pthread_mutex_lock(&g_app_cb_mutex);
+#ifdef __ST_THINGS_RTOS__
+ pthread_mutex_lock(&m_thread_oic_reset);
+ ret = things_wifi_state_changed_cb(state, ap_name, ip_addr);
+ pthread_mutex_unlock(&m_thread_oic_reset);
+#else
+ ret = things_wifi_state_changed_cb(state, ap_name, ip_addr);
+#endif
+ pthread_mutex_unlock(&g_app_cb_mutex);
+
+ return ret;
+}
+
+int things_register_stop_soft_ap_func(things_stop_soft_ap_func_type func)
+{
+ if (NULL != func) {
+ return register_stop_softap_cb(func);
+ } else {
+ return 0;
+ }
+}
+
+int things_register_pin_generated_func(things_pin_generated_func_type func)
+{
+ if (NULL != func) {
+#ifdef __SECURED__
+ return esm_register_pin_generated_cb(func);
+#else
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Stack is in UNSECURED Mode");
+ return 0;
+#endif
+ } else {
+ return 0;
+ }
+}
+
+int things_register_pin_display_close_func(things_pin_display_close_func_type func)
+{
+ if (NULL != func) {
+#ifdef __SECURED__
+ return esm_register_pin_close_cb(func);
+#else
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Stack is in UNSECURED Mode");
+ return 0;
+#endif
+ } else {
+ return 0;
+ }
+}
+
+int things_register_user_confirm_func(things_get_user_confirm_func_type func)
+{
+ if (NULL != func) {
+#ifdef __SECURED__
+ return esm_register_user_confirm_cb(func);
+#else
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Stack is in UNSECURED Mode");
+ return 0;
+#endif
+ } else {
+ return 0;
+ }
+}
+
+int things_register_handle_request_func(things_handle_request_func_type get_func, things_handle_request_func_type set_func)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+ if ((NULL == get_func) || (NULL == set_func)) {
+ THINGS_LOG(THINGS_ERROR, TAG, "Callback is NULL");
+ return 0;
+ }
+ register_handle_request_func(get_func, set_func);
+ return 1;
+}
+
+//////////////////////////////////////////////////////////////////////////
+// Functions Definition for Security feature
+//////////////////////////////////////////////////////////////////////////
+int things_register_otm_event_handler(things_sec_otm_state_func_type otmEventCallback)
+{
+ THINGS_LOG(THINGS_DEBUG, TAG, THINGS_FUNC_ENTRY);
+#ifdef __SECURED__
+ if (otmEventCallback == NULL) {
+ THINGS_LOG(THINGS_ERROR, TAG, "otmEventCallback is NULL");
+ return 0;
+ }
+ g_otm_event_handler = otmEventCallback;
+#else
+ THINGS_LOG(THINGS_ERROR, TAG, "Stack is in UNSECURED Mode");
+ return 0;
+#endif
+ return 1;
+}
+
+int things_save_acl(const char *uuid, const char *resourceUri, const char *resourceType, const char *interfaceName, uint16_t permission)
+{
+ int ret = -1;
+ THINGS_LOG(THINGS_DEBUG, TAG, "In things_save_acl");
+#ifdef __SECURED__
+ ret = sm_save_acl(uuid, resourceUri, resourceType, interfaceName, permission);
+#else
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Stack is in UNSECURED Mode");
+#endif
+ THINGS_LOG(THINGS_DEBUG, TAG, "Out things_save_acl");
+ return ret;
+}
+
+int things_set_mot_status(bool enable)
+{
+ int ret = -1;
+ THINGS_LOG(THINGS_DEBUG, TAG, "In things_set_mot_status");
+#ifdef __SECURED__
+ ret = sm_set_mot_status(enable);
+#else
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Stack is in UNSECURED Mode");
+#endif
+ THINGS_LOG(THINGS_DEBUG, TAG, "Out things_set_mot_status");
+ return ret;
+}
+
+//////////////////////////////////////////////////////////////////////////
+// Functions Definition for Reset Handling.
+//////////////////////////////////////////////////////////////////////////
+static void things_set_reset_mask(rst_state_e value)
+{
+ if (value != RST_COMPLETE) {
+ m_reset_bit_mask |= value;
+ } else {
+ m_reset_bit_mask = value;
+ }
+}
+
+bool things_get_reset_mask(rst_state_e value)
+{
+ return (int)(m_reset_bit_mask & value) != 0 ? true : false;
+}
+
+void things_control_queue_empty(void)
+{
+ if (things_get_reset_mask(RST_CONTROL_MODULE_DISABLE) == true) {
+ things_set_reset_mask(RST_CONTROL_QUEUE_EMPTY);
+ }
+}
+
+int things_return_user_opinion_for_reset(int b_reset_start) // b_reset_start : User opinion.
+{
+ THINGS_LOG(THINGS_DEBUG, TAG, "Enter.");
+
+ int result = 0;
+
+ if (b_reset_start == true && b_reset_continue_flag == true) { // User allow Reset-Starting.
+ things_set_reset_mask(RST_USER_CONFIRM_COMPLETED);
+ result = 1;
+ } else { // User not allow Reset.
+ b_reset_continue_flag = false;
+ }
+
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "User Opinion : %d", result);
+
+ THINGS_LOG(THINGS_DEBUG, TAG, "Exit.");
+ return result;
+}
+
+static void *__attribute__((optimize("O0"))) t_things_reset_loop(reset_args_s *args)
+{
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Enter. Handler=0x%X", h_thread_things_reset);
+
+ int result = 0;
+ things_reset_result_func_type things_cb_func_for_reset_result = NULL;
+
+ if (args == NULL) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "args is NULL. It's mandatory.");
+ goto GOTO_OUT;
+ }
+
+ if (g_confirm_reset_start == NULL) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Reset-Start confirmation Function is not registered. It's mandatory.");
+ goto GOTO_OUT;
+ }
+
+ things_set_reset_mask(RST_COMPLETE);
+ THINGS_LOG(THINGS_DEBUG, TAG, "Start Reset Processing.");
+
+ // 0. Trigger User-Confirm GUI and Wait for getting User-Opinion with regard to Reset.
+ THINGS_LOG(THINGS_DEBUG, TAG, "Trigger Reset-GUI.");
+ if (g_confirm_reset_start(&things_cb_func_for_reset_result, args->resetType) == 0) {
+ THINGS_LOG(THINGS_DEBUG, TAG, "User don't want to reset. So reset canceled.");
+ goto GOTO_OUT;
+ }
+
+ THINGS_LOG(THINGS_DEBUG, TAG, "Waiting User-Opinion for Reset-Start.");
+ while (b_reset_continue_flag == true && things_get_reset_mask(RST_USER_CONFIRM_COMPLETED) == false) { // It's Blocking until receive user-opinion.
+ usleep(300000); // 0.3 seconds wait.
+ }
+
+ THINGS_LOG(THINGS_DEBUG, TAG, "Break-Stop Check.");
+ if (b_reset_continue_flag == false) {
+ THINGS_LOG(THINGS_DEBUG, TAG, "Called Reset break-STOP.");
+ goto GOTO_OUT;
+ }
+ // 1. Easy Setup : Provisioning Disable.
+ // 2. Controlling Module : Disable pushing request to Queue.
+ THINGS_LOG(THINGS_DEBUG, TAG, "Disable Modules.(EasySetup/Controlling Module)");
+ things_set_reset_mask(RST_EASY_SETUP_DISABLE | RST_CONTROL_MODULE_DISABLE);
+
+ THINGS_LOG(THINGS_DEBUG, TAG, "Break-Stop Check.");
+ if (b_reset_continue_flag == false) {
+ THINGS_LOG(THINGS_DEBUG, TAG, "Called Reset break-STOP.");
+ goto GOTO_OUT;
+ }
+ // 3. Notification Push Disable.
+ THINGS_LOG(THINGS_DEBUG, TAG, "Disable Notification Module.");
+ things_set_reset_mask(RST_NOTI_MODULE_DISABLE);
+
+ OCClearObserverlist(); // delete All Observer. (for remote Client)
+
+ // 4. Cloud Manager : Terminate
+ THINGS_LOG(THINGS_DEBUG, TAG, "Terminate Cloud Module.");
+ es_cloud_terminate();
+
+ // 5. Easy Setup : Terminate
+ THINGS_LOG(THINGS_DEBUG, TAG, "Terminate Easy-Setup Module.");
+ if (esm_terminate_easysetup() != ESM_MODULE_TERMINATED) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Easy-Setup Module termination failed");
+ goto GOTO_OUT;
+ }
+ // 6. Delete Cloud data in "provisioning.json"
+ THINGS_LOG(THINGS_DEBUG, TAG, "Delete Cloud-Data in provisioning.json file.");
+ if (dm_del_things_cloud_data() == 0) {
+ THINGS_LOG(THINGS_DEBUG, TAG, "It's failed to delete information about Cloud-Data in \"ocf_infoX.json\" file.");
+ goto GOTO_OUT;
+ }
+ THINGS_LOG(THINGS_INFO, TAG, "Reset done: cloud provisioning data");
+
+ OCClearCallBackList(); // delete All Client Call-Back List. (for SET Self-Request)
+
+ // 7. Security Reset.
+#ifdef __SECURED__
+ if (0 != sm_reset_svrdb()) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Failed to initialize OICSecurity features.");
+ goto GOTO_OUT;
+ }
+ THINGS_LOG(THINGS_INFO, TAG, "Reset done: security resources");
+
+ if (0 != sm_generate_mac_based_device_id(true)) {
+ THINGS_LOG(THINGS_WARNING, TAG, "Failed to generate MAC based device_id.");
+ goto GOTO_OUT;
+ }
+#else
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "NOT SECURED MODE!!!!! ");
+#endif
+
+ // 8. Easy Setup : Initialization.
+ THINGS_LOG(THINGS_DEBUG, TAG, "Initial Easy-Setup Module.");
+ if (ESM_OK != esm_init_easysetup(0, g_server_builder)) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Easy-Setup Module initialization failed");
+ goto GOTO_OUT;
+ }
+ esm_register_cloud_cb(cloud_data_cb_esm);
+
+ // 9. Cloud Manager : Initialization.
+ THINGS_LOG(THINGS_DEBUG, TAG, "Initial Cloud Module.");
+ if (es_cloud_init(g_server_builder) == NULL) {
+ THINGS_LOG(THINGS_DEBUG, TAG, "It's failed Cloud_Module initialization.");
+ goto GOTO_OUT;
+ }
+
+ THINGS_LOG(THINGS_DEBUG, TAG, "Reset Success.");
+ result = 1;
+
+GOTO_OUT:
+ // 10. All Module Enable.
+ things_set_reset_mask(RST_COMPLETE);
+
+ /*SVACE warning fix */
+ if (args) {
+ // 11. If reset-processing is triggered by remote-owner, then Notify result of Reset.
+ THINGS_LOG(THINGS_DEBUG, TAG, "Notify result of reset to remote-client.(mobile)");
+ notify_result_of_reset(args->remote_owner, result);
+ }
+ // 12. If there is Reset Result Call-Back Function, then Notify result of Reset to st_things-Application.
+ if (things_cb_func_for_reset_result) { // Notify result of reset to st_things.
+ THINGS_LOG(THINGS_DEBUG, TAG, "Notify result of reset to st_things.");
+ things_cb_func_for_reset_result(result);
+ }
+
+ if (args) {
+ things_free(args);
+ args = NULL;
+ }
+ pthread_mutex_lock(&m_thread_oic_reset);
+ h_thread_things_reset = 0;
+ b_thread_things_reset = false;
+ pthread_mutex_unlock(&m_thread_oic_reset);
+ THINGS_LOG(THINGS_DEBUG, TAG, "Exit.");
+ return NULL;
+}
+
+OCEntityHandlerResult things_abort(pthread_t *h_thread_abort, things_es_enrollee_abort_e level)
+{
+ s_abort_s *ARGs = NULL;
+ OCEntityHandlerResult eh_result = OC_EH_ERROR;
+
+ if (h_thread_abort == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "h_thread_abort is NULL.");
+ return eh_result;
+ }
+
+ if ((*h_thread_abort) == 0) {
+ if ((ARGs = (s_abort_s *) things_malloc(sizeof(s_abort_s))) == NULL) {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Memory Allocation is failed.(for abort Thread)");
+ return OC_EH_ERROR;
+ }
+
+ ARGs->h_thread = h_thread_abort;
+ ARGs->level = level;
+
+ eh_result = OC_EH_OK;
+#ifdef __ST_THINGS_RTOS__
+ if (pthread_create_rtos(h_thread_abort, NULL, (pthread_func_type) t_things_abort_loop, ARGs, THINGS_STACK_OICABORT_THREAD) != 0)
+#else
+ if (things_thread_create(h_thread_abort, NULL, (pthread_func_type) t_things_abort_loop, ARGs) != 0)
+#endif
+
+ {
+ THINGS_LOG_V_ERROR(THINGS_ERROR, TAG, "Create thread is failed.(for abort Thread)");
+ *h_thread_abort = 0;
+ eh_result = OC_EH_ERROR;
+ }
+ } else {
+ THINGS_LOG_D(THINGS_DEBUG, TAG, "Already called Thread. So, OC_EH_NOT_ACCEPTABLE");
+ eh_result = OC_EH_NOT_ACCEPTABLE;
+ }
+
+ pthread_detach(h_thread_abort);
+ return eh_result;
+}
+
+static void *__attribute__((optimize("O0"))) t_things_abort_loop(s_abort_s *contents)
+{
+ THINGS_LOG(THINGS_DEBUG, TAG, "Enter.");
+
+ if (contents == NULL) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "contents is NULL.");
+ goto GOTO_OUT;
+ }
+
+ if (g_abort_easysetup != NULL) {
+ THINGS_LOG_ERROR(THINGS_ERROR, TAG, "Registered Abort Function. So, Call Function st_things API.");
+ g_abort_easysetup(contents->level);
+ }
+
+GOTO_OUT:
+ if (contents) {
+ *(contents->h_thread) = 0;
+ things_free(contents);
+ contents = NULL;
+ }
+
+ THINGS_LOG(THINGS_DEBUG, TAG, "Exit.");
+ return NULL;
+}