#include "ttd-build-json.h"
#include "common-util.h"
-#ifndef SERVER_URL
-/* TODO : remove it after test */
-#define TEST_SERVER_URL "http://test.showiot.xyz/api/cmd?&target=test-page-device&owner=test-page&state=created"
-#define SERVER_URL TEST_SERVER_URL
-#endif
-
#define CMD_MGR_GET_INTERVAL_SEC (3600 * 3)
#define RESULT_WAIT_IN_SEC (10)
#define RESULT_WAIT_TIME (RESULT_WAIT_IN_SEC * 1000000)
#define RESULT_WAIT_TRY_MAX (6)
+// #define CMD_FETCH_TEST
+
typedef struct _ttd_result_data_s {
char *cmd_id;
ttd_cmd_result_e result;
GMutex get_mutex;
GCond get_cond;
GThread *launch_thread;
- int launch_thread_running;
};
+/* Just a pointer value to make unblocking async queue and exiting thread,
+ * it could be any address as long, as it isn't a valid queue item
+ */
+static const gpointer quit_marker = (gpointer) &ttd_cmd_mgr_init;
+
/* Use singleton */
static struct __cmd_mgr_h *g_handle = NULL;
-static const char *__ttd_get_cloud_url(void)
+static void __cmd_id_item_free(gpointer data)
{
- const char *url = NULL;
+ if (!data)
+ return;
- /* TODO : get cloud url */
- url = SERVER_URL;
+ if (data == quit_marker)
+ return;
- return url;
+ g_free(data);
}
static void __result_item_free(gpointer data)
{
ttd_result_data_s *item = data;
- if (!item)
+
+ if (!data)
+ return;
+
+ if (data == quit_marker)
return;
if (item->cmd_id)
retv_if(!handle, -1);
- ret = ttd_http_get_cloud_cmd(__ttd_get_cloud_url(), &cmd, &r_code);
+ ret = ttd_http_command_get(&cmd, &r_code);
if (ret) {
_E("failed to get cmd [%ld]", r_code);
if (res_code)
*res_code = r_code;
return -1;
}
+
if (res_code)
*res_code = r_code;
struct __cmd_mgr_h *handle = data;
g_mutex_lock(&handle->get_mutex);
- while (g_atomic_int_get(&(handle->get_thread_running))) {
+ while (TRUE) {
int ret = 0;
guint64 until = 0;
unsigned int retry = 0;
g_cond_wait_until(&handle->get_cond, &handle->get_mutex, until);
_D("thread unblocked");
- if (g_handle->get_by_request)
+ if (!handle->get_thread_running)
+ break;
+
+ if (handle->get_by_request)
retry = 5;
+ else
+ retry = 1;
- do {
+ while(retry) {
long res_code = 0;
ret = _get_cloud_cmd(handle, &res_code);
break;
retry--;
- g_usleep(G_USEC_PER_SEC); // sleep in 1 second before retry
- } while(retry);
+ if (retry)
+ g_usleep(G_USEC_PER_SEC); // sleep in 1 second before retry
+ };
- g_handle->get_by_request = 0;
+ handle->get_by_request = 0;
}
g_mutex_unlock(&handle->get_mutex);
-
+ _D("thread terminated");
return NULL;
}
{
struct __cmd_mgr_h *handle = data;
- while (g_atomic_int_get(&(handle->launch_thread_running))) {
+ while (TRUE) {
char *cmd_id = NULL;
ttd_cmd_data *cmd_data = NULL;
char *report = NULL;
}
_D("unblock launch thread");
+ if (cmd_id == quit_marker)
+ goto THREAD_EXIT;
+
// get cmd data from cmd_hash
g_mutex_lock(&handle->mutex);
cmd_data = g_hash_table_lookup(handle->cmd_hash, cmd_id);
cmd_type = ttd_cmd_get_type(cmd_data);
report = ttd_build_json_create_report(cmd_id, cmd_type,
TTD_CMD_STATE_RUNNING, 0, "state update", NULL);
- _D("report - %s", report);
- ret = ttd_http_post_cmd_result(
- __ttd_get_cloud_url(), report, &r_code);
+ ret = ttd_http_report_post(report, &r_code);
if (r_code != 200) {
_E("failed to post report [%ld]", r_code);
g_free(report);
_E("cmd[%s] no proper launch function", cmd_id);
report = ttd_build_json_create_report(cmd_id, cmd_type,
TTD_CMD_STATE_FAILED, 0, "no proper launch function", NULL);
- _D("report - %s", report);
- ttd_http_post_cmd_result(__ttd_get_cloud_url(), report, NULL);
+ ttd_http_report_post(report, NULL);
g_free(report);
report = NULL;
goto DONE_N_WAIT;
_E("cmd[%s] launch failed", cmd_id);
report = ttd_build_json_create_report(cmd_id, cmd_type,
TTD_CMD_STATE_FAILED, 0, "command launch failed", NULL);
- _D("report - %s", report);
- ttd_http_post_cmd_result(__ttd_get_cloud_url(), report, NULL);
+ ttd_http_report_post(report, NULL);
g_free(report);
report = NULL;
goto DONE_N_WAIT;
/* timeout to wait result, report fail */
report = ttd_build_json_create_report(cmd_id, cmd_type,
TTD_CMD_STATE_FAILED, 0, "timeout to wait result ", NULL);
- _D("report - %s", report);
- ttd_http_post_cmd_result(__ttd_get_cloud_url(), report, NULL);
+ ttd_http_report_post(report, NULL);
g_free(report);
report = NULL;
break;
}
+ if (result_item == quit_marker)
+ goto THREAD_EXIT;
+
switch (result_item->result) {
case TTD_CMD_RESULT_RUNNING:
/* report running and wait more result */
report = ttd_build_json_create_report(cmd_id, cmd_type,
TTD_CMD_STATE_RUNNING, 0,
"report in progress", result_item->data);
- _D("report - %s", report);
- ttd_http_post_cmd_result(__ttd_get_cloud_url(), report, NULL);
- g_free(report);
- report = NULL;
+ ttd_http_report_post(report, NULL);
break;
case TTD_CMD_RESULT_SUCCESS:
/* report done */
report = ttd_build_json_create_report(cmd_id, cmd_type,
TTD_CMD_STATE_DONE, 0,
"done", result_item->data);
- _D("report - %s", report);
- ttd_http_post_cmd_result(__ttd_get_cloud_url(), report, NULL);
- g_free(report);
- report = NULL;
-
+ ttd_http_report_post(report, NULL);
result_wait = 0;
break;
case TTD_CMD_RESULT_FAIL:
report = ttd_build_json_create_report(cmd_id, cmd_type,
TTD_CMD_STATE_FAILED, 0,
"failed to process command", result_item->data);
- _D("report - %s", report);
- ttd_http_post_cmd_result(__ttd_get_cloud_url(), report, NULL);
- g_free(report);
- report = NULL;
+ ttd_http_report_post(report, NULL);
result_wait = 0;
break;
/* unhandled states */
default:
break;
}
+ g_free(report);
+ report = NULL;
__result_item_free(result_item);
}
g_mutex_unlock(&handle->mutex);
g_free(cmd_id);
}
- }
+ continue;
+THREAD_EXIT:
+ _D("get quit_marker");
+ break;
+ }
+ _D("thread terminated");
return NULL;
}
if (!g_handle)
return;
- g_mutex_clear(&g_handle->mutex);
-
- if (g_handle->launch_thread) {
- g_atomic_int_set(&(g_handle->launch_thread_running), 0);
- g_thread_join(g_handle->launch_thread);
- }
-
if (g_handle->get_thread) {
- g_atomic_int_set(&(g_handle->get_thread_running), 0);
+ g_mutex_lock(&g_handle->get_mutex);
+ g_handle->get_thread_running = 0;
+ g_cond_broadcast(&g_handle->get_cond);
+ g_mutex_unlock(&g_handle->get_mutex);
+
g_thread_join(g_handle->get_thread);
}
g_mutex_clear(&g_handle->get_mutex);
g_cond_clear(&g_handle->get_cond);
+ if (g_handle->launch_thread) {
+ g_async_queue_push(g_handle->cmd_id_queue, quit_marker);
+ g_async_queue_push(g_handle->result_queue, quit_marker);
+
+ g_thread_join(g_handle->launch_thread);
+ }
+
+ g_mutex_clear(&g_handle->mutex);
+
if (g_handle->result_queue)
g_async_queue_unref(g_handle->result_queue);
g_handle = NULL;
}
+#ifdef CMD_FETCH_TEST
static gboolean __get_cmd_first_time(gpointer data)
{
ttd_cmd_mgr_get_cmd();
return G_SOURCE_REMOVE;
}
+#endif /* CMD_FETCH_TEST */
int ttd_cmd_mgr_init(void)
{
g_handle = g_try_malloc0(sizeof(struct __cmd_mgr_h));
retvm_if(!g_handle, -1, "failed to malloc");
- g_handle->cmd_id_queue = g_async_queue_new_full((GDestroyNotify)g_free);
+ g_handle->cmd_id_queue = g_async_queue_new_full(__cmd_id_item_free);
goto_if(!g_handle->cmd_id_queue, ERROR_N_EXIT);
g_handle->cmd_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
g_mutex_init(&g_handle->mutex);
- g_atomic_int_set(&(g_handle->get_thread_running), 1);
g_mutex_init(&g_handle->get_mutex);
g_cond_init(&g_handle->get_cond);
+ g_handle->get_thread_running = 1;
g_handle->get_thread =
g_thread_try_new(NULL, (GThreadFunc)_get_thread, g_handle, &error);
goto ERROR_N_EXIT;
}
- g_atomic_int_set(&(g_handle->launch_thread_running), 1);
g_handle->launch_thread =
g_thread_try_new(NULL, (GThreadFunc)_launch_thread, g_handle, &error);
if (!g_handle->launch_thread) {
goto ERROR_N_EXIT;
}
- // need it ??
+#ifdef CMD_FETCH_TEST
g_idle_add(__get_cmd_first_time, NULL);
+#endif /* CMD_FETCH_TEST */
return 0;
ERROR_N_EXIT:
- g_error_free(error);
+ if (error)
+ g_error_free(error);
__free_cmd_mgr_handle();
return -1;
}
#include <openssl/crypto.h>
#include <glib.h>
#include "ttd-log.h"
+#include "ttd-url.h"
#define CERT_FILE_PATH "/opt/share/cert-svc/ca-certificate.crt"
static GMutex *mutex_a = NULL;
static int http_initialized = 0;
+static char *urls[TTD_URL_TYPE_NUM] = { NULL, };
static void __locking_function(int mode, int n, const char *file, int line)
{
int ttd_http_fini(void)
{
+ int i= 0;
__ssl_thread_mutex_cleanup();
curl_global_cleanup();
+
+ for (i = 0; i < TTD_URL_TYPE_NUM; i++) {
+ g_free(urls[i]);
+ urls[i] = NULL;
+ }
+
http_initialized = 0;
return 0;
}
+static const char *__get_url_by_type(ttd_url_type_e type)
+{
+ if (!urls[type])
+ urls[type] = ttd_url_get_by_type(type);
+
+ return urls[type];
+}
+
static size_t _get_cmd_write(void *ptr, size_t size, size_t nmemb, void *data)
{
size_t res_size = 0;
return res_size;
}
-int ttd_http_get_cloud_cmd(const char *url, char **cmd_json, long *res_code)
+int ttd_http_command_get(char **cmd_json, long *res_code)
{
int ret = 0;
CURL *curl = NULL;
CURLcode res = CURLE_OK;
long r_code = 0;
+ const char *url = NULL;
retvm_if(!http_initialized, -1, "http is not initialized yet");
- retvm_if(!url, -1, "url is null");
retvm_if(!cmd_json, -1, "cmd_json is null");
+ url = __get_url_by_type(TTD_URL_CMD);
+ retvm_if(!url, -1, "failed to get url for command GET");
+
curl = curl_easy_init();
retvm_if(!curl, NULL, "failed to curl_easy_init()");
return ret;
}
-int ttd_http_post_cmd_result(
- const char *url, const char *result_json, long *res_code)
+int ttd_http_report_post(const char *result_json, long *res_code)
{
struct curl_slist *headers = NULL;
+ const char *url = NULL;
+
+ url = __get_url_by_type(TTD_URL_REPORT);
+ retvm_if(!url, -1, "failed to get url for command POST");
+
+ _D("report - %s", result_json);
headers = curl_slist_append(headers, "Accept: application/json");
headers = curl_slist_append(headers, "Content-Type: application/json");
return __ttd_http_post(url, result_json, headers, res_code);
}
-int ttd_http_post_data(const char *url, const char *data, long *res_code)
+int ttd_http_appdata_post(const char *url, const char *data, long *res_code)
{
struct curl_slist *headers = NULL;