ecda6ba67acd4bad324464b44c1e5f18111625af
[platform/core/iot/iotcon.git] / test / iotcon-test-basic-server.c
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdlib.h>
18 #include <glib.h>
19
20 #include <iotcon.h>
21 #include <iotcon-internal.h>
22 #include "test.h"
23
24 #define DOOR_RESOURCE_URI "/door/1"
25 #define DOOR_RESOURCE_URI2 "/door/2"
26 #define DOOR_RESOURCE_TYPE "org.tizen.door"
27
28 /* Door Resource */
29 typedef struct _door_resource_s {
30         bool state;
31         char *uri_path;
32         char *type;
33         int ifaces;
34         int properties;
35         iotcon_resource_h handle;
36         iotcon_observers_h observers;
37         iotcon_representation_h repr;
38 } door_resource_s;
39
40 static bool _resource_created;
41
42 static void _request_handler(iotcon_resource_h resource, iotcon_request_h request,
43                 void *user_data);
44
45 static int _set_door_resource(door_resource_s *door)
46 {
47         int ret;
48
49         door->state = false;
50
51         door->uri_path = strdup(DOOR_RESOURCE_URI);
52         if (NULL == door->uri_path) {
53                 ERR("strdup(%s) Fail", DOOR_RESOURCE_URI);
54                 return -1;
55         }
56
57         door->type = strdup(DOOR_RESOURCE_TYPE);
58         if (NULL == door->type) {
59                 ERR("strdup(%s) Fail", DOOR_RESOURCE_TYPE);
60                 free(door->uri_path);
61                 return -1;
62         }
63
64         door->ifaces = IOTCON_INTERFACE_DEFAULT;
65         door->properties = IOTCON_RESOURCE_DISCOVERABLE;
66
67         ret = iotcon_observers_create(&door->observers);
68         if (IOTCON_ERROR_NONE != ret) {
69                 ERR("iotcon_observers_create() Fail");
70                 free(door->type);
71                 free(door->uri_path);
72                 return -1;
73         }
74
75         return 0;
76 }
77
78 static void _free_door_resource(door_resource_s *door)
79 {
80         iotcon_observers_destroy(door->observers);
81         free(door->type);
82         free(door->uri_path);
83 }
84
85 static void _check_door_state(door_resource_s door)
86 {
87         if (false == door.state)
88                 INFO("[Door] closed.");
89         else
90                 INFO("[Door] opened.");
91 }
92
93 static iotcon_resource_h _create_door_resource(char *uri_path, char *type, int ifaces,
94                 int properties, void *user_data)
95 {
96         int ret;
97         iotcon_resource_h handle;
98         iotcon_resource_types_h resource_types;
99
100         ret = iotcon_resource_types_create(&resource_types);
101         if (IOTCON_ERROR_NONE != ret) {
102                 ERR("iotcon_resource_types_create() Fail(%d)", ret);
103                 return NULL;
104         }
105
106         ret = iotcon_resource_types_add(resource_types, type);
107         if (IOTCON_ERROR_NONE != ret) {
108                 ERR("iotcon_resource_types_add() Fail(%d)", ret);
109                 iotcon_resource_types_destroy(resource_types);
110                 return NULL;
111         }
112
113         /* register door resource */
114         ret = iotcon_resource_create(uri_path, resource_types, ifaces, properties,
115                         _request_handler, user_data, &handle);
116         if (IOTCON_ERROR_NONE != ret) {
117                 ERR("iotcon_resource_create() Fail");
118                 iotcon_resource_types_destroy(resource_types);
119                 return NULL;
120         }
121
122         iotcon_resource_types_destroy(resource_types);
123
124         return handle;
125 }
126
127 static int _send_response(iotcon_request_h request, iotcon_representation_h repr,
128                 iotcon_response_result_e result)
129 {
130         int ret;
131         iotcon_response_h response;
132
133         ret = iotcon_response_create(request, &response);
134         if (IOTCON_ERROR_NONE != ret) {
135                 ERR("iotcon_response_create() Fail(%d)", ret);
136                 return -1;
137         }
138
139         ret = iotcon_response_set_result(response, result);
140         if (IOTCON_ERROR_NONE != ret) {
141                 ERR("iotcon_response_set_result() Fail(%d)", ret);
142                 iotcon_response_destroy(response);
143                 return -1;
144         }
145
146         ret = iotcon_response_set_representation(response, IOTCON_INTERFACE_DEFAULT, repr);
147         if (IOTCON_ERROR_NONE != ret) {
148                 ERR("iotcon_response_set_representation() Fail(%d)", ret);
149                 iotcon_response_destroy(response);
150                 return -1;
151         }
152
153         /* send Representation to the client */
154         ret = iotcon_response_send(response);
155         if (IOTCON_ERROR_NONE != ret) {
156                 ERR("iotcon_response_send() Fail(%d)", ret);
157                 iotcon_response_destroy(response);
158                 return -1;
159         }
160
161         iotcon_response_destroy(response);
162
163         return 0;
164 }
165
166 static iotcon_representation_h _get_door_representation(door_resource_s *door)
167 {
168         int ret;
169         iotcon_state_h state;
170         iotcon_representation_h repr;
171
172         /* create a door Representation */
173         ret = iotcon_representation_create(&repr);
174         if (IOTCON_ERROR_NONE != ret) {
175                 ERR("iotcon_representation_create() Fail(%d)", ret);
176                 return NULL;
177         }
178
179         /* create a door state */
180         ret = iotcon_state_create(&state);
181         if (IOTCON_ERROR_NONE != ret) {
182                 ERR("iotcon_state_create() Fail(%d)", ret);
183                 iotcon_representation_destroy(repr);
184                 return NULL;
185         }
186
187         ret = iotcon_representation_set_uri_path(repr, door->uri_path);
188         if (IOTCON_ERROR_NONE != ret) {
189                 ERR("iotcon_representation_set_uri_path() Fail(%d)", ret);
190                 iotcon_state_destroy(state);
191                 iotcon_representation_destroy(repr);
192                 return NULL;
193         }
194
195         ret = iotcon_state_set_bool(state, "opened", door->state);
196         if (IOTCON_ERROR_NONE != ret) {
197                 ERR("iotcon_state_set_bool() Fail(%d)", ret);
198                 iotcon_state_destroy(state);
199                 iotcon_representation_destroy(repr);
200                 return NULL;
201         }
202
203         ret = iotcon_representation_set_state(repr, state);
204         if (IOTCON_ERROR_NONE != ret) {
205                 ERR("iotcon_representation_set_state() Fail(%d)", ret);
206                 iotcon_state_destroy(state);
207                 iotcon_representation_destroy(repr);
208                 return NULL;
209         }
210
211         iotcon_state_destroy(state);
212
213         return repr;
214 }
215
216 static int _request_handler_get(door_resource_s *door, iotcon_request_h request)
217 {
218         int ret;
219         iotcon_representation_h resp_repr;
220         INFO("GET request");
221
222         resp_repr = _get_door_representation(door);
223         if (NULL == resp_repr) {
224                 ERR("_get_door_representation() Fail");
225                 return -1;
226         }
227
228         ret = _send_response(request, resp_repr, IOTCON_RESPONSE_OK);
229         if (0 != ret) {
230                 ERR("_send_response() Fail(%d)", ret);
231                 iotcon_representation_destroy(resp_repr);
232                 return -1;
233         }
234
235         iotcon_representation_destroy(resp_repr);
236
237         return 0;
238 }
239
240 static int _set_door_representation(door_resource_s *door, iotcon_representation_h repr)
241 {
242         int ret;
243         bool bval;
244         iotcon_state_h state;
245
246         ret = iotcon_representation_get_state(repr, &state);
247         if (IOTCON_ERROR_NONE != ret) {
248                 ERR("iotcon_representation_get_state() Fail(%d)", ret);
249                 return -1;
250         }
251
252         ret = iotcon_state_get_bool(state, "opened", &bval);
253         if (IOTCON_ERROR_NONE != ret) {
254                 ERR("iotcon_state_get_bool() Fail(%d)", ret);
255                 return -1;
256         }
257
258         door->state = bval;
259
260         return 0;
261 }
262
263 static int _request_handler_put(door_resource_s *door, iotcon_request_h request)
264 {
265         int ret;
266         iotcon_representation_h req_repr, resp_repr;
267         INFO("PUT request");
268
269         ret = iotcon_request_get_representation(request, &req_repr);
270         if (IOTCON_ERROR_NONE != ret) {
271                 ERR("iotcon_request_get_representation() Fail(%d)", ret);
272                 return -1;
273         }
274
275         ret = _set_door_representation(door, req_repr);
276         if (0 != ret) {
277                 ERR("_set_door_representation() Fail(%d)", ret);
278                 return -1;
279         }
280
281         _check_door_state(*door);
282
283         resp_repr = _get_door_representation(door);
284         if (NULL == resp_repr) {
285                 ERR("_get_door_representation() Fail");
286                 return -1;
287         }
288
289         ret = _send_response(request, resp_repr, IOTCON_RESPONSE_OK);
290         if (0 != ret) {
291                 ERR("_send_response() Fail(%d)", ret);
292                 iotcon_representation_destroy(resp_repr);
293                 return -1;
294         }
295
296         /* notify */
297         ret = iotcon_resource_notify(door->handle, resp_repr, door->observers);
298         if (IOTCON_ERROR_NONE != ret)
299                 ERR("iotcon_resource_notify() Fail(%d)", ret);
300
301         iotcon_representation_destroy(resp_repr);
302
303         return 0;
304 }
305
306 static gboolean _door_state_changer(gpointer user_data)
307 {
308         int ret;
309         static int i = 0;
310         iotcon_representation_h repr;
311         door_resource_s *door = user_data;
312
313         if ((5 == i++) || NULL == door->observers)
314                 return G_SOURCE_REMOVE;
315
316         if (false == door->state) {
317                 door->state = true;
318                 INFO("[Door] closed -> opened");
319         } else {
320                 door->state = false;
321                 INFO("[Door] opened -> closed");
322         }
323
324         INFO("NOTIFY!");
325
326         repr = _get_door_representation(door);
327         if (NULL == repr) {
328                 ERR("_get_door_representation() Fail");
329                 return G_SOURCE_REMOVE;
330         }
331
332         ret = iotcon_resource_notify(door->handle, repr, door->observers);
333         if (IOTCON_ERROR_NONE != ret) {
334                 ERR("iotcon_resource_notify() Fail(%d)", ret);
335                 iotcon_representation_destroy(repr);
336                 return G_SOURCE_REMOVE;
337         }
338
339         iotcon_representation_destroy(repr);
340         return G_SOURCE_CONTINUE;
341 }
342
343 static int _request_handler_post(door_resource_s *door, iotcon_request_h request)
344 {
345         int ret;
346         iotcon_state_h resp_state;
347         iotcon_representation_h resp_repr = NULL;
348         iotcon_resource_h new_door_handle;
349         INFO("POST request");
350
351         if (_resource_created) {
352                 ERR("Resource(%s) is already created", DOOR_RESOURCE_URI2);
353                 return -1;
354         }
355
356         new_door_handle = _create_door_resource(DOOR_RESOURCE_URI2, door->type,
357                         IOTCON_INTERFACE_DEFAULT, (IOTCON_RESOURCE_DISCOVERABLE | IOTCON_RESOURCE_OBSERVABLE), door);
358         if (NULL == new_door_handle) {
359                 ERR("_create_door_resource() Fail");
360                 return -1;
361         }
362         _resource_created = true;
363
364         /* send information that new resource was created */
365         ret = iotcon_representation_create(&resp_repr);
366         if (IOTCON_ERROR_NONE != ret) {
367                 ERR("iotcon_representation_create() Fail(%d)", ret);
368                 return -1;
369         }
370
371         ret = iotcon_state_create(&resp_state);
372         if (IOTCON_ERROR_NONE != ret) {
373                 ERR("iotcon_state_create() Fail(%d)", ret);
374                 iotcon_representation_destroy(resp_repr);
375                 return -1;
376         }
377
378         ret = iotcon_state_set_str(resp_state, "createduripath", DOOR_RESOURCE_URI2);
379         if (IOTCON_ERROR_NONE != ret) {
380                 ERR("iotcon_state_set_str() Fail(%d)", ret);
381                 iotcon_state_destroy(resp_state);
382                 iotcon_representation_destroy(resp_repr);
383                 return -1;
384         }
385
386         ret = iotcon_representation_set_state(resp_repr, resp_state);
387         if (IOTCON_ERROR_NONE != ret) {
388                 ERR("iotcon_representation_set_state() Fail(%d)", ret);
389                 iotcon_state_destroy(resp_state);
390                 iotcon_representation_destroy(resp_repr);
391                 return -1;
392         }
393
394         iotcon_state_destroy(resp_state);
395
396         ret = _send_response(request, resp_repr, IOTCON_RESPONSE_RESOURCE_CREATED);
397         if (0 != ret) {
398                 ERR("_send_response() Fail(%d)", ret);
399                 iotcon_representation_destroy(resp_repr);
400                 return -1;
401         }
402
403         iotcon_representation_destroy(resp_repr);
404
405         return 0;
406 }
407
408 static int _request_handler_delete(iotcon_resource_h resource, iotcon_request_h request)
409 {
410         int ret;
411         INFO("DELETE request");
412
413         ret = iotcon_resource_destroy(resource);
414         if (IOTCON_ERROR_NONE != ret) {
415                 ERR("iotcon_unregiser_resource() Fail(%d)", ret);
416                 return -1;
417         }
418
419         ret = _send_response(request, NULL, IOTCON_RESPONSE_RESULT_DELETED);
420         if (0 != ret) {
421                 ERR("_send_response() Fail(%d)", ret);
422                 return -1;
423         }
424
425         return 0;
426 }
427
428 static bool _query_cb(const char *key, const char *value, void *user_data)
429 {
430         INFO("key : %s, value : %s", key, value);
431
432         return IOTCON_FUNC_CONTINUE;
433 }
434
435 static void _request_handler(iotcon_resource_h resource, iotcon_request_h request,
436                 void *user_data)
437 {
438         door_resource_s *door;
439         iotcon_query_h query;
440         int ret, observe_id;
441         iotcon_request_type_e type;
442         iotcon_observe_type_e observe_type;
443         char *host_address;
444
445         RET_IF(NULL == request);
446
447         ret = iotcon_request_get_host_address(request, &host_address);
448         if (IOTCON_ERROR_NONE != ret) {
449                 ERR("iotcon_request_get_host_address() Fail(%d)", ret);
450                 _send_response(request, NULL, IOTCON_RESPONSE_ERROR);
451                 return;
452         }
453         INFO("host_address : %s", host_address);
454
455         ret = iotcon_request_get_query(request, &query);
456         if (IOTCON_ERROR_NONE != ret) {
457                 ERR("iotcon_request_get_query() Fail(%d)", ret);
458                 _send_response(request, NULL, IOTCON_RESPONSE_ERROR);
459                 return;
460         }
461         if (query)
462                 iotcon_query_foreach(query, _query_cb, NULL);
463
464         ret = iotcon_request_get_request_type(request, &type);
465         if (IOTCON_ERROR_NONE != ret) {
466                 ERR("iotcon_request_get_types() Fail(%d)", ret);
467                 _send_response(request, NULL, IOTCON_RESPONSE_ERROR);
468                 return;
469         }
470
471
472         door = user_data;
473
474         if (IOTCON_REQUEST_GET == type)
475                 ret = _request_handler_get(door, request);
476
477         else if (IOTCON_REQUEST_PUT == type)
478                 ret = _request_handler_put(door, request);
479
480         else if (IOTCON_REQUEST_POST == type)
481                 ret = _request_handler_post(door, request);
482
483         else if (IOTCON_REQUEST_DELETE == type)
484                 ret = _request_handler_delete(resource, request);
485
486         if (0 != ret) {
487                 _send_response(request, NULL, IOTCON_RESPONSE_ERROR);
488                 return;
489         }
490
491         ret = iotcon_request_get_observe_type(request, &observe_type);
492         if (IOTCON_ERROR_NONE != ret) {
493                 ERR("iotcon_request_get_observe_type() Fail(%d)", ret);
494                 return;
495         }
496
497         if (IOTCON_OBSERVE_REGISTER == observe_type) {
498                 ret = iotcon_request_get_observe_id(request, &observe_id);
499                 if (IOTCON_ERROR_NONE != ret) {
500                         ERR("iotcon_request_get_observe_id() Fail(%d)", ret);
501                         return;
502                 }
503
504                 ret = iotcon_observers_add(door->observers, observe_id);
505                 if (IOTCON_ERROR_NONE != ret) {
506                         ERR("iotcon_observers_add() Fail(%d)", ret);
507                         return;
508                 }
509         } else if (IOTCON_OBSERVE_DEREGISTER == observe_type) {
510                 ret = iotcon_request_get_observe_id(request, &observe_id);
511                 if (IOTCON_ERROR_NONE != ret) {
512                         ERR("iotcon_request_get_observe_id() Fail(%d)", ret);
513                         return;
514                 }
515                 ret = iotcon_observers_remove(door->observers, observe_id);
516                 if (IOTCON_ERROR_NONE != ret) {
517                         ERR("iotcon_observers_remove() Fail(%d)", ret);
518                         return;
519                 }
520         }
521 }
522
523 static gboolean _presence_timer(gpointer user_data)
524 {
525         static int i = 0;
526         i++;
527         if (i % 2)
528                 iotcon_stop_presence();
529         else
530                 iotcon_start_presence(10);
531
532         if (3 == i)
533                 return G_SOURCE_REMOVE;
534
535         return G_SOURCE_CONTINUE;
536 }
537
538 int main(int argc, char **argv)
539 {
540         FN_CALL;
541         int ret;
542         GMainLoop *loop;
543         door_resource_s my_door = {0};
544
545         loop = g_main_loop_new(NULL, FALSE);
546
547         /* connect iotcon */
548         ret = iotcon_connect();
549         if (IOTCON_ERROR_NONE != ret) {
550                 ERR("iotcon_connect() Fail(%d)", ret);
551                 return -1;
552         }
553
554         /* set local door resource */
555         ret = _set_door_resource(&my_door);
556         if (0 != ret) {
557                 ERR("_set_door_resource() Fail");
558                 iotcon_disconnect();
559                 return -1;
560         }
561
562         /* add resource options */
563         my_door.ifaces |= IOTCON_INTERFACE_BATCH;
564         my_door.properties |= IOTCON_RESOURCE_OBSERVABLE;
565
566         /* add presence */
567         g_timeout_add_seconds(10, _presence_timer, NULL);
568         iotcon_start_presence(10);
569
570         /* create new door resource */
571         my_door.handle = _create_door_resource(my_door.uri_path, my_door.type, my_door.ifaces,
572                         my_door.properties, &my_door);
573         if (NULL == my_door.handle) {
574                 ERR("_create_door_resource() Fail");
575                 _free_door_resource(&my_door);
576                 iotcon_disconnect();
577                 return -1;
578         }
579
580         _check_door_state(my_door);
581
582         /* add observe */
583         g_timeout_add_seconds(5, _door_state_changer, &my_door);
584
585         g_main_loop_run(loop);
586         g_main_loop_unref(loop);
587
588         iotcon_resource_destroy(my_door.handle);
589
590         _free_door_resource(&my_door);
591
592         /* disconnect iotcon */
593         iotcon_disconnect();
594
595         return 0;
596 }