27f8a37868ea137be6b2c4557c84e9085d05217a
[apps/native/position-finder-server.git] / src / webutil.c
1 /*
2  * Copyright (c) 2017 Samsung Electronics Co., Ltd.
3  *
4  * Contact: Jin Yoon <jinny.yoon@samsung.com>
5  *          Geunsun Lee <gs86.lee@samsung.com>
6  *          Eunyoung Lee <ey928.lee@samsung.com>
7  *          Junkyu Han <junkyu.han@samsung.com>
8  *          Jeonghoon Park <jh1979.park@samsung.com>
9  *
10  * Licensed under the Flora License, Version 1.1 (the License);
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  * http://floralicense.org/license/
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an AS IS BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  */
22
23 #include <stdbool.h>
24 #include <curl/curl.h>
25 #include <glib-object.h>
26 #include <json-glib/json-glib.h>
27 #include "log.h"
28 #include "webutil.h"
29
30 #define URI_PATH_LEN 64
31 #define REQ_CON_TIMEOUT 5L
32 #define REQ_TIMEOUT 7L
33
34 typedef struct _wu_json_handle {
35         JsonBuilder *builder;
36         bool is_begin;
37         bool is_end;
38 } wu_json_handle;
39
40 static wu_json_handle Json_h = {NULL, false, false};
41
42 static size_t _post_response_write_callback(char *ptr, size_t size, size_t nmemb, void *userdata)
43 {
44         size_t res_size = 0;
45
46         res_size = size*nmemb;
47
48         if (res_size > 0)
49                 _I("POST response : %s", ptr);
50         /* What should we do here, if response body has negative message? */
51
52         return res_size;
53 }
54
55 static size_t _get_response_write_callback(void *ptr, size_t size, size_t nmemb, void *data)
56 {
57         size_t res_size = 0;
58         char **received = (char **)data;
59
60         res_size = size*nmemb;
61
62         if (received && res_size > 0)
63                 *received = strndup((char *)ptr, size*nmemb);
64         else
65                 _E("fail to get response [res size : %d]", res_size);
66
67         return res_size;
68 }
69
70 int web_util_noti_init(void)
71 {
72         int ret = 0;
73         CURLcode result;
74         result = curl_global_init(CURL_GLOBAL_DEFAULT);
75         if (result != CURLE_OK) {
76                 _E("curl_global_init() failed: %s",
77                         curl_easy_strerror(result));
78                 ret = -1;
79         }
80         return ret;
81 }
82
83 void web_util_noti_fini(void)
84 {
85         curl_global_cleanup();
86         return;
87 }
88
89 int web_util_noti_post(const char *resource, const char *json_data)
90 {
91         int ret = 0;
92         CURL *curl = NULL;
93         CURLcode response = CURLE_OK;
94         struct curl_slist *headers = NULL;
95
96         retv_if(resource == NULL, -1);
97         retv_if(json_data == NULL, -1);
98
99         _I("server : %s", resource);
100         _I("json_data : %s", json_data);
101
102         curl = curl_easy_init();
103
104         if (!curl) {
105                 _E("fail to init curl");
106                 return -1;
107         }
108
109         headers = curl_slist_append(headers, "Accept: application/json");
110         headers = curl_slist_append(headers, "Content-Type: application/json");
111
112         curl_easy_setopt(curl, CURLOPT_URL, resource);
113         curl_easy_setopt(curl, CURLOPT_POST, 1L);
114         curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
115         curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json_data);
116         curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, _post_response_write_callback);
117         curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, REQ_CON_TIMEOUT);
118         curl_easy_setopt(curl, CURLOPT_TIMEOUT, REQ_TIMEOUT);
119
120         response = curl_easy_perform(curl);
121
122         if (response != CURLE_OK) {
123                 _E("curl_easy_perform() failed: %s",
124                         curl_easy_strerror(response));
125                 /* What should we do here, if response is kind of errors? */
126                 ret = -1;
127         }
128
129         curl_slist_free_all(headers);
130         curl_easy_cleanup(curl);
131
132         return ret;
133 }
134
135 int web_util_noti_get(const char *resource, char **res)
136 {
137         int ret = 0;
138         CURL *curl = NULL;
139         CURLcode response = CURLE_OK;
140
141         retv_if(resource == NULL, -1);
142
143         _I("GET to [%s]", resource);
144
145         curl = curl_easy_init();
146
147         if (!curl) {
148                 _E("fail to init curl");
149                 return -1;
150         }
151
152         curl_easy_setopt(curl, CURLOPT_URL, resource);
153         curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, _get_response_write_callback);
154         curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)res);
155         curl_easy_setopt(curl, CURLOPT_USERAGENT, "tizen-iot-agent/1.0");
156         curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, REQ_CON_TIMEOUT);
157
158         response = curl_easy_perform(curl);
159
160         if (response != CURLE_OK) {
161                 _E("curl_easy_perform() failed: %s",
162                 curl_easy_strerror(response));
163                 /* What should we do here, if response is kind of errors? */
164                 ret = -1;
165         }
166
167         curl_easy_cleanup(curl);
168
169         return ret;
170 }
171
172 int web_util_json_init(void)
173 {
174         if (Json_h.builder)
175                 g_object_unref(Json_h.builder);
176
177         Json_h.is_begin = false;
178         Json_h.is_end = false;
179         Json_h.builder = json_builder_new();
180         retv_if(Json_h.builder == NULL, -1);
181
182         return 0;
183 }
184
185 int web_util_json_fini(void)
186 {
187
188         if (Json_h.builder) {
189                 g_object_unref(Json_h.builder);
190                 Json_h.builder = NULL;
191         }
192
193         Json_h.is_begin = false;
194         Json_h.is_end = false;
195
196         return 0;
197 }
198
199 int web_util_json_begin(void)
200 {
201         retv_if(Json_h.builder == NULL, -1);
202         retv_if(Json_h.is_begin == true, -1);
203         retv_if(Json_h.is_end == true, -1);
204
205         Json_h.is_begin = true;
206
207         json_builder_begin_object(Json_h.builder);
208
209         return 0;
210 }
211
212 int web_util_json_end(void)
213 {
214         retv_if(Json_h.builder == NULL, -1);
215         retv_if(Json_h.is_begin == false, -1);
216         retv_if(Json_h.is_end == true, -1);
217
218         json_builder_end_object(Json_h.builder);
219         Json_h.is_end = true;
220
221         return 0;
222 }
223
224 int web_util_json_add_int(const char* key, long long int value)
225 {
226         retv_if(!key, -1);
227
228         if (Json_h.builder == NULL) {
229                 _E("Handle for json is not initialized, call web_util_json_init() first");
230                 return -1;
231         }
232
233         if (Json_h.is_begin == false) {
234                 _E("json object has not begun, call web_util_json_begin() first");
235                 return -1;
236         }
237
238         if (Json_h.is_end == true) {
239                 _E("json object has already ended, call web_util_json_begin() first");
240                 return -1;
241         }
242
243         json_builder_set_member_name(Json_h.builder, key);
244         json_builder_add_int_value(Json_h.builder, value);
245
246         return 0;
247 }
248
249 int web_util_json_add_double(const char* key, double value)
250 {
251         retv_if(!key, -1);
252
253         if (Json_h.builder == NULL) {
254                 _E("Handle for json is not initialized, call web_util_json_init() first");
255                 return -1;
256         }
257
258         if (Json_h.is_begin == false) {
259                 _E("json object has not begun, call web_util_json_begin() first");
260                 return -1;
261         }
262
263         if (Json_h.is_end == true) {
264                 _E("json object has already ended, call web_util_json_begin() first");
265                 return -1;
266         }
267
268         json_builder_set_member_name(Json_h.builder, key);
269         json_builder_add_double_value(Json_h.builder, value);
270
271         return 0;
272 }
273
274 int web_util_json_add_boolean(const char* key, bool value)
275 {
276         retv_if(!key, -1);
277
278         if (Json_h.builder == NULL) {
279                 _E("Handle for json is not initialized, call web_util_json_init() first");
280                 return -1;
281         }
282
283         if (Json_h.is_begin == false) {
284                 _E("json object has not begun, call web_util_json_begin() first");
285                 return -1;
286         }
287
288         if (Json_h.is_end == true) {
289                 _E("json object has already ended, call web_util_json_begin() first");
290                 return -1;
291         }
292
293         json_builder_set_member_name(Json_h.builder, key);
294         json_builder_add_boolean_value(Json_h.builder, value);
295
296         return 0;
297 }
298
299 int web_util_json_add_string(const char* key, const char *value)
300 {
301         retv_if(!key, -1);
302
303         if (Json_h.builder == NULL) {
304                 _E("Handle for json is not initialized, call web_util_json_init() first");
305                 return -1;
306         }
307
308         if (Json_h.is_begin == false) {
309                 _E("json object has not begun, call web_util_json_begin() first");
310                 return -1;
311         }
312
313         if (Json_h.is_end == true) {
314                 _E("json object has already ended, call web_util_json_begin() first");
315                 return -1;
316         }
317
318         json_builder_set_member_name(Json_h.builder, key);
319         json_builder_add_string_value(Json_h.builder, value);
320
321         return 0;
322 }
323
324 int web_util_json_data_array_begin(void)
325 {
326         int ret = 0;
327         retv_if(Json_h.builder == NULL, -1);
328
329         ret = web_util_json_begin();
330         retv_if(ret, -1);
331
332         json_builder_set_member_name(Json_h.builder, "SensorDataList");
333         json_builder_begin_array(Json_h.builder);
334
335         return 0;
336 }
337
338 int web_util_json_data_array_end(void)
339 {
340         retv_if(Json_h.builder == NULL, -1);
341         retv_if(Json_h.is_begin == false, -1);
342         retv_if(Json_h.is_end == true, -1);
343
344         json_builder_end_array(Json_h.builder);
345         web_util_json_end();
346
347         return 0;
348 }
349
350 int web_util_json_add_sensor_data(const char* sensorpi_id, web_util_sensor_data_s *sensor_data)
351 {
352         const char n_id[] = "SensorPiID";
353         const char n_motion[] = "Motion";
354         const char n_flame[] = "Flame";
355         const char n_hum[] = "Humidity";
356         const char n_temp[] = "Temperature";
357         const char n_vib[] = "Vibration";
358         const char n_co2[] = "CO2";
359         const char n_sound[] = "SoundLevel";
360         const char n_tilt[] = "Tilt";
361         const char n_light[] = "Light";
362         const char n_collision[] = "Collision";
363         const char n_obstacle[] = "Obstacle";
364         const char n_distance[] = "Distance";
365         const char n_rain[] = "Rain";
366         const char n_touch[] = "Touch";
367         const char n_gas[] = "Gas";
368         const char n_e_sensor[] = "SensorEnabled";
369         const char n_hash[] = "Hash";
370         const char n_ip[] = "SensorPiIP";
371
372         retv_if(!sensorpi_id, -1);
373         retv_if(Json_h.builder == NULL, -1);
374         retv_if(Json_h.is_begin == false, -1);
375         retv_if(Json_h.is_end == true, -1);
376         retv_if(sensor_data == NULL, -1);
377
378         /* JSON structure :
379         {
380                 SensorPiID: string,
381                 SensorPiIP: string,
382                 Motion: boolean,
383                 Flame: boolean,
384                 Humidity: double,
385                 Temperature: double,
386                 Vibration: boolean,
387                 CO2: double,
388                 SoundLevel: int,
389                 Tilt: int,
390                 Light: int,
391                 Collision: int,
392                 Obstacle: int,
393                 Distance: double,
394                 Rain: int,
395                 Touch: int,
396                 Gas: int,
397                 SensorEnabled: [Motion, ],
398                 Hash: string,
399         }
400         */
401
402
403         json_builder_begin_object(Json_h.builder);
404
405         json_builder_set_member_name(Json_h.builder, n_id);
406         json_builder_add_string_value(Json_h.builder, sensorpi_id);
407
408         if (sensor_data->ip_addr) {
409                 json_builder_set_member_name(Json_h.builder, n_ip);
410                 json_builder_add_string_value(Json_h.builder, sensor_data->ip_addr);
411         }
412
413         if (sensor_data->enabled_sensor & WEB_UTIL_SENSOR_MOTION) {
414                 json_builder_set_member_name(Json_h.builder, n_motion);
415                 json_builder_add_int_value(Json_h.builder, sensor_data->motion);
416         }
417
418         if (sensor_data->enabled_sensor & WEB_UTIL_SENSOR_FLAME) {
419                 json_builder_set_member_name(Json_h.builder, n_flame);
420                 json_builder_add_int_value(Json_h.builder, sensor_data->flame);
421         }
422
423         if (sensor_data->enabled_sensor & WEB_UTIL_SENSOR_HUMIDITY) {
424                 json_builder_set_member_name(Json_h.builder, n_hum);
425                 json_builder_add_double_value(Json_h.builder, sensor_data->humidity);
426         }
427
428         if (sensor_data->enabled_sensor & WEB_UTIL_SENSOR_TEMPERATURE) {
429                 json_builder_set_member_name(Json_h.builder, n_temp);
430                 json_builder_add_double_value(Json_h.builder, sensor_data->temperature);
431         }
432
433         if (sensor_data->enabled_sensor & WEB_UTIL_SENSOR_VIB) {
434                 json_builder_set_member_name(Json_h.builder, n_vib);
435                 json_builder_add_int_value(Json_h.builder, sensor_data->virbration);
436         }
437
438         if (sensor_data->enabled_sensor & WEB_UTIL_SENSOR_CO2) {
439                 json_builder_set_member_name(Json_h.builder, n_co2);
440                 json_builder_add_double_value(Json_h.builder, sensor_data->co2);
441         }
442
443         if (sensor_data->enabled_sensor & WEB_UTIL_SENSOR_SOUND) {
444                 json_builder_set_member_name(Json_h.builder, n_sound);
445                 json_builder_add_int_value(Json_h.builder, sensor_data->soundlevel);
446         }
447
448         if (sensor_data->enabled_sensor & WEB_UTIL_SENSOR_TILT) {
449                 json_builder_set_member_name(Json_h.builder, n_tilt);
450                 json_builder_add_int_value(Json_h.builder, sensor_data->tilt);
451         }
452
453         if (sensor_data->enabled_sensor & WEB_UTIL_SENSOR_LIGHT) {
454                 json_builder_set_member_name(Json_h.builder, n_light);
455                 json_builder_add_int_value(Json_h.builder, sensor_data->light);
456         }
457
458         if (sensor_data->enabled_sensor & WEB_UTIL_SENSOR_COLLISION) {
459                 json_builder_set_member_name(Json_h.builder, n_collision);
460                 json_builder_add_int_value(Json_h.builder, sensor_data->collision);
461         }
462
463         if (sensor_data->enabled_sensor & WEB_UTIL_SENSOR_OBSTACLE) {
464                 json_builder_set_member_name(Json_h.builder, n_obstacle);
465                 json_builder_add_int_value(Json_h.builder, sensor_data->obstacle);
466         }
467
468         if (sensor_data->enabled_sensor & WEB_UTIL_SENSOR_ULTRASONIC_DISTANCE) {
469                 json_builder_set_member_name(Json_h.builder, n_distance);
470                 json_builder_add_double_value(Json_h.builder, sensor_data->distance);
471         }
472
473         if (sensor_data->enabled_sensor & WEB_UTIL_SENSOR_RAIN) {
474                 json_builder_set_member_name(Json_h.builder, n_rain);
475                 json_builder_add_int_value(Json_h.builder, sensor_data->rain);
476         }
477
478         if (sensor_data->enabled_sensor & WEB_UTIL_SENSOR_TOUCH) {
479                 json_builder_set_member_name(Json_h.builder, n_touch);
480                 json_builder_add_int_value(Json_h.builder, sensor_data->touch);
481         }
482
483         if (sensor_data->enabled_sensor & WEB_UTIL_SENSOR_GAS) {
484                 json_builder_set_member_name(Json_h.builder, n_gas);
485                 json_builder_add_int_value(Json_h.builder, sensor_data->gas);
486         }
487
488         json_builder_set_member_name(Json_h.builder, n_e_sensor);
489         json_builder_begin_array(Json_h.builder);
490
491         if (sensor_data->enabled_sensor & WEB_UTIL_SENSOR_MOTION)
492                 json_builder_add_string_value(Json_h.builder, n_motion);
493
494         if (sensor_data->enabled_sensor & WEB_UTIL_SENSOR_FLAME)
495                 json_builder_add_string_value(Json_h.builder, n_flame);
496
497         if (sensor_data->enabled_sensor & WEB_UTIL_SENSOR_HUMIDITY)
498                 json_builder_add_string_value(Json_h.builder, n_hum);
499
500         if (sensor_data->enabled_sensor & WEB_UTIL_SENSOR_TEMPERATURE)
501                 json_builder_add_string_value(Json_h.builder, n_temp);
502
503         if (sensor_data->enabled_sensor & WEB_UTIL_SENSOR_VIB)
504                 json_builder_add_string_value(Json_h.builder, n_vib);
505
506         if (sensor_data->enabled_sensor & WEB_UTIL_SENSOR_CO2)
507                 json_builder_add_string_value(Json_h.builder, n_co2);
508
509         if (sensor_data->enabled_sensor & WEB_UTIL_SENSOR_SOUND)
510                 json_builder_add_string_value(Json_h.builder, n_sound);
511
512         if (sensor_data->enabled_sensor & WEB_UTIL_SENSOR_TILT)
513                 json_builder_add_string_value(Json_h.builder, n_tilt);
514
515         if (sensor_data->enabled_sensor & WEB_UTIL_SENSOR_LIGHT)
516                 json_builder_add_string_value(Json_h.builder, n_light);
517
518         if (sensor_data->enabled_sensor & WEB_UTIL_SENSOR_COLLISION)
519                 json_builder_add_string_value(Json_h.builder, n_collision);
520
521         if (sensor_data->enabled_sensor & WEB_UTIL_SENSOR_OBSTACLE)
522                 json_builder_add_string_value(Json_h.builder, n_obstacle);
523
524         if (sensor_data->enabled_sensor & WEB_UTIL_SENSOR_ULTRASONIC_DISTANCE)
525                 json_builder_add_string_value(Json_h.builder, n_distance);
526
527         if (sensor_data->enabled_sensor & WEB_UTIL_SENSOR_RAIN)
528                 json_builder_add_string_value(Json_h.builder, n_rain);
529
530         if (sensor_data->enabled_sensor & WEB_UTIL_SENSOR_TOUCH)
531                 json_builder_add_string_value(Json_h.builder, n_touch);
532
533         if (sensor_data->enabled_sensor & WEB_UTIL_SENSOR_GAS)
534                 json_builder_add_string_value(Json_h.builder, n_gas);
535
536         json_builder_end_array(Json_h.builder);
537
538         if (sensor_data->hash) {
539                 json_builder_set_member_name(Json_h.builder, n_hash);
540                 json_builder_add_string_value(Json_h.builder, sensor_data->hash);
541         }
542
543         json_builder_end_object(Json_h.builder);
544
545         return 0;
546 }
547
548 char *web_util_get_json_string(void)
549 {
550         JsonGenerator *gen = NULL;
551         JsonNode *root = NULL;
552         char *str = NULL;
553
554         retv_if(Json_h.builder == NULL, NULL);
555         retv_if(Json_h.is_begin == false, NULL);
556         retv_if(Json_h.is_end == false, NULL);
557
558         root = json_builder_get_root(Json_h.builder);
559         retv_if(root == NULL, NULL);
560
561         gen = json_generator_new();
562         goto_if(gen == NULL, error_release_all);
563         json_generator_set_root(gen, root);
564
565         str = json_generator_to_data(gen, NULL);
566
567         return str;
568
569 error_release_all:
570         if (root)
571                 json_node_free(root);
572
573         return NULL;
574 }
575