fabbf863965ca77792ebfc66b01d6d15a1ba2421
[apps/native/tizen-things-daemon.git] / daemon / src / ttd-http.c
1 /*
2  * Copyright (c) 2018 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Flora License, Version 1.1 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://floralicense.org/license/
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <curl/curl.h>
18 #include <openssl/crypto.h>
19 #include <glib.h>
20 #include "ttd-log.h"
21
22 #define CERT_FILE_PATH "/opt/share/cert-svc/ca-certificate.crt"
23
24 static GMutex *mutex_a = NULL;
25 static int http_initialized = 0;
26
27 static void __locking_function(int mode, int n, const char *file, int line)
28 {
29         if(mode & CRYPTO_LOCK)
30                 g_mutex_lock(&mutex_a[n]);
31         else
32                 g_mutex_unlock(&mutex_a[n]);
33 }
34
35 static unsigned long __id_function(void)
36 {
37         return ((unsigned long)g_thread_self());
38 }
39
40 int __ssl_thread_mutex_setup(void)
41 {
42         int i;
43
44         mutex_a = g_malloc(CRYPTO_num_locks() * sizeof(GMutex));
45         if(!mutex_a)
46                 return -1;
47
48         for(i = 0; i < CRYPTO_num_locks(); i++)
49                 g_mutex_init(&mutex_a[i]);
50
51         CRYPTO_set_id_callback(__id_function);
52         CRYPTO_set_locking_callback(__locking_function);
53
54         return 0;
55 }
56
57 static int __ssl_thread_mutex_cleanup(void)
58 {
59         int i;
60
61         if(!mutex_a)
62                 return -1;
63
64         CRYPTO_set_id_callback(NULL);
65         CRYPTO_set_locking_callback(NULL);
66
67         for(i = 0; i < CRYPTO_num_locks(); i++)
68                 g_mutex_clear(&mutex_a[i]);
69
70         g_free(mutex_a);
71         mutex_a = NULL;
72
73         return 0;
74 }
75
76
77 int ttd_http_init(void)
78 {
79         int ret = 0;
80         curl_global_init(CURL_GLOBAL_DEFAULT);
81         ret = __ssl_thread_mutex_setup();
82         if (ret) {
83                 _E("failed to setup ssl thread mutex");
84                 return -1;
85         }
86
87         http_initialized = 1;
88
89         return 0;
90 }
91
92 int ttd_http_fini(void)
93 {
94         __ssl_thread_mutex_cleanup();
95         curl_global_cleanup();
96         http_initialized = 0;
97
98         return 0;
99 }
100
101 static size_t _get_cmd_write(void *ptr, size_t size, size_t nmemb, void *data)
102 {
103         size_t res_size = 0;
104         char **received = data;
105
106         res_size = size * nmemb;
107
108         if (received && res_size > 0) {
109                 if (*received) {
110                         char *temp = NULL;
111                         char *new = NULL;
112                         temp = g_strndup((const char *)ptr, res_size);
113                         new = g_strdup_printf("%s%s", *received, temp);
114                         g_free(temp);
115                         g_free(*received);
116                         *received = new;
117                 } else
118                         *received = g_strndup((const char *)ptr, res_size);
119         } else
120                 _E("fail to get response [res size : %d]", res_size);
121
122         return res_size;
123 }
124
125 int ttd_http_get_cloud_cmd(const char *url, char **cmd_json)
126 {
127         int ret = 0;
128         CURL *curl = NULL;
129         CURLcode res = CURLE_OK;
130
131         retvm_if(!http_initialized, -1, "http is not initialized yet");
132         retvm_if(!url, -1, "url is null");
133         retvm_if(!cmd_json, -1, "cmd_json is null");
134
135         curl = curl_easy_init();
136
137         retvm_if(!curl, NULL, "failed to curl_easy_init()");
138
139         curl_easy_setopt(curl, CURLOPT_URL, url);
140         curl_easy_setopt(curl, CURLOPT_CAPATH, CERT_FILE_PATH);
141         curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, _get_cmd_write);
142         curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)cmd_json);
143
144         res = curl_easy_perform(curl);
145         if (res != CURLE_OK) {
146                 _E("curl_easy_perform() failed: %s", curl_easy_strerror(res));
147                 g_free(*cmd_json);
148                 ret = -1;
149         }
150         _D("received cmd : %s", *cmd_json ? *cmd_json : "NULL");
151
152         curl_easy_cleanup(curl);
153
154         return ret;
155 }
156
157 int ttd_http_post_cmd_result(const char *url, const char *result_json)
158 {
159         int ret = 0;
160         CURL *curl = NULL;
161         CURLcode res = CURLE_OK;
162         struct curl_slist *headers = NULL;
163
164         retvm_if(!http_initialized, -1, "http is not initialized yet");
165         retvm_if(!url, -1, "url is null");
166         retvm_if(!result_json, -1, "result_json is null");
167
168         curl = curl_easy_init();
169
170         retvm_if(!curl, NULL, "failed to curl_easy_init()");
171
172         headers = curl_slist_append(headers, "Accept: application/json");
173         headers = curl_slist_append(headers, "Content-Type: application/json");
174
175         /* TODO : what should I do before post result */
176         curl_easy_setopt(curl, CURLOPT_URL, url);
177         curl_easy_setopt(curl, CURLOPT_CAPATH, CERT_FILE_PATH);
178         curl_easy_setopt(curl, CURLOPT_POST, 1L);
179         curl_easy_setopt(curl, CURLOPT_POSTFIELDS, result_json);
180
181         res = curl_easy_perform(curl);
182         if (res != CURLE_OK) {
183                 _E("curl_easy_perform() failed: %s", curl_easy_strerror(res));
184                 ret = -1;
185         }
186
187         curl_slist_free_all(headers);
188         curl_easy_cleanup(curl);
189
190         return ret;
191 }