Challenge : Create server requried in Question#3
[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 <Eina.h>
27 #include <app_common.h>
28
29 #include "log.h"
30 #include "connectivity.h"
31
32 #define DEVICE_NAME "Dr.Evil's device"
33 #define BUFSIZE 1024
34 #define URI_PATH_LEN 64
35 #define URI_PATH "/door/1"
36 #define PATH "path"
37
38 static void _request_resource_handler(iotcon_resource_h resource, iotcon_request_h request, void *user_data);
39
40 static int _send_response(iotcon_request_h request, iotcon_representation_h representation, iotcon_response_result_e result)
41 {
42         int ret = -1;
43         iotcon_response_h response;
44
45         ret = iotcon_response_create(request, &response);
46         retv_if(IOTCON_ERROR_NONE != ret, -1);
47
48         ret = iotcon_response_set_result(response, result);
49         goto_if(IOTCON_ERROR_NONE != ret, error);
50
51         ret = iotcon_response_set_representation(response, representation);
52         goto_if(IOTCON_ERROR_NONE != ret, error);
53
54         ret = iotcon_response_send(response);
55         goto_if(IOTCON_ERROR_NONE != ret, error);
56
57         iotcon_response_destroy(response);
58
59         return 0;
60
61 error:
62         iotcon_response_destroy(response);
63         return -1;
64 }
65
66 static void _destroy_representation(iotcon_representation_h representation)
67 {
68         ret_if(!representation);
69         iotcon_representation_destroy(representation);
70 }
71
72 static iotcon_representation_h _create_representation_with_bool(connectivity_resource_s *resource_info, const char *key, bool value)
73 {
74         iotcon_attributes_h attributes = NULL;
75         iotcon_representation_h representation = NULL;
76         char *uri_path = NULL;
77         int ret = -1;
78
79         ret = iotcon_resource_get_uri_path(resource_info->res, &uri_path);
80         retv_if(IOTCON_ERROR_NONE != ret, NULL);
81
82         ret = iotcon_representation_create(&representation);
83         retv_if(IOTCON_ERROR_NONE != ret, NULL);
84
85         ret = iotcon_attributes_create(&attributes);
86         goto_if(IOTCON_ERROR_NONE != ret, error);
87
88         ret = iotcon_representation_set_uri_path(representation, uri_path);
89         goto_if(IOTCON_ERROR_NONE != ret, error);
90
91         ret = iotcon_attributes_add_str(attributes, PATH, resource_info->path);
92         goto_if(IOTCON_ERROR_NONE != ret, error);
93
94         ret = iotcon_attributes_add_bool(attributes, key, value);
95         goto_if(IOTCON_ERROR_NONE != ret, error);
96
97         ret = iotcon_representation_set_attributes(representation, attributes);
98         goto_if(IOTCON_ERROR_NONE != ret, error);
99
100         iotcon_attributes_destroy(attributes);
101
102         return representation;
103
104 error:
105         if (attributes) iotcon_attributes_destroy(attributes);
106         if (representation) iotcon_representation_destroy(representation);
107
108         return NULL;
109 }
110
111 static iotcon_representation_h _create_representation_with_int(connectivity_resource_s *resource_info, const char *key, int value)
112 {
113         iotcon_attributes_h attributes = NULL;
114         iotcon_representation_h representation = NULL;
115         char *uri_path = NULL;
116         int ret = -1;
117
118         ret = iotcon_resource_get_uri_path(resource_info->res, &uri_path);
119         retv_if(IOTCON_ERROR_NONE != ret, NULL);
120
121         ret = iotcon_representation_create(&representation);
122         retv_if(IOTCON_ERROR_NONE != ret, NULL);
123
124         ret = iotcon_attributes_create(&attributes);
125         goto_if(IOTCON_ERROR_NONE != ret, error);
126
127         ret = iotcon_representation_set_uri_path(representation, uri_path);
128         goto_if(IOTCON_ERROR_NONE != ret, error);
129
130         ret = iotcon_attributes_add_str(attributes, PATH, resource_info->path);
131         goto_if(IOTCON_ERROR_NONE != ret, error);
132
133         ret = iotcon_attributes_add_int(attributes, key, value);
134         goto_if(IOTCON_ERROR_NONE != ret, error);
135
136         ret = iotcon_representation_set_attributes(representation, attributes);
137         goto_if(IOTCON_ERROR_NONE != ret, error);
138
139         iotcon_attributes_destroy(attributes);
140
141         return representation;
142
143 error:
144         if (attributes) iotcon_attributes_destroy(attributes);
145         if (representation) iotcon_representation_destroy(representation);
146
147         return NULL;
148 }
149
150 static iotcon_representation_h _create_representation_with_double(connectivity_resource_s *resource_info, const char *key, double value)
151 {
152         iotcon_attributes_h attributes = NULL;
153         iotcon_representation_h representation = NULL;
154         char *uri_path = NULL;
155         int ret = -1;
156
157         ret = iotcon_resource_get_uri_path(resource_info->res, &uri_path);
158         retv_if(IOTCON_ERROR_NONE != ret, NULL);
159
160         ret = iotcon_representation_create(&representation);
161         retv_if(IOTCON_ERROR_NONE != ret, NULL);
162
163         ret = iotcon_attributes_create(&attributes);
164         goto_if(IOTCON_ERROR_NONE != ret, error);
165
166         ret = iotcon_representation_set_uri_path(representation, uri_path);
167         goto_if(IOTCON_ERROR_NONE != ret, error);
168
169         ret = iotcon_attributes_add_str(attributes, PATH, resource_info->path);
170         goto_if(IOTCON_ERROR_NONE != ret, error);
171
172         ret = iotcon_attributes_add_double(attributes, key, value);
173         goto_if(IOTCON_ERROR_NONE != ret, error);
174
175         ret = iotcon_representation_set_attributes(representation, attributes);
176         goto_if(IOTCON_ERROR_NONE != ret, error);
177
178         iotcon_attributes_destroy(attributes);
179
180         return representation;
181
182 error:
183         if (attributes) iotcon_attributes_destroy(attributes);
184         if (representation) iotcon_representation_destroy(representation);
185
186         return NULL;
187 }
188
189 static iotcon_representation_h _create_representation_with_str(connectivity_resource_s *resource_info, const char *key, char *value)
190 {
191         iotcon_attributes_h attributes = NULL;
192         iotcon_representation_h representation = NULL;
193         char *uri_path = NULL;
194         int ret = -1;
195
196         ret = iotcon_resource_get_uri_path(resource_info->res, &uri_path);
197         retv_if(IOTCON_ERROR_NONE != ret, NULL);
198
199         ret = iotcon_representation_create(&representation);
200         retv_if(IOTCON_ERROR_NONE != ret, NULL);
201
202         ret = iotcon_attributes_create(&attributes);
203         goto_if(IOTCON_ERROR_NONE != ret, error);
204
205         ret = iotcon_representation_set_uri_path(representation, uri_path);
206         goto_if(IOTCON_ERROR_NONE != ret, error);
207
208         ret = iotcon_attributes_add_str(attributes, PATH, resource_info->path);
209         goto_if(IOTCON_ERROR_NONE != ret, error);
210
211         ret = iotcon_attributes_add_str(attributes, key, value);
212         goto_if(IOTCON_ERROR_NONE != ret, error);
213
214         ret = iotcon_representation_set_attributes(representation, attributes);
215         goto_if(IOTCON_ERROR_NONE != ret, error);
216
217         iotcon_attributes_destroy(attributes);
218
219         return representation;
220
221 error:
222         if (attributes) iotcon_attributes_destroy(attributes);
223         if (representation) iotcon_representation_destroy(representation);
224
225         return NULL;
226 }
227
228 static void _print_iotcon_error(int err_no)
229 {
230         switch (err_no) {
231         case IOTCON_ERROR_NOT_SUPPORTED:
232                 _E("IOTCON_ERROR_NOT_SUPPORTED");
233                 break;
234         case IOTCON_ERROR_PERMISSION_DENIED:
235                 _E("IOTCON_ERROR_PERMISSION_DENIED");
236                 break;
237         case IOTCON_ERROR_INVALID_PARAMETER:
238                 _E("IOTCON_ERROR_INVALID_PARAMETER");
239                 break;
240         default:
241                 _E("Error : [%d]", err_no);
242                 break;
243         }
244 }
245
246 int connectivity_notify_bool(connectivity_resource_s *resource_info, const char *key, bool value)
247 {
248         iotcon_representation_h representation;
249         int ret = -1;
250
251         retv_if(!resource_info, -1);
252         retv_if(!resource_info->observers, -1);
253
254         _D("Notify the value[%d]", value);
255
256         representation = _create_representation_with_bool(resource_info, key, value);
257         retv_if(!representation, -1);
258
259         ret = iotcon_resource_notify(resource_info->res, representation, resource_info->observers, IOTCON_QOS_LOW);
260         if (IOTCON_ERROR_NONE != ret) {
261                 _I("There are some troubles for notifying value[%d]", ret);
262                 _print_iotcon_error(ret);
263                 return -1;
264         }
265
266         _destroy_representation(representation);
267
268         return 0;
269 }
270
271 int connectivity_notify_int(connectivity_resource_s *resource_info, const char *key, int value)
272 {
273         iotcon_representation_h representation;
274         int ret = -1;
275
276         retv_if(!resource_info, -1);
277         retv_if(!resource_info->observers, -1);
278
279         _D("Notify the value[%d]", value);
280
281         representation = _create_representation_with_int(resource_info, key, value);
282         retv_if(!representation, -1);
283
284         ret = iotcon_resource_notify(resource_info->res, representation, resource_info->observers, IOTCON_QOS_LOW);
285         if (IOTCON_ERROR_NONE != ret) {
286                 _I("There are some troubles for notifying value[%d]", ret);
287                 _print_iotcon_error(ret);
288                 return -1;
289         }
290
291         _destroy_representation(representation);
292
293         return 0;
294 }
295
296 int connectivity_notify_double(connectivity_resource_s *resource_info, const char *key, double value)
297 {
298         iotcon_representation_h representation;
299         int ret = -1;
300
301         retv_if(!resource_info, -1);
302         retv_if(!resource_info->observers, -1);
303
304         _D("Notify the value[%f]", value);
305
306         representation = _create_representation_with_double(resource_info, key, value);
307         retv_if(!representation, -1);
308
309         ret = iotcon_resource_notify(resource_info->res, representation, resource_info->observers, IOTCON_QOS_LOW);
310         if (IOTCON_ERROR_NONE != ret) {
311                 _I("There are some troubles for notifying value[%d]", ret);
312                 _print_iotcon_error(ret);
313                 return -1;
314         }
315
316         _destroy_representation(representation);
317
318         return 0;
319 }
320
321 int connectivity_notify_string(connectivity_resource_s *resource_info, const char *key, char *value)
322 {
323         iotcon_representation_h representation;
324         int ret = -1;
325
326         retv_if(!resource_info, -1);
327         retv_if(!resource_info->observers, -1);
328
329         _D("Notify all members [%s]", value);
330
331         representation = _create_representation_with_str(resource_info, key, value);
332         retv_if(!representation, -1);
333
334         ret = iotcon_resource_notify(resource_info->res, representation, resource_info->observers, IOTCON_QOS_LOW);
335         if (IOTCON_ERROR_NONE != ret) {
336                 //_I("There are some troubles for notifying value[%d]", ret);
337                 _print_iotcon_error(ret);
338                 return -1;
339         }
340
341         _destroy_representation(representation);
342
343         return 0;
344 }
345
346 static bool _query_cb(const char *key, const char *value, void *user_data)
347 {
348         _D("Key : [%s], Value : [%s]", key, value);
349
350         return IOTCON_FUNC_CONTINUE;
351 }
352
353 static int _handle_query(iotcon_request_h request)
354 {
355         iotcon_query_h query = NULL;
356         int ret = -1;
357
358         ret = iotcon_request_get_query(request, &query);
359         retv_if(IOTCON_ERROR_NONE != ret, -1);
360
361         if (query) iotcon_query_foreach(query, _query_cb, NULL);
362
363         return 0;
364 }
365
366 static int _handle_request_by_crud_type(iotcon_request_h request, connectivity_resource_s *resource_info)
367 {
368         iotcon_request_type_e type;
369         int ret = -1;
370
371         ret = iotcon_request_get_request_type(request, &type);
372         retv_if(IOTCON_ERROR_NONE != ret, -1);
373
374         switch (type) {
375         case IOTCON_REQUEST_GET:
376                 _I("Do not support 'get' query");
377                 break;
378         case IOTCON_REQUEST_PUT:
379                 _I("Do not support 'put' query");
380                 break;
381         case IOTCON_REQUEST_POST:
382                 _I("Do not support 'post' query");
383                 break;
384         case IOTCON_REQUEST_DELETE:
385                 _I("Do not support 'delete' query");
386                 break;
387         default:
388                 _E("Cannot reach here");
389                 ret = -1;
390                 break;
391         }
392         retv_if(0 != ret, -1);
393
394         return 0;
395 }
396
397 static int _handle_observer(iotcon_request_h request, iotcon_observers_h observers)
398 {
399         iotcon_observe_type_e observe_type;
400         int ret = -1;
401         int observe_id = -1;
402
403         ret = iotcon_request_get_observe_type(request, &observe_type);
404         retv_if(IOTCON_ERROR_NONE != ret, -1);
405
406         if (IOTCON_OBSERVE_REGISTER == observe_type) {
407                 ret = iotcon_request_get_observe_id(request, &observe_id);
408                 retv_if(IOTCON_ERROR_NONE != ret, -1);
409
410                 _I("Add an observer : %d", observe_id);
411
412                 ret = iotcon_observers_add(observers, observe_id);
413                 retv_if(IOTCON_ERROR_NONE != ret, -1);
414         } else if (IOTCON_OBSERVE_DEREGISTER == observe_type) {
415                 ret = iotcon_request_get_observe_id(request, &observe_id);
416                 retv_if(IOTCON_ERROR_NONE != ret, -1);
417
418                 _I("Remove an observer : %d", observe_id);
419
420                 ret = iotcon_observers_remove(observers, observe_id);
421                 retv_if(IOTCON_ERROR_NONE != ret, -1);
422         }
423
424         return 0;
425 }
426
427 static void _request_resource_handler(iotcon_resource_h resource, iotcon_request_h request, void *user_data)
428 {
429         connectivity_resource_s *resource_info = user_data;
430         int ret = -1;
431         char *host_address = NULL;
432
433         ret_if(!request);
434
435         ret = iotcon_request_get_host_address(request, &host_address);
436         goto_if(IOTCON_ERROR_NONE != ret, error);
437
438         _D("Host address : %s", host_address);
439
440         ret = _handle_query(request);
441         goto_if(IOTCON_ERROR_NONE != ret, error);
442
443         ret = _handle_request_by_crud_type(request, resource_info);
444         goto_if(0 != ret, error);
445
446         ret = _handle_observer(request, resource_info->observers);
447         goto_if(0 != ret, error);
448
449         return;
450
451 error:
452         _send_response(request, NULL, IOTCON_RESPONSE_ERROR);
453 }
454
455 static void _copy_file(const char *in_filename, const char *out_filename)
456 {
457         char buf[BUFSIZE] = { 0, };
458         size_t nread = 0;
459         FILE *in = NULL;
460         FILE *out = NULL;
461
462         ret_if(!in_filename);
463         ret_if(!out_filename);
464
465         in = fopen(in_filename, "r");
466         ret_if(!in);
467
468         out = fopen(out_filename, "w");
469         goto_if(!out, error);
470
471         rewind(in);
472         while ((nread = fread(buf, 1, sizeof(buf), in)) > 0) {
473                 if (fwrite(buf, 1, nread, out) < nread) {
474                         _E("critical error to copy a file");
475                         break;
476                 }
477         }
478
479         fclose(in);
480         fclose(out);
481
482         return;
483
484 error:
485         fclose(out);
486 }
487
488 int connectivity_init(void)
489 {
490         int ret = -1;
491
492         _copy_file(CBOR_FILE_IN_RES, CBOR_FILE_IN_DATA);
493
494         ret = iotcon_initialize(CBOR_FILE_IN_DATA);
495         retv_if(IOTCON_ERROR_NONE != ret, -1);
496
497         ret = iotcon_set_device_name(DEVICE_NAME);
498         goto_if(IOTCON_ERROR_NONE != ret, error);
499
500         return 0;
501
502 error:
503         iotcon_deinitialize();
504         return -1;
505 }
506
507 int connectivity_fini(void)
508 {
509         iotcon_deinitialize();
510         return 0;
511 }
512
513 void connectivity_unset_resource(connectivity_resource_s *resource_info)
514 {
515         ret_if(!resource_info);
516         if (resource_info->observers) iotcon_observers_destroy(resource_info->observers);
517         if (resource_info->res) iotcon_resource_destroy(resource_info->res);
518         if (resource_info->path) free(resource_info->path);
519         free(resource_info);
520 }
521
522 int connectivity_set_resource(const char *path, const char *type, connectivity_resource_s **out_resource_info)
523 {
524         iotcon_resource_types_h resource_types = NULL;
525         iotcon_resource_interfaces_h ifaces = NULL;
526         connectivity_resource_s *resource_info = NULL;
527         uint8_t policies;
528         int ret = -1;
529
530         retv_if(!path, -1);
531         retv_if(!type, -1);
532         retv_if(!out_resource_info, -1);
533
534         resource_info = calloc(1, sizeof(connectivity_resource_s));
535         retv_if(!resource_info, -1);
536
537         resource_info->path = strdup(path);
538         goto_if(!resource_info->path, error);
539
540         _D("Path : [%s]", resource_info->path);
541
542         ret = iotcon_resource_types_create(&resource_types);
543         goto_if(IOTCON_ERROR_NONE != ret, error);
544
545         ret = iotcon_resource_types_add(resource_types, type);
546         goto_if(IOTCON_ERROR_NONE != ret, error);
547
548         ret = iotcon_resource_interfaces_create(&ifaces);
549         goto_if(IOTCON_ERROR_NONE != ret, error);
550
551         ret = iotcon_resource_interfaces_add(ifaces, IOTCON_INTERFACE_DEFAULT);
552         goto_if(IOTCON_ERROR_NONE != ret, error);
553
554         ret = iotcon_resource_interfaces_add(ifaces, IOTCON_INTERFACE_BATCH);
555         goto_if(IOTCON_ERROR_NONE != ret, error);
556
557         policies =
558                 IOTCON_RESOURCE_DISCOVERABLE |
559                 IOTCON_RESOURCE_OBSERVABLE |
560                 IOTCON_RESOURCE_SECURE;
561
562         ret = iotcon_resource_create(URI_PATH,
563                         resource_types,
564                         ifaces,
565                         policies,
566                         _request_resource_handler,
567                         resource_info,
568                         &resource_info->res);
569         goto_if(IOTCON_ERROR_NONE != ret, error);
570
571         ret = iotcon_observers_create(&resource_info->observers);
572         goto_if(IOTCON_ERROR_NONE != ret, error);
573
574         iotcon_resource_types_destroy(resource_types);
575         iotcon_resource_interfaces_destroy(ifaces);
576         *out_resource_info = resource_info;
577
578         return 0;
579
580 error:
581         if (ifaces) iotcon_resource_interfaces_destroy(ifaces);
582         if (resource_types) iotcon_resource_types_destroy(resource_types);
583         if (resource_info->res) iotcon_resource_destroy(resource_info->res);
584         if (resource_info->path) free(resource_info->path);
585         if (resource_info) free(resource_info);
586
587         return -1;
588 }