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