a9c695b4f93d2e360c6728133685f6470dad15a0
[apps/native/position-finder-server.git] / src / connectivity.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  *
9  * Licensed under the Flora License, Version 1.1 (the License);
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://floralicense.org/license/
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an AS IS BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  */
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <stdbool.h>
25 #include <glib.h>
26 #include <app_common.h>
27 #include <iotcon.h>
28
29 #include "log.h"
30 #include "connectivity.h"
31 #include "webutil.h"
32 #include "controller_util.h"
33
34 #define DEFAULT_RESOURCE_TYPE "org.tizen.door"
35 #define BUFSIZE 1024
36 #define URI_PATH_LEN 64
37 #define URI_PATH "/door/1"
38 #define PATH "path"
39 #define IOTCON_DB_FILENAME "iotcon-test-svr-db-server.dat"
40
41 struct _connectivity_resource {
42         char *path;
43         char *type;
44         connectivity_protocol_e protocol_type;
45         GHashTable *value_hash;
46         union {
47                 struct {
48                         iotcon_resource_h res;
49                         iotcon_observers_h observers;
50                 } iotcon_data;
51                 struct {
52                         /* Nothing */
53                         char *reserve;
54                 } http_data;
55         } conn_data;
56 };
57
58 typedef enum {
59         DATA_VAL_TYPE_BOOL = 0,
60         DATA_VAL_TYPE_INT,
61         DATA_VAL_TYPE_DOUBLE,
62         DATA_VAL_TYPE_STRING
63 } conn_data_val_type_e;
64
65 typedef struct _conn_data_value_s {
66         conn_data_val_type_e type;
67         union {
68                 bool b_val;
69                 int i_val;
70                 double d_val;
71                 char *s_val;
72         };
73 } conn_data_value_s;
74
75 static connectivity_protocol_e ProtocolType = CONNECTIVITY_PROTOCOL_DEFAULT;
76 static int connectivity_iotcon_intialized = 0;
77 static int connectivity_http_intialized = 0;
78
79 static void _print_iotcon_error(int err_no)
80 {
81         switch (err_no) {
82         case IOTCON_ERROR_NOT_SUPPORTED:
83                 _E("IOTCON_ERROR_NOT_SUPPORTED");
84                 break;
85         case IOTCON_ERROR_PERMISSION_DENIED:
86                 _E("IOTCON_ERROR_PERMISSION_DENIED");
87                 break;
88         case IOTCON_ERROR_INVALID_PARAMETER:
89                 _E("IOTCON_ERROR_INVALID_PARAMETER");
90                 break;
91         default:
92                 _E("Error : [%d]", err_no);
93                 break;
94         }
95
96         return;
97 }
98
99 static void _copy_file(const char *in_filename, const char *out_filename)
100 {
101         char buf[BUFSIZE] = { 0, };
102         size_t nread = 0;
103         FILE *in = NULL;
104         FILE *out = NULL;
105
106         ret_if(!in_filename);
107         ret_if(!out_filename);
108
109         in = fopen(in_filename, "r");
110         ret_if(!in);
111
112         out = fopen(out_filename, "w");
113         goto_if(!out, error);
114
115         rewind(in);
116         while ((nread = fread(buf, 1, sizeof(buf), in)) > 0) {
117                 if (fwrite(buf, 1, nread, out) < nread) {
118                         _E("critical error to copy a file");
119                         break;
120                 }
121         }
122
123         fclose(in);
124         fclose(out);
125
126         return;
127
128 error:
129         fclose(out);
130         return;
131 }
132
133 static bool _query_cb(const char *key, const char *value, void *user_data)
134 {
135         _D("Key : [%s], Value : [%s]", key, value);
136
137         return IOTCON_FUNC_CONTINUE;
138 }
139
140 static int _handle_query(iotcon_request_h request)
141 {
142         iotcon_query_h query = NULL;
143         int ret = -1;
144
145         ret = iotcon_request_get_query(request, &query);
146         retv_if(IOTCON_ERROR_NONE != ret, -1);
147
148         if (query) iotcon_query_foreach(query, _query_cb, NULL);
149
150         return 0;
151 }
152
153 static int _handle_request_by_crud_type(iotcon_request_h request, connectivity_resource_s *resource_info)
154 {
155         iotcon_request_type_e type;
156         int ret = -1;
157
158         ret = iotcon_request_get_request_type(request, &type);
159         retv_if(IOTCON_ERROR_NONE != ret, -1);
160
161         switch (type) {
162         case IOTCON_REQUEST_GET:
163                 _I("Do not support 'get' query");
164                 break;
165         case IOTCON_REQUEST_PUT:
166                 _I("Do not support 'put' query");
167                 break;
168         case IOTCON_REQUEST_POST:
169                 _I("Do not support 'post' query");
170                 break;
171         case IOTCON_REQUEST_DELETE:
172                 _I("Do not support 'delete' query");
173                 break;
174         default:
175                 _E("Cannot reach here");
176                 ret = -1;
177                 break;
178         }
179         retv_if(0 != ret, -1);
180
181         return 0;
182 }
183
184 static int _handle_observer(iotcon_request_h request, iotcon_observers_h observers)
185 {
186         iotcon_observe_type_e observe_type;
187         int ret = -1;
188         int observe_id = -1;
189
190         ret = iotcon_request_get_observe_type(request, &observe_type);
191         retv_if(IOTCON_ERROR_NONE != ret, -1);
192
193         if (IOTCON_OBSERVE_REGISTER == observe_type) {
194                 ret = iotcon_request_get_observe_id(request, &observe_id);
195                 retv_if(IOTCON_ERROR_NONE != ret, -1);
196
197                 _I("Add an observer : %d", observe_id);
198
199                 ret = iotcon_observers_add(observers, observe_id);
200                 retv_if(IOTCON_ERROR_NONE != ret, -1);
201         } else if (IOTCON_OBSERVE_DEREGISTER == observe_type) {
202                 ret = iotcon_request_get_observe_id(request, &observe_id);
203                 retv_if(IOTCON_ERROR_NONE != ret, -1);
204
205                 _I("Remove an observer : %d", observe_id);
206
207                 ret = iotcon_observers_remove(observers, observe_id);
208                 retv_if(IOTCON_ERROR_NONE != ret, -1);
209         }
210
211         return 0;
212 }
213
214 static int _send_response(iotcon_request_h request, iotcon_representation_h representation, iotcon_response_result_e result)
215 {
216         int ret = -1;
217         iotcon_response_h response;
218
219         ret = iotcon_response_create(request, &response);
220         retv_if(IOTCON_ERROR_NONE != ret, -1);
221
222         ret = iotcon_response_set_result(response, result);
223         goto_if(IOTCON_ERROR_NONE != ret, error);
224
225         ret = iotcon_response_set_representation(response, representation);
226         goto_if(IOTCON_ERROR_NONE != ret, error);
227
228         ret = iotcon_response_send(response);
229         goto_if(IOTCON_ERROR_NONE != ret, error);
230
231         iotcon_response_destroy(response);
232
233         return 0;
234
235 error:
236         iotcon_response_destroy(response);
237         return -1;
238 }
239
240 static void _request_resource_handler(iotcon_resource_h resource, iotcon_request_h request, void *user_data)
241 {
242         connectivity_resource_s *resource_info = user_data;
243         int ret = -1;
244         char *host_address = NULL;
245
246         ret_if(!request);
247
248         ret = iotcon_request_get_host_address(request, &host_address);
249         goto_if(IOTCON_ERROR_NONE != ret, error);
250
251         _D("Host address : %s", host_address);
252
253         ret = _handle_query(request);
254         goto_if(IOTCON_ERROR_NONE != ret, error);
255
256         ret = _handle_request_by_crud_type(request, resource_info);
257         goto_if(0 != ret, error);
258
259         ret = _handle_observer(request, resource_info->conn_data.iotcon_data.observers);
260         goto_if(0 != ret, error);
261
262         return;
263
264 error:
265         _send_response(request, NULL, IOTCON_RESPONSE_ERROR);
266         return;
267 }
268
269 static int __init_iotcon(connectivity_resource_s *resource_info)
270 {
271         int ret = -1;
272         iotcon_resource_types_h resource_types = NULL;
273         iotcon_resource_interfaces_h ifaces = NULL;
274         uint8_t policies = IOTCON_RESOURCE_NO_POLICY;
275         char res_path[PATH_MAX] = {0,};
276         char data_path[PATH_MAX] = {0,};
277         char *prefix = NULL;
278
279         retv_if(!resource_info, -1);
280         retv_if(resource_info->protocol_type != CONNECTIVITY_PROTOCOL_IOTIVITY, -1);
281
282         prefix = app_get_resource_path();
283         retv_if(!prefix, -1);
284         snprintf(res_path, sizeof(res_path)-1, "%s%s", prefix, IOTCON_DB_FILENAME);
285         free(prefix);
286         prefix = NULL;
287
288         prefix = app_get_data_path();
289         retv_if(!prefix, -1);
290         snprintf(data_path, sizeof(data_path)-1, "%s%s", prefix, IOTCON_DB_FILENAME);
291         free(prefix);
292
293         _copy_file(res_path, data_path);
294
295         ret = iotcon_initialize(data_path);
296         retv_if(IOTCON_ERROR_NONE != ret, -1);
297
298         /* TODO : If we have to set device name, naming it more gorgeous one */
299         ret = iotcon_set_device_name(DEFAULT_RESOURCE_TYPE);
300         goto_if(IOTCON_ERROR_NONE != ret, error);
301
302         ret = iotcon_resource_types_create(&resource_types);
303         goto_if(IOTCON_ERROR_NONE != ret, error);
304
305         ret = iotcon_resource_types_add(resource_types, resource_info->type);
306         goto_if(IOTCON_ERROR_NONE != ret, error);
307
308         ret = iotcon_resource_interfaces_create(&ifaces);
309         goto_if(IOTCON_ERROR_NONE != ret, error);
310
311         ret = iotcon_resource_interfaces_add(ifaces, IOTCON_INTERFACE_DEFAULT);
312         goto_if(IOTCON_ERROR_NONE != ret, error);
313
314         ret = iotcon_resource_interfaces_add(ifaces, IOTCON_INTERFACE_BATCH);
315         goto_if(IOTCON_ERROR_NONE != ret, error);
316
317         policies =
318                 IOTCON_RESOURCE_DISCOVERABLE |
319                 IOTCON_RESOURCE_OBSERVABLE |
320                 IOTCON_RESOURCE_SECURE;
321
322         ret = iotcon_resource_create(URI_PATH,
323                         resource_types,
324                         ifaces,
325                         policies,
326                         _request_resource_handler,
327                         resource_info,
328                         &resource_info->conn_data.iotcon_data.res);
329         goto_if(IOTCON_ERROR_NONE != ret, error);
330
331         ret = iotcon_observers_create(&resource_info->conn_data.iotcon_data.observers);
332         goto_if(IOTCON_ERROR_NONE != ret, error);
333
334         iotcon_resource_types_destroy(resource_types);
335         iotcon_resource_interfaces_destroy(ifaces);
336         connectivity_iotcon_intialized = 1;
337
338         return 0;
339
340 error:
341         if (resource_types) iotcon_resource_types_destroy(resource_types);
342         if (ifaces) iotcon_resource_interfaces_destroy(ifaces);
343         if (resource_info->conn_data.iotcon_data.res) iotcon_resource_destroy(resource_info->conn_data.iotcon_data.res);
344         iotcon_deinitialize();
345         return -1;
346 }
347
348 static int __init_http(connectivity_resource_s *resource_info)
349 {
350         int ret = 0;
351         ret = web_util_noti_init();
352         if (!ret)
353                 connectivity_http_intialized = 1;
354
355         return ret;
356 }
357
358 #ifdef PRINT_DEBUG_DETAIL
359 static bool __print_attributes_cb(iotcon_attributes_h attributes, const char *key, void *user_data)
360 {
361         iotcon_type_e type = IOTCON_TYPE_NONE;
362
363         iotcon_attributes_get_type(attributes, key, &type);
364
365         switch (type) {
366         case IOTCON_TYPE_INT: {
367                 int value = 0;
368                 iotcon_attributes_get_int(attributes, key, &value);
369                 _D("key[%s] - int value [%d]", key, value);
370                 }
371                 break;
372         case IOTCON_TYPE_BOOL: {
373                 bool value = 0;
374                 iotcon_attributes_get_bool(attributes, key, &value);
375                 _D("key[%s] - bool value [%d]", key, value);
376                 }
377                 break;
378         case IOTCON_TYPE_DOUBLE: {
379                 double value = 0;
380                 iotcon_attributes_get_double(attributes, key, &value);
381                 _D("key[%s] - double value [%lf]", key, value);
382                 }
383         break;
384         case IOTCON_TYPE_STR: {
385                 char *value = 0;
386                 iotcon_attributes_get_str(attributes, key, &value);
387                 _D("key[%s] - string value [%s]", key, value);
388                 }
389         break;
390         case IOTCON_TYPE_NONE:
391         case IOTCON_TYPE_BYTE_STR:
392         case IOTCON_TYPE_NULL:
393         case IOTCON_TYPE_LIST:
394         case IOTCON_TYPE_ATTRIBUTES:
395         default:
396                 _W("unhandled key[%s] type[%d]", key, type);
397                 break;
398         }
399
400         return IOTCON_FUNC_CONTINUE;
401 }
402 #endif
403
404 static void __print_attribute(iotcon_attributes_h attributes)
405 {
406 #ifdef PRINT_DEBUG_DETAIL
407         ret_if(!attributes);
408
409         iotcon_attributes_foreach(attributes, __print_attributes_cb, NULL);
410 #endif
411         return;
412 }
413
414 static void _destroy_representation(iotcon_representation_h representation)
415 {
416         ret_if(!representation);
417         iotcon_representation_destroy(representation);
418         return;
419 }
420
421 static iotcon_representation_h _create_representation_with_bool(connectivity_resource_s *resource_info, const char *key, bool value)
422 {
423         iotcon_attributes_h attributes = NULL;
424         iotcon_representation_h representation = NULL;
425         char *uri_path = NULL;
426         int ret = -1;
427
428         ret = iotcon_resource_get_uri_path(resource_info->conn_data.iotcon_data.res, &uri_path);
429         retv_if(IOTCON_ERROR_NONE != ret, NULL);
430
431         ret = iotcon_representation_create(&representation);
432         retv_if(IOTCON_ERROR_NONE != ret, NULL);
433
434         ret = iotcon_attributes_create(&attributes);
435         goto_if(IOTCON_ERROR_NONE != ret, error);
436
437         ret = iotcon_representation_set_uri_path(representation, uri_path);
438         goto_if(IOTCON_ERROR_NONE != ret, error);
439
440         ret = iotcon_attributes_add_str(attributes, PATH, resource_info->path);
441         goto_if(IOTCON_ERROR_NONE != ret, error);
442
443         ret = iotcon_attributes_add_bool(attributes, key, value);
444         goto_if(IOTCON_ERROR_NONE != ret, error);
445
446         ret = iotcon_representation_set_attributes(representation, attributes);
447         goto_if(IOTCON_ERROR_NONE != ret, error);
448
449         iotcon_attributes_destroy(attributes);
450
451         return representation;
452
453 error:
454         if (attributes) iotcon_attributes_destroy(attributes);
455         if (representation) iotcon_representation_destroy(representation);
456
457         return NULL;
458 }
459
460 static iotcon_representation_h _create_representation_with_int(connectivity_resource_s *resource_info, const char *key, int value)
461 {
462         iotcon_attributes_h attributes = NULL;
463         iotcon_representation_h representation = NULL;
464         char *uri_path = NULL;
465         int ret = -1;
466
467         ret = iotcon_resource_get_uri_path(resource_info->conn_data.iotcon_data.res, &uri_path);
468         retv_if(IOTCON_ERROR_NONE != ret, NULL);
469
470         ret = iotcon_representation_create(&representation);
471         retv_if(IOTCON_ERROR_NONE != ret, NULL);
472
473         ret = iotcon_attributes_create(&attributes);
474         goto_if(IOTCON_ERROR_NONE != ret, error);
475
476         ret = iotcon_representation_set_uri_path(representation, uri_path);
477         goto_if(IOTCON_ERROR_NONE != ret, error);
478
479         ret = iotcon_attributes_add_str(attributes, PATH, resource_info->path);
480         goto_if(IOTCON_ERROR_NONE != ret, error);
481
482         ret = iotcon_attributes_add_int(attributes, key, value);
483         goto_if(IOTCON_ERROR_NONE != ret, error);
484
485         ret = iotcon_representation_set_attributes(representation, attributes);
486         goto_if(IOTCON_ERROR_NONE != ret, error);
487
488         iotcon_attributes_destroy(attributes);
489
490         return representation;
491
492 error:
493         if (attributes) iotcon_attributes_destroy(attributes);
494         if (representation) iotcon_representation_destroy(representation);
495
496         return NULL;
497 }
498
499 static iotcon_representation_h _create_representation_with_double(connectivity_resource_s *resource_info, const char *key, double value)
500 {
501         iotcon_attributes_h attributes = NULL;
502         iotcon_representation_h representation = NULL;
503         char *uri_path = NULL;
504         int ret = -1;
505
506         ret = iotcon_resource_get_uri_path(resource_info->conn_data.iotcon_data.res, &uri_path);
507         retv_if(IOTCON_ERROR_NONE != ret, NULL);
508
509         ret = iotcon_representation_create(&representation);
510         retv_if(IOTCON_ERROR_NONE != ret, NULL);
511
512         ret = iotcon_attributes_create(&attributes);
513         goto_if(IOTCON_ERROR_NONE != ret, error);
514
515         ret = iotcon_representation_set_uri_path(representation, uri_path);
516         goto_if(IOTCON_ERROR_NONE != ret, error);
517
518         ret = iotcon_attributes_add_str(attributes, PATH, resource_info->path);
519         goto_if(IOTCON_ERROR_NONE != ret, error);
520
521         ret = iotcon_attributes_add_double(attributes, key, value);
522         goto_if(IOTCON_ERROR_NONE != ret, error);
523
524         ret = iotcon_representation_set_attributes(representation, attributes);
525         goto_if(IOTCON_ERROR_NONE != ret, error);
526
527         iotcon_attributes_destroy(attributes);
528
529         return representation;
530
531 error:
532         if (attributes) iotcon_attributes_destroy(attributes);
533         if (representation) iotcon_representation_destroy(representation);
534
535         return NULL;
536 }
537
538 static iotcon_representation_h _create_representation_with_string(connectivity_resource_s *resource_info, const char *key, const char *value)
539 {
540         iotcon_attributes_h attributes = NULL;
541         iotcon_representation_h representation = NULL;
542         char *uri_path = NULL;
543         int ret = -1;
544
545         ret = iotcon_resource_get_uri_path(resource_info->conn_data.iotcon_data.res, &uri_path);
546         retv_if(IOTCON_ERROR_NONE != ret, NULL);
547
548         ret = iotcon_representation_create(&representation);
549         retv_if(IOTCON_ERROR_NONE != ret, NULL);
550
551         ret = iotcon_attributes_create(&attributes);
552         goto_if(IOTCON_ERROR_NONE != ret, error);
553
554         ret = iotcon_representation_set_uri_path(representation, uri_path);
555         goto_if(IOTCON_ERROR_NONE != ret, error);
556
557         ret = iotcon_attributes_add_str(attributes, PATH, resource_info->path);
558         goto_if(IOTCON_ERROR_NONE != ret, error);
559
560         ret = iotcon_attributes_add_str(attributes, key, (char *)value);
561         goto_if(IOTCON_ERROR_NONE != ret, error);
562
563         ret = iotcon_representation_set_attributes(representation, attributes);
564         goto_if(IOTCON_ERROR_NONE != ret, error);
565
566         iotcon_attributes_destroy(attributes);
567
568         return representation;
569
570 error:
571         if (attributes) iotcon_attributes_destroy(attributes);
572         if (representation) iotcon_representation_destroy(representation);
573
574         return NULL;
575 }
576
577 static inline void __noti_by_http(void)
578 {
579         char *json_data = NULL;
580
581         json_data = web_util_get_json_string();
582         if (json_data) {
583                 const char *url = NULL;
584                 controller_util_get_address(&url);
585                 if (url)
586                         web_util_noti_post(url, json_data);
587                 else
588                         _E("fail to get url");
589                 free(json_data);
590         } else
591                 _E("fail to get json_data");
592
593         return;
594 }
595
596 int connectivity_notify_bool(connectivity_resource_s *resource_info, const char *key, bool value)
597 {
598         int ret = -1;
599
600         retv_if(!resource_info, -1);
601         retv_if(!key, -1);
602
603         _D("Notify key[%s], value[%d]", key, value);
604
605         switch (resource_info->protocol_type) {
606         case CONNECTIVITY_PROTOCOL_IOTIVITY:
607                 retv_if(!resource_info->conn_data.iotcon_data.res, -1);
608                 retv_if(!resource_info->conn_data.iotcon_data.observers, -1);
609                 {
610                         iotcon_representation_h representation;
611                         representation = _create_representation_with_bool(resource_info, key, value);
612                         retv_if(!representation, -1);
613                         ret = iotcon_resource_notify(resource_info->conn_data.iotcon_data.res,
614                                         representation, resource_info->conn_data.iotcon_data.observers, IOTCON_QOS_LOW);
615                         if (IOTCON_ERROR_NONE != ret) {
616                                 _W("There are some troubles for notifying value[%d]", ret);
617                                 _print_iotcon_error(ret);
618                                 return -1;
619                         }
620                         _destroy_representation(representation);
621                 }
622                 break;
623         case CONNECTIVITY_PROTOCOL_HTTP:
624                 ret = web_util_json_init();
625                 retv_if(ret, -1);
626
627                 ret = web_util_json_begin();
628                 retv_if(ret, -1);
629
630                 web_util_json_add_string("SensorPiID", resource_info->path);
631                 web_util_json_add_string("SensorPiType", resource_info->type);
632                 web_util_json_add_boolean(key, value);
633                 web_util_json_end();
634
635                 __noti_by_http();
636
637                 web_util_json_fini();
638                 break;
639         default:
640                 _E("Unknown protocol type[%d]", resource_info->protocol_type);
641                 return -1;
642                 break;
643         }
644
645         return 0;
646 }
647
648 int connectivity_notify_int(connectivity_resource_s *resource_info, const char *key, int value)
649 {
650         int ret = -1;
651
652         retv_if(!resource_info, -1);
653         retv_if(!key, -1);
654
655         _D("Notify key[%s], value[%d]", key, value);
656
657         switch (resource_info->protocol_type) {
658         case CONNECTIVITY_PROTOCOL_IOTIVITY:
659                 retv_if(!resource_info->conn_data.iotcon_data.res, -1);
660                 retv_if(!resource_info->conn_data.iotcon_data.observers, -1);
661                 {
662                         iotcon_representation_h representation;
663                         representation = _create_representation_with_int(resource_info, key, value);
664                         retv_if(!representation, -1);
665                         ret = iotcon_resource_notify(resource_info->conn_data.iotcon_data.res,
666                                         representation, resource_info->conn_data.iotcon_data.observers, IOTCON_QOS_LOW);
667                         if (IOTCON_ERROR_NONE != ret) {
668                                 _W("There are some troubles for notifying value[%d]", ret);
669                                 _print_iotcon_error(ret);
670                                 return -1;
671                         }
672                         _destroy_representation(representation);
673                 }
674                 break;
675         case CONNECTIVITY_PROTOCOL_HTTP:
676                 ret = web_util_json_init();
677                 retv_if(ret, -1);
678
679                 ret = web_util_json_begin();
680                 retv_if(ret, -1);
681
682                 web_util_json_add_string("SensorPiID", resource_info->path);
683                 web_util_json_add_string("SensorPiType", resource_info->type);
684                 web_util_json_add_int(key, value);
685                 web_util_json_end();
686
687                 __noti_by_http();
688
689                 web_util_json_fini();
690                 break;
691         default:
692                 _E("Unknown protocol type[%d]", resource_info->protocol_type);
693                 return -1;
694                 break;
695         }
696         return 0;
697 }
698
699 int connectivity_notify_double(connectivity_resource_s *resource_info, const char *key, double value)
700 {
701         int ret = -1;
702
703         retv_if(!resource_info, -1);
704         retv_if(!key, -1);
705
706         _D("Notify key[%s], value[%lf]", key, value);
707
708         switch (resource_info->protocol_type) {
709         case CONNECTIVITY_PROTOCOL_IOTIVITY:
710                 retv_if(!resource_info->conn_data.iotcon_data.res, -1);
711                 retv_if(!resource_info->conn_data.iotcon_data.observers, -1);
712                 {
713                         iotcon_representation_h representation;
714                         representation = _create_representation_with_double(resource_info, key, value);
715                         retv_if(!representation, -1);
716                         ret = iotcon_resource_notify(resource_info->conn_data.iotcon_data.res,
717                                         representation, resource_info->conn_data.iotcon_data.observers, IOTCON_QOS_LOW);
718                         if (IOTCON_ERROR_NONE != ret) {
719                                 _W("There are some troubles for notifying value[%d]", ret);
720                                 _print_iotcon_error(ret);
721                                 return -1;
722                         }
723                         _destroy_representation(representation);
724                 }
725                 break;
726         case CONNECTIVITY_PROTOCOL_HTTP:
727                 ret = web_util_json_init();
728                 retv_if(ret, -1);
729
730                 ret = web_util_json_begin();
731                 retv_if(ret, -1);
732
733                 web_util_json_add_string("SensorPiID", resource_info->path);
734                 web_util_json_add_string("SensorPiType", resource_info->type);
735                 web_util_json_add_double(key, value);
736                 web_util_json_end();
737
738                 __noti_by_http();
739
740                 web_util_json_fini();
741                 break;
742         default:
743                 _E("Unknown protocol type[%d]", resource_info->protocol_type);
744                 return -1;
745                 break;
746         }
747         return 0;
748 }
749
750 int connectivity_notify_string(connectivity_resource_s *resource_info, const char *key, const char *value)
751 {
752         int ret = -1;
753
754         retv_if(!resource_info, -1);
755         retv_if(!key, -1);
756         retv_if(!value, -1);
757
758         _D("Notify key[%s], value[%s]", key, value);
759
760         switch (resource_info->protocol_type) {
761         case CONNECTIVITY_PROTOCOL_IOTIVITY:
762                 retv_if(!resource_info->conn_data.iotcon_data.res, -1);
763                 retv_if(!resource_info->conn_data.iotcon_data.observers, -1);
764                 {
765                         iotcon_representation_h representation;
766                         representation = _create_representation_with_string(resource_info, key, value);
767                         retv_if(!representation, -1);
768                         ret = iotcon_resource_notify(resource_info->conn_data.iotcon_data.res,
769                                         representation, resource_info->conn_data.iotcon_data.observers, IOTCON_QOS_LOW);
770                         if (IOTCON_ERROR_NONE != ret) {
771                                 _W("There are some troubles for notifying value[%d]", ret);
772                                 _print_iotcon_error(ret);
773                                 return -1;
774                         }
775                         _destroy_representation(representation);
776                 }
777                 break;
778         case CONNECTIVITY_PROTOCOL_HTTP:
779                 ret = web_util_json_init();
780                 retv_if(ret, -1);
781
782                 ret = web_util_json_begin();
783                 retv_if(ret, -1);
784
785                 web_util_json_add_string("SensorPiID", resource_info->path);
786                 web_util_json_add_string("SensorPiType", resource_info->type);
787                 web_util_json_add_string(key, value);
788                 web_util_json_end();
789
790                 __noti_by_http();
791
792                 web_util_json_fini();
793                 break;
794         default:
795                 _E("Unknown protocol type[%d]", resource_info->protocol_type);
796                 return -1;
797                 break;
798         }
799         return 0;
800 }
801
802 static void __hash_key_free(gpointer data)
803 {
804         free(data);
805         return;
806 }
807
808 static void __hash_value_free(gpointer data)
809 {
810         conn_data_value_s *value = data;
811         if (value && (value->type == DATA_VAL_TYPE_STRING))
812                 free(value->s_val);
813         free(value);
814
815         return;
816 }
817
818 static int __add_value_to_hash(connectivity_resource_s *resource_info, const char *key, conn_data_value_s *value)
819 {
820         retv_if(!resource_info, -1);
821         retv_if(!key, -1);
822         retv_if(!value, -1);
823
824         if (!resource_info->value_hash) {
825                 resource_info->value_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
826                                                                                 __hash_key_free, __hash_value_free);
827                 retv_if(!resource_info->value_hash, -1);
828         }
829
830         g_hash_table_insert(resource_info->value_hash, strdup(key), value);
831
832         return 0;
833 }
834
835 int connectivity_attributes_add_bool(connectivity_resource_s *resource_info, const char *key, bool value)
836 {
837         conn_data_value_s *data_value = NULL;
838
839         retv_if(!resource_info, -1);
840         retv_if(!key, -1);
841
842         _D("adding key[%s] - value[%d]", key, value);
843
844         data_value = malloc(sizeof(conn_data_value_s));
845         retv_if(!data_value, -1);
846
847         data_value->type = DATA_VAL_TYPE_BOOL;
848         data_value->b_val = value;
849
850         return __add_value_to_hash(resource_info, key, data_value);
851 }
852
853 int connectivity_attributes_add_int(connectivity_resource_s *resource_info, const char *key, int value)
854 {
855         conn_data_value_s *data_value = NULL;
856
857         retv_if(!resource_info, -1);
858         retv_if(!key, -1);
859
860         _D("adding key[%s] - value[%d]", key, value);
861
862         data_value = malloc(sizeof(conn_data_value_s));
863         retv_if(!data_value, -1);
864
865         data_value->type = DATA_VAL_TYPE_INT;
866         data_value->i_val = value;
867
868         return __add_value_to_hash(resource_info, key, data_value);
869 }
870
871 int connectivity_attributes_add_double(connectivity_resource_s *resource_info, const char *key, double value)
872 {
873         conn_data_value_s *data_value = NULL;
874
875         retv_if(!resource_info, -1);
876         retv_if(!key, -1);
877
878         _D("adding key[%s] - value[%lf]", key, value);
879
880         data_value = malloc(sizeof(conn_data_value_s));
881         retv_if(!data_value, -1);
882
883         data_value->type = DATA_VAL_TYPE_DOUBLE;
884         data_value->d_val = value;
885
886         return __add_value_to_hash(resource_info, key, data_value);
887 }
888
889 int connectivity_attributes_add_string(connectivity_resource_s *resource_info, const char *key, const char *value)
890 {
891         conn_data_value_s *data_value = NULL;
892
893         retv_if(!resource_info, -1);
894         retv_if(!key, -1);
895         retv_if(!value, -1);
896
897         _D("adding key[%s] - value[%s]", key, value);
898
899         data_value = malloc(sizeof(conn_data_value_s));
900         retv_if(!data_value, -1);
901
902         data_value->type = DATA_VAL_TYPE_STRING;
903         data_value->s_val = strdup(value);
904
905         return __add_value_to_hash(resource_info, key, data_value);
906 }
907
908 int connectivity_attributes_remove_value_by_key(connectivity_resource_s *resource_info, const char *key)
909 {
910         retv_if(!resource_info, -1);
911         retv_if(!key, -1);
912
913         if (resource_info->value_hash)
914                 g_hash_table_remove(resource_info->value_hash, key);
915
916         return 0;
917 }
918
919 int connectivity_attributes_remove_all(connectivity_resource_s *resource_info)
920 {
921         retv_if(!resource_info, -1);
922
923         if (resource_info->value_hash) {
924                 g_hash_table_destroy(resource_info->value_hash);
925                 resource_info->value_hash = NULL;
926         }
927
928         return 0;
929 }
930
931 static void __json_add_data_iter_cb(gpointer key, gpointer value, gpointer user_data)
932 {
933         char *name = key;
934         conn_data_value_s *data = value;
935         int ret = 0;
936
937         ret_if(name);
938         ret_if(data);
939
940         switch (data->type) {
941         case DATA_VAL_TYPE_BOOL:
942                 ret = web_util_json_add_boolean(name, data->b_val);
943                 if (IOTCON_ERROR_NONE != ret)
944                         _E("failed to add key[%s], value[%d]", name, data->b_val);
945                 break;
946         case DATA_VAL_TYPE_INT:
947                 ret = web_util_json_add_int(name, data->i_val);
948                 if (IOTCON_ERROR_NONE != ret)
949                         _E("failed to add key[%s], value[%d]", name, data->i_val);
950                 break;
951         case DATA_VAL_TYPE_DOUBLE:
952                 ret = web_util_json_add_double(name, data->d_val);
953                 if (IOTCON_ERROR_NONE != ret)
954                         _E("failed to add key[%s], value[%lf]", name, data->d_val);
955                 break;
956         case DATA_VAL_TYPE_STRING:
957                 ret = web_util_json_add_string(name, data->s_val);
958                 if (IOTCON_ERROR_NONE != ret)
959                         _E("failed to add key[%s], value[%s]", name, data->s_val);
960                 break;
961         default:
962                 _E("Unknown data type [%d]", data->type);
963                 break;
964         }
965
966         return;
967 }
968
969 static void __attr_add_data_iter_cb(gpointer key, gpointer value, gpointer user_data)
970 {
971         char *name = key;
972         conn_data_value_s *data = value;
973         iotcon_attributes_h attr = user_data;
974         int ret = 0;
975
976         ret_if(name);
977         ret_if(data);
978         ret_if(attr);
979
980         switch (data->type) {
981         case DATA_VAL_TYPE_BOOL:
982                 ret = iotcon_attributes_add_bool(attr, name, data->b_val);
983                 if (IOTCON_ERROR_NONE != ret)
984                         _E("failed to add key[%s], value[%d]", name, data->b_val);
985                 break;
986         case DATA_VAL_TYPE_INT:
987                 ret = iotcon_attributes_add_int(attr, name, data->i_val);
988                 if (IOTCON_ERROR_NONE != ret)
989                         _E("failed to add key[%s], value[%d]", name, data->i_val);
990                 break;
991         case DATA_VAL_TYPE_DOUBLE:
992                 ret = iotcon_attributes_add_double(attr, name, data->d_val);
993                 if (IOTCON_ERROR_NONE != ret)
994                         _E("failed to add key[%s], value[%lf]", name, data->d_val);
995                 break;
996         case DATA_VAL_TYPE_STRING:
997                 ret = iotcon_attributes_add_str(attr, name, data->s_val);
998                 if (IOTCON_ERROR_NONE != ret)
999                         _E("failed to add key[%s], value[%s]", name, data->s_val);
1000                 break;
1001         default:
1002                 _E("Unknown data type [%d]", data->type);
1003                 break;
1004         }
1005
1006         return;
1007 }
1008
1009 static int __create_attributes(connectivity_resource_s *resource_info, iotcon_attributes_h *attributes)
1010 {
1011         int ret = 0;
1012         iotcon_attributes_h attr = NULL;
1013
1014         ret = iotcon_attributes_create(&attr);
1015         if (IOTCON_ERROR_NONE != ret) {
1016                 _print_iotcon_error(ret);
1017                 return -1;
1018         }
1019
1020         ret = iotcon_attributes_add_str(attr, PATH, resource_info->path);
1021         if (IOTCON_ERROR_NONE != ret) {
1022                 _print_iotcon_error(ret);
1023                 iotcon_attributes_destroy(attr);
1024                 return -1;
1025         }
1026         if (resource_info->value_hash)
1027                 g_hash_table_foreach(resource_info->value_hash, __attr_add_data_iter_cb, attr);
1028
1029         *attributes = attr;
1030
1031         return 0;
1032 }
1033
1034 int connectivity_attributes_notify_all(connectivity_resource_s *resource_info)
1035 {
1036         int ret = 0;
1037
1038         retv_if(!resource_info, -1);
1039
1040         if (resource_info->value_hash == NULL) {
1041                 _W("You have nothing to notify now");
1042                 return 0;
1043         }
1044
1045
1046         switch (resource_info->protocol_type) {
1047         case CONNECTIVITY_PROTOCOL_IOTIVITY:
1048                 retv_if(!resource_info->conn_data.iotcon_data.res, -1);
1049                 retv_if(!resource_info->conn_data.iotcon_data.observers, -1);
1050                 {
1051                         char *uri_path = NULL;
1052                         iotcon_representation_h representation = NULL;
1053                         iotcon_attributes_h attributes = NULL;
1054                         int iotcon_ret = 0;
1055
1056                         iotcon_ret = iotcon_resource_get_uri_path(resource_info->conn_data.iotcon_data.res, &uri_path);
1057                         retv_if(IOTCON_ERROR_NONE != iotcon_ret, -1);
1058
1059                         iotcon_ret = iotcon_representation_create(&representation);
1060                         retv_if(IOTCON_ERROR_NONE != iotcon_ret, -1);
1061
1062                         iotcon_ret = iotcon_representation_set_uri_path(representation, uri_path);
1063                         if (IOTCON_ERROR_NONE != iotcon_ret) {
1064                                 _print_iotcon_error(iotcon_ret);
1065                                 ret = -1;
1066                         }
1067
1068                         iotcon_ret = __create_attributes(resource_info, &attributes);
1069                         if (iotcon_ret) {
1070                                 _E("failed to create attributes");
1071                                 ret = -1;
1072                         }
1073                         __print_attribute(attributes);
1074
1075                         iotcon_ret = iotcon_representation_set_attributes(representation, attributes);
1076                         if (IOTCON_ERROR_NONE != iotcon_ret) {
1077                                 _print_iotcon_error(iotcon_ret);
1078                                 ret = -1;
1079                         }
1080
1081                         iotcon_ret = iotcon_resource_notify(resource_info->conn_data.iotcon_data.res, representation,
1082                                         resource_info->conn_data.iotcon_data.observers, IOTCON_QOS_LOW);
1083                         if (IOTCON_ERROR_NONE != iotcon_ret) {
1084                                 _print_iotcon_error(iotcon_ret);
1085                                 ret = -1;
1086                         }
1087
1088                         iotcon_representation_destroy(representation);
1089                         iotcon_attributes_destroy(attributes);
1090                 }
1091                 break;
1092         case CONNECTIVITY_PROTOCOL_HTTP:
1093                 ret = web_util_json_init();
1094                 retv_if(ret, -1);
1095
1096                 ret = web_util_json_begin();
1097                 retv_if(ret, -1);
1098
1099                 web_util_json_add_string("SensorPiID", resource_info->path);
1100                 web_util_json_add_string("SensorPiType", resource_info->type);
1101                 g_hash_table_foreach(resource_info->value_hash, __json_add_data_iter_cb, NULL);
1102                 web_util_json_end();
1103
1104                 __noti_by_http();
1105
1106                 web_util_json_fini();
1107                 break;
1108         default:
1109                 break;
1110         }
1111
1112         g_hash_table_destroy(resource_info->value_hash);
1113         resource_info->value_hash = NULL;
1114
1115         return ret;
1116 }
1117
1118 void connectivity_unset_resource(connectivity_resource_s *resource_info)
1119 {
1120         ret_if(!resource_info);
1121
1122         switch (resource_info->protocol_type) {
1123         case CONNECTIVITY_PROTOCOL_IOTIVITY:
1124                 if (resource_info->conn_data.iotcon_data.observers) iotcon_observers_destroy(resource_info->conn_data.iotcon_data.observers);
1125                 if (resource_info->conn_data.iotcon_data.res) iotcon_resource_destroy(resource_info->conn_data.iotcon_data.res);
1126                 iotcon_deinitialize();
1127                 connectivity_iotcon_intialized = 0;
1128                 break;
1129         case CONNECTIVITY_PROTOCOL_HTTP:
1130                 web_util_noti_fini();
1131                 connectivity_http_intialized = 0;
1132                 break;
1133         default:
1134                 break;
1135         }
1136
1137         if (resource_info->path) free(resource_info->path);
1138         if (resource_info->type) free(resource_info->type);
1139         free(resource_info);
1140
1141         return;
1142 }
1143
1144 int connectivity_set_resource(const char *path, const char *type, connectivity_resource_s **out_resource_info)
1145 {
1146         connectivity_resource_s *resource_info = NULL;
1147         int ret = -1;
1148
1149         retv_if(!path, -1);
1150         retv_if(!type, -1);
1151         retv_if(!out_resource_info, -1);
1152
1153         resource_info = calloc(1, sizeof(connectivity_resource_s));
1154         retv_if(!resource_info, -1);
1155
1156         resource_info->path = strdup(path);
1157         goto_if(!resource_info->path, error);
1158
1159         resource_info->type = strdup(type);
1160         goto_if(!resource_info->type, error);
1161
1162         resource_info->protocol_type = ProtocolType;
1163
1164         _D("Path[%s], Type[%s], protocol_type[%d]" , resource_info->path, resource_info->type, resource_info->protocol_type);
1165
1166         switch (resource_info->protocol_type) {
1167         case CONNECTIVITY_PROTOCOL_DEFAULT:
1168                 _D("default protocol type is iotivity\n \
1169                          To set connectivity use connectivity_set_protocol_type() function");
1170                 resource_info->protocol_type = CONNECTIVITY_PROTOCOL_IOTIVITY;
1171         case CONNECTIVITY_PROTOCOL_IOTIVITY:
1172                 ret = __init_iotcon(resource_info);
1173                 goto_if(ret, error);
1174                 break;
1175         case CONNECTIVITY_PROTOCOL_HTTP:
1176                 ret = __init_http(resource_info);
1177                 goto_if(ret, error);
1178                 break;
1179         default:
1180                 goto error;
1181                 break;
1182         }
1183
1184         *out_resource_info = resource_info;
1185
1186         return 0;
1187
1188 error:
1189         if (resource_info->path) free(resource_info->path);
1190         if (resource_info->type) free(resource_info->type);
1191         if (resource_info) free(resource_info);
1192
1193         return -1;
1194 }
1195
1196 int connectivity_set_protocol(connectivity_protocol_e protocol_type)
1197 {
1198         int ret = 0;
1199         retv_if(protocol_type >= CONNECTIVITY_PROTOCOL_MAX, -1);
1200
1201         switch (protocol_type) {
1202         case CONNECTIVITY_PROTOCOL_DEFAULT:
1203         case CONNECTIVITY_PROTOCOL_IOTIVITY:
1204                 if (connectivity_iotcon_intialized) {
1205                         _E("protocol type[%d] aleady initialized", protocol_type);
1206                         return -1;
1207                 }
1208                 ProtocolType = CONNECTIVITY_PROTOCOL_IOTIVITY;
1209                 break;
1210         case CONNECTIVITY_PROTOCOL_HTTP:
1211                 if (connectivity_http_intialized) {
1212                         _E("protocol type[%d] aleady initialized", protocol_type);
1213                         return -1;
1214                 }
1215                 ProtocolType = CONNECTIVITY_PROTOCOL_HTTP;
1216                 break;
1217         default:
1218                 _E("unknown protocol type[%d]", protocol_type);
1219                 return -1;
1220                 break;
1221         }
1222
1223         return ret;
1224 }