<commit_before>/****************************************************************************
 *
 * 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 THINGS_PING_ENABLE      1

#include <sys/types.h>
#include <stdbool.h>
#include <unistd.h>
#include <pthread.h>
#include "ocpayload.h"
#include "octypes.h"
#include "easy-setup/es_common.h"
#include "utils/things_malloc.h"
#include "utils/things_string.h"
#include "logging/things_logger.h"
#include "things_list.h"
#include "things_ping.h"

#ifdef __ST_THINGS_RTOS__
#include "things_rtos_util.h"
#endif

#ifdef THINGS_PING_ENABLE
#include "oickeepalive.h"
#endif
#include "easy-setup/resource_handler.h"
#include "cloud/cloud_manager.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 MAX_RETRY_CNT       10

#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;


pthread_mutex_t mutex_ping_list;
static list_s *list = NULL;
static const char INTERVAL_ARRAY[] = "inarray";
static const char INTERVAL[] = "in";
things_ping_s* p_ping = NULL;

static void *thd_ping_loop(things_ping_s *ping);
static OCStackApplicationResult discover_ping_resource_handler(void *ctx, OCDoHandle handle, OCClientResponse *client_response);
static OCStackApplicationResult handler_ping_request(void *ctx, OCDoHandle handle, OCClientResponse *client_response);

static things_ping_s *create_things_ping_s(const char *remote_addr, const uint16_t port);
static void terminate_things_ping_s(things_ping_s *ping);
static int is_ip_key_equal(things_ping_s *ping, const char *target_ip);
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 post_state);
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(things_ping_s *ping, int64_t *intervals, int int_ea, ping_state_e confirm_state);
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);

#ifdef THINGS_PING_ENABLE
bool things_ping_init(void)
{
	THINGS_LOG_D(TAG, "Enter.");

	bool res = false;

	pthread_mutex_init(&mutex_ping_list, NULL);
	pthread_mutex_lock(&mutex_ping_list);

	if (list == NULL) {
		if ((list = create_list()) == NULL) {
			THINGS_LOG_E(TAG, "memory allocation is failed.");
			pthread_mutex_unlock(&mutex_ping_list);
			return res;
		}

		res = true;
	} else {
		res = true;
	}
	pthread_mutex_unlock(&mutex_ping_list);

	p_ping = NULL;
	THINGS_LOG_D(TAG, "Exit.");
	return res;
}

bool things_ping_terminate(void)
{
	THINGS_LOG_D(TAG, "Enter.");

	pthread_mutex_lock(&mutex_ping_list);
	if (list) {
		THINGS_LOG_D(TAG, "things_ping_s terminate.");
		things_ping_s *ping = NULL;
		while ((ping = (things_ping_s *) list->pop(list)) != NULL) {
			THINGS_LOG_D(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(TAG, "Terminate ping-list.");
		terminate_list(list);
		list = NULL;
	}

	pthread_mutex_unlock(&mutex_ping_list);
	pthread_mutex_destroy(&mutex_ping_list);<commit_msg>framework/st_things: Make ping thread desrtoyed promptly<commit_after>/****************************************************************************
 *
 * 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 THINGS_PING_ENABLE      1

#include <sys/types.h>
#include <stdbool.h>
#include <unistd.h>
#include <pthread.h>
#include "ocpayload.h"
#include "octypes.h"
#include "easy-setup/es_common.h"
#include "utils/things_malloc.h"
#include "utils/things_string.h"
#include "logging/things_logger.h"
#include "things_list.h"
#include "things_ping.h"

#ifdef __ST_THINGS_RTOS__
#include "things_rtos_util.h"
#endif

#ifdef THINGS_PING_ENABLE
#include "oickeepalive.h"
#endif
#include "easy-setup/resource_handler.h"
#include "cloud/cloud_manager.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 MAX_RETRY_CNT       10

#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;


pthread_mutex_t mutex_ping_list;
static list_s *list = NULL;
static const char INTERVAL_ARRAY[] = "inarray";
static const char INTERVAL[] = "in";
things_ping_s* p_ping = NULL;

static void *thd_ping_loop(things_ping_s *ping);
static OCStackApplicationResult discover_ping_resource_handler(void *ctx, OCDoHandle handle, OCClientResponse *client_response);
static OCStackApplicationResult handler_ping_request(void *ctx, OCDoHandle handle, OCClientResponse *client_response);

static things_ping_s *create_things_ping_s(const char *remote_addr, const uint16_t port);
static void terminate_things_ping_s(things_ping_s *ping);
static int is_ip_key_equal(things_ping_s *ping, const char *target_ip);
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 post_state);
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(things_ping_s *ping, int64_t *intervals, int int_ea, ping_state_e confirm_state);
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);

#ifdef THINGS_PING_ENABLE
bool things_ping_init(void)
{
	THINGS_LOG_D(TAG, "Enter.");

	bool res = false;

	pthread_mutex_init(&mutex_ping_list, NULL);
	pthread_mutex_lock(&mutex_ping_list);

	if (list == NULL) {
		if ((list = create_list()) == NULL) {
			THINGS_LOG_E(TAG, "memory allocation is failed.");
			pthread_mutex_unlock(&mutex_ping_list);
			return res;
		}

		res = true;
	} else {
		res = true;
	}
	pthread_mutex_unlock(&mutex_ping_list);

	p_ping = NULL;
	THINGS_LOG_D(TAG, "Exit.");
	return res;
}

bool things_ping_terminate(void)
{
	THINGS_LOG_D(TAG, "Enter.");

	pthread_mutex_lock(&mutex_ping_list);
	if (list) {
		THINGS_LOG_D(TAG, "things_ping_s terminate.");
		things_ping_s *ping = NULL;
		while ((ping = (things_ping_s *) list->pop(list)) != NULL) {
			THINGS_LOG_D(TAG, "Terminate ping.(%s)", ping->addr);
			if (get_mask(ping, PING_ST_STARTTHREAD) == true) {
				things_ping_destroy_thread(ping);
			}
			terminate_things_ping_s(ping);
		}

		THINGS_LOG_D(TAG, "Terminate ping-list.");
		terminate_list(list);
		list = NULL;
	}

	pthread_mutex_unlock(&mutex_ping_list);
	pthread_mutex_destroy(&mutex_ping_list);
{'fraction_non_alphanumeric': 0.12604959004247754, 'fraction_numerical': 0.006717376271856169, 'mean_word_length': 5.790073775989269, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2400114', 'n_tokens_mistral': 3649, 'n_tokens_neox': 3364, 'n_words': 874}