Modify terms related to signal
[platform/core/iot/iotcon.git] / daemon / icd-ioty.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 <stdio.h>
18 #include <stdlib.h>
19 #include <stdint.h> /* for uint8_t etc */
20 #include <errno.h>
21 #include <glib.h>
22 #include <tizen_type.h>
23 #include <system_info.h>
24 #include <system_settings.h>
25
26 #include <octypes.h>
27 #include <ocstack.h>
28
29 #include "iotcon.h"
30 #include "ic-dbus.h"
31 #include "ic-utils.h"
32 #include "icd.h"
33 #include "icd-payload.h"
34 #include "icd-dbus.h"
35 #include "icd-ioty.h"
36 #include "icd-ioty-type.h"
37 #include "icd-ioty-ocprocess.h"
38
39 #define ICD_UUID_LENGTH 37
40
41 static const char *ICD_SYSTEM_INFO_TIZEN_ID = "http://tizen.org/system/tizenid";
42 static const char *ICD_SYSTEM_INFO_PLATFORM_NAME = "http://tizen.org/system/platform.name";
43 static const char *ICD_SYSTEM_INFO_PLATFORM_VERSION = "http://tizen.org/feature/platform.version";
44 static const char *ICD_SYSTEM_INFO_MANUF_NAME = "http://tizen.org/system/manufacturer";
45 static const char *ICD_SYSTEM_INFO_MODEL_NAME = "http://tizen.org/system/model_name";
46 static const char *ICD_SYSTEM_INFO_BUILD_STRING = "http://tizen.org/system/build.string";
47
48 typedef struct {
49         char *device_name;
50         char *tizen_device_id;
51 } icd_tizen_info_s;
52
53 static icd_tizen_info_s icd_tizen_info = {0};
54
55 static GMutex icd_csdk_mutex;
56
57 void icd_ioty_csdk_lock()
58 {
59         g_mutex_lock(&icd_csdk_mutex);
60 }
61
62
63 void icd_ioty_csdk_unlock()
64 {
65         g_mutex_unlock(&icd_csdk_mutex);
66 }
67
68
69 GThread* icd_ioty_init(const char *addr, unsigned short port)
70 {
71         FN_CALL;
72         GError *error;
73         GThread *thread;
74
75         OCStackResult result = OCInit(addr, port, OC_CLIENT_SERVER);
76         if (OC_STACK_OK != result) {
77                 ERR("OCInit() Fail(%d)", result);
78                 return NULL;
79         }
80
81         DBG("OCInit() Success");
82
83         thread = g_thread_try_new("packet_receive_thread", icd_ioty_ocprocess_thread,
84                         NULL, &error);
85         if (NULL == thread) {
86                 ERR("g_thread_try_new() Fail(%s)", error->message);
87                 g_error_free(error);
88                 return NULL;
89         }
90
91         return thread;
92 }
93
94
95 void icd_ioty_deinit(GThread *thread)
96 {
97         OCStackResult result;
98
99         icd_ioty_ocprocess_stop();
100         g_thread_join(thread);
101
102         result = OCStop();
103         if (OC_STACK_OK != result)
104                 ERR("OCStop() Fail(%d)", result);
105 }
106
107 static int _ioty_properties_to_oic_properties(int properties)
108 {
109         int prop = OC_RES_PROP_NONE;
110
111         if (IOTCON_DISCOVERABLE & properties)
112                 prop |= OC_DISCOVERABLE;
113
114         if (IOTCON_OBSERVABLE & properties)
115                 prop |= OC_OBSERVABLE;
116
117         if (IOTCON_ACTIVE & properties)
118                 prop |= OC_ACTIVE;
119
120         if (IOTCON_SLOW & properties)
121                 prop |= OC_SLOW;
122
123         if (IOTCON_SECURE & properties)
124                 prop |= OC_SECURE;
125
126         if (IOTCON_EXPLICIT_DISCOVERABLE & properties)
127                 prop |= OC_EXPLICIT_DISCOVERABLE;
128
129         /* TODO: Secure option is not supported yet. */
130         properties = (properties & OC_SECURE)? (properties ^ OC_SECURE):properties;
131
132         return prop;
133 }
134
135 OCResourceHandle icd_ioty_register_resource(const char *uri_path,
136                 const char* const* res_types, int ifaces, int properties)
137 {
138         FN_CALL;
139         int i;
140         OCStackResult ret;
141         OCResourceHandle handle;
142         const char *res_iface = NULL;
143
144         if (IOTCON_INTERFACE_DEFAULT & ifaces) {
145                 res_iface = IC_INTERFACE_DEFAULT;
146                 ifaces ^= IOTCON_INTERFACE_DEFAULT;
147         } else if (IOTCON_INTERFACE_LINK & ifaces) {
148                 res_iface = IC_INTERFACE_LINK;
149                 ifaces ^= IOTCON_INTERFACE_LINK;
150         } else if (IOTCON_INTERFACE_BATCH & ifaces) {
151                 res_iface = IC_INTERFACE_BATCH;
152                 ifaces ^= IOTCON_INTERFACE_BATCH;
153         } else if (IOTCON_INTERFACE_GROUP & ifaces) {
154                 res_iface = IC_INTERFACE_GROUP;
155                 ifaces ^= IOTCON_INTERFACE_GROUP;
156         } else {
157                 ERR("Invalid interface type(%d)", ifaces);
158                 return NULL;
159         }
160
161         properties = _ioty_properties_to_oic_properties(properties);
162
163         icd_ioty_csdk_lock();
164         ret = OCCreateResource(&handle, res_types[0], res_iface, uri_path,
165                         icd_ioty_ocprocess_req_handler, NULL, properties);
166         icd_ioty_csdk_unlock();
167         if (OC_STACK_OK != ret) {
168                 ERR("OCCreateResource() Fail(%d)", ret);
169                 return NULL;
170         }
171
172         for (i = 1; res_types[i]; i++)
173                 icd_ioty_bind_type(handle, res_types[i]);
174
175         if (IOTCON_INTERFACE_DEFAULT & ifaces)
176                 icd_ioty_bind_interface(handle, IOTCON_INTERFACE_DEFAULT);
177         if (IOTCON_INTERFACE_LINK & ifaces)
178                 icd_ioty_bind_interface(handle, IOTCON_INTERFACE_LINK);
179         if (IOTCON_INTERFACE_BATCH & ifaces)
180                 icd_ioty_bind_interface(handle, IOTCON_INTERFACE_BATCH);
181         if (IOTCON_INTERFACE_GROUP & ifaces)
182                 icd_ioty_bind_interface(handle, IOTCON_INTERFACE_GROUP);
183
184         return handle;
185 }
186
187
188 int icd_ioty_unregister_resource(OCResourceHandle handle)
189 {
190         OCStackResult ret;
191
192         icd_ioty_csdk_lock();
193         ret = OCDeleteResource(handle);
194         icd_ioty_csdk_unlock();
195
196         if (OC_STACK_OK != ret) {
197                 ERR("OCDeleteResource() Fail(%d)", ret);
198                 return icd_ioty_convert_error(ret);
199         }
200
201         return IOTCON_ERROR_NONE;
202 }
203
204
205 int icd_ioty_bind_interface(OCResourceHandle handle, iotcon_interface_e iface)
206 {
207         int ret;
208         OCStackResult result;
209         char *resource_interface;
210
211         ret = ic_utils_convert_interface_flag(iface, &resource_interface);
212         if (IOTCON_ERROR_NONE != ret) {
213                 ERR("ic_utils_convert_interface_flag(%d) Fail(%d)", iface, ret);
214                 return ret;
215         }
216
217         icd_ioty_csdk_lock();
218         result = OCBindResourceInterfaceToResource(handle, resource_interface);
219         icd_ioty_csdk_unlock();
220
221         if (OC_STACK_OK != result) {
222                 ERR("OCBindResourceInterfaceToResource() Fail(%d)", result);
223                 return icd_ioty_convert_error(result);
224         }
225
226         return IOTCON_ERROR_NONE;
227 }
228
229
230 int icd_ioty_bind_type(OCResourceHandle handle, const char *resource_type)
231 {
232         OCStackResult ret;
233
234         icd_ioty_csdk_lock();
235         ret = OCBindResourceTypeToResource(handle, resource_type);
236         icd_ioty_csdk_unlock();
237
238         if (OC_STACK_OK != ret) {
239                 ERR("OCBindResourceTypeToResource() Fail(%d)", ret);
240                 return icd_ioty_convert_error(ret);
241         }
242
243         return IOTCON_ERROR_NONE;
244 }
245
246
247 int icd_ioty_bind_resource(OCResourceHandle parent, OCResourceHandle child)
248 {
249         OCStackResult ret;
250
251         icd_ioty_csdk_lock();
252         ret = OCBindResource(parent, child);
253         icd_ioty_csdk_unlock();
254
255         if (OC_STACK_OK != ret) {
256                 ERR("OCBindResource() Fail(%d)", ret);
257                 return icd_ioty_convert_error(ret);
258         }
259
260         return IOTCON_ERROR_NONE;
261 }
262
263
264 int icd_ioty_unbind_resource(OCResourceHandle parent, OCResourceHandle child)
265 {
266         OCStackResult ret;
267
268         icd_ioty_csdk_lock();
269         ret = OCUnBindResource(parent, child);
270         icd_ioty_csdk_unlock();
271
272         if (OC_STACK_OK != ret) {
273                 ERR("OCUnBindResource() Fail(%d)", ret);
274                 return icd_ioty_convert_error(ret);
275         }
276
277         return IOTCON_ERROR_NONE;
278 }
279
280 int icd_ioty_notify(OCResourceHandle handle, GVariant *msg, GVariant *observers)
281 {
282         int i, obs_length, msg_length;
283         GVariant *repr_gvar;
284         GVariantIter obs_iter, msg_iter;
285         OCStackResult ret;
286         OCRepPayload *payload;
287
288         g_variant_iter_init(&obs_iter, observers);
289         obs_length = g_variant_iter_n_children(&obs_iter);
290
291         /* Variable-length Array */
292         OCObservationId obs_ids[obs_length];
293
294         for (i = 0; i < obs_length; i++)
295                 g_variant_iter_loop(&obs_iter, "i", &obs_ids[i]);
296
297         g_variant_iter_init(&msg_iter, msg);
298         msg_length = g_variant_iter_n_children(&msg_iter);
299         if (msg_length) {
300                 g_variant_iter_loop(&msg_iter, "v", &repr_gvar);
301                 /* TODO : How to use error_code. */
302                 payload = icd_payload_representation_from_gvariant(repr_gvar);
303         }
304
305         icd_ioty_csdk_lock();
306         /* TODO : QoS is come from lib. */
307         if (msg_length) {
308                 ret = OCNotifyListOfObservers(handle, obs_ids, obs_length, payload, OC_LOW_QOS);
309         } else {
310                 ret = OCNotifyAllObservers(handle, OC_LOW_QOS);
311         }
312         icd_ioty_csdk_unlock();
313
314         if (OC_STACK_NO_OBSERVERS == ret) {
315                 WARN("No Observers. Stop Notifying");
316                 return IOTCON_ERROR_NONE;
317         } else if (OC_STACK_OK != ret) {
318                 ERR("OCNotifyListOfObservers() Fail(%d)", ret);
319                 return icd_ioty_convert_error(ret);
320         }
321
322         return IOTCON_ERROR_NONE;
323 }
324
325
326 static int _ioty_get_header_options(GVariantIter *src, int src_size,
327                 OCHeaderOption dest[], int dest_size)
328 {
329         int i = 0;
330         char *option_data;
331         unsigned short option_id;
332
333         RETV_IF(NULL == dest, IOTCON_ERROR_INVALID_PARAMETER);
334
335         if (dest_size < src_size) {
336                 ERR("Exceed Size(%d)", src_size);
337                 return IOTCON_ERROR_INVALID_PARAMETER;
338         }
339
340         while (g_variant_iter_loop(src, "(q&s)", &option_id, &option_data)) {
341                 dest[i].protocolID = OC_COAP_ID;
342                 dest[i].optionID = option_id;
343                 dest[i].optionLength = strlen(option_data) + 1;
344                 memcpy(dest[i].optionData, option_data, dest[i].optionLength);
345                 i++;
346         }
347
348         return IOTCON_ERROR_NONE;
349 }
350
351
352 int icd_ioty_send_response(GVariant *resp)
353 {
354         GVariant *repr_gvar;
355         GVariantIter *options;
356         OCStackResult ret;
357         OCEntityHandlerResponse response = {0};
358         int result, options_size;
359         int64_t request_handle, resource_handle;
360
361         g_variant_get(resp, "(a(qs)ivxx)",
362                         &options,
363                         &result,
364                         &repr_gvar,
365                         &request_handle,
366                         &resource_handle);
367
368         response.requestHandle = ICD_INT64_TO_POINTER(request_handle);
369         response.resourceHandle = ICD_INT64_TO_POINTER(resource_handle);
370         response.ehResult = (OCEntityHandlerResult)result;
371
372         options_size = g_variant_iter_n_children(options);
373         response.numSendVendorSpecificHeaderOptions = options_size;
374
375         if (0 != options_size) {
376                 int ret= _ioty_get_header_options(options,
377                                 response.numSendVendorSpecificHeaderOptions,
378                                 response.sendVendorSpecificHeaderOptions,
379                                 sizeof(response.sendVendorSpecificHeaderOptions)
380                                 / sizeof(response.sendVendorSpecificHeaderOptions[0]));
381
382                 if (IOTCON_ERROR_NONE != ret)
383                         ERR("_ioty_get_header_options() Fail(%d)", ret);
384         }
385         g_variant_iter_free(options);
386
387         response.payload = (OCPayload*)icd_payload_representation_from_gvariant(repr_gvar);
388
389         /* related to block transfer */
390         response.persistentBufferFlag = 0;
391
392         icd_ioty_csdk_lock();
393         ret = OCDoResponse(&response);
394         icd_ioty_csdk_unlock();
395
396         if (OC_STACK_OK != ret) {
397                 ERR("OCDoResponse() Fail(%d)", ret);
398                 return icd_ioty_convert_error(ret);
399         }
400
401         return IOTCON_ERROR_NONE;
402 }
403
404
405 static void _ioty_free_signal_context(void *data)
406 {
407         icd_sig_ctx_s *context = data;
408         free(context->bus_name);
409         free(context);
410 }
411
412
413 int icd_ioty_find_resource(const char *host_address, int conn_type,
414                 const char *resource_type, unsigned int signal_number, const char *bus_name)
415 {
416         int len;
417         OCStackResult result;
418         icd_sig_ctx_s *context;
419         char uri[PATH_MAX] = {0};
420         OCCallbackData cbdata = {0};
421         OCConnectivityType oic_conn_type;
422
423         if (IC_STR_EQUAL == strcmp(IOTCON_MULTICAST_ADDRESS, host_address)) {
424                 len = snprintf(uri, sizeof(uri), "%s", OC_RSRVD_WELL_KNOWN_URI);
425         } else {
426                 len = snprintf(uri, sizeof(uri), ICD_IOTY_COAP"%s%s", host_address,
427                                 OC_RSRVD_WELL_KNOWN_URI);
428         }
429         if (len <= 0 || sizeof(uri) <= len) {
430                 ERR("snprintf() Fail(%d)", len);
431                 return IOTCON_ERROR_IO_ERROR;
432         }
433
434         if (IC_STR_EQUAL != strcmp(IC_STR_NULL, resource_type))
435                 snprintf(uri + len, sizeof(uri) - len, "?rt=%s", resource_type);
436
437         context = calloc(1, sizeof(icd_sig_ctx_s));
438         if (NULL == context) {
439                 ERR("calloc() Fail(%d)", errno);
440                 return IOTCON_ERROR_OUT_OF_MEMORY;
441         }
442
443         context->bus_name = ic_utils_strdup(bus_name);
444         context->signal_number = signal_number;
445
446         cbdata.context = context;
447         cbdata.cb = icd_ioty_ocprocess_find_cb;
448         cbdata.cd = _ioty_free_signal_context;
449
450         oic_conn_type = icd_ioty_conn_type_to_oic_conn_type(conn_type);
451
452         icd_ioty_csdk_lock();
453         /* TODO : QoS is come from lib. */
454         result = OCDoResource(NULL, OC_REST_DISCOVER, uri, NULL, NULL, oic_conn_type,
455                         OC_LOW_QOS, &cbdata, NULL, 0);
456         icd_ioty_csdk_unlock();
457
458         if (OC_STACK_OK != result) {
459                 ERR("OCDoResource() Fail(%d)", result);
460                 free(context->bus_name);
461                 free(context);
462                 return icd_ioty_convert_error(result);
463         }
464
465         return IOTCON_ERROR_NONE;
466 }
467
468
469 /*
470  * returned string SHOULD be released by you
471  */
472 static char* _icd_ioty_resource_generate_uri(char *uri_path, GVariant *query)
473 {
474         int len;
475         bool loop_first = true;
476         char *key, *value;
477         GVariantIter query_iter;
478         char uri_buf[PATH_MAX] = {0};
479
480         len = snprintf(uri_buf, sizeof(uri_buf), "%s", uri_path);
481
482         /* remove suffix '/' */
483         if ('/' == uri_buf[strlen(uri_buf) - 1]) {
484                 uri_buf[strlen(uri_buf) - 1] = '\0';
485                 len--;
486         }
487
488         g_variant_iter_init(&query_iter, query);
489
490         while (g_variant_iter_loop(&query_iter, "(&s&s)", &key, &value)) {
491                 int query_len;
492
493                 DBG("query exist. key(%s), value(%s)", key, value);
494
495                 if (true == loop_first) {
496                         query_len = snprintf(uri_buf + len, sizeof(uri_buf) - len, "?%s=%s", key, value);
497                         loop_first = false;
498                 } else {
499                         query_len = snprintf(uri_buf + len, sizeof(uri_buf) - len, "&%s=%s", key, value);
500                 }
501
502                 len += query_len;
503         }
504
505         return strdup(uri_buf);
506 }
507
508
509 void icd_ioty_complete(int type, GDBusMethodInvocation *invocation, GVariant *value)
510 {
511         switch(type) {
512         case ICD_CRUD_GET:
513                 ic_dbus_complete_get(icd_dbus_get_object(), invocation, value);
514                 break;
515         case ICD_CRUD_PUT:
516                 ic_dbus_complete_put(icd_dbus_get_object(), invocation, value);
517                 break;
518         case ICD_CRUD_POST:
519                 ic_dbus_complete_post(icd_dbus_get_object(), invocation, value);
520                 break;
521         case ICD_CRUD_DELETE:
522                 ic_dbus_complete_delete(icd_dbus_get_object(), invocation, value);
523                 break;
524         case ICD_TIZEN_INFO:
525                 ic_dbus_complete_get_tizen_info(icd_dbus_get_object(), invocation, value);
526                 break;
527         default:
528                 INFO("Invalid type(%d)", type);
529         }
530 }
531
532
533 void icd_ioty_complete_error(int type, GDBusMethodInvocation *invocation, int ret_val)
534 {
535         GVariant *value;
536         GVariant *payload;
537         GVariantBuilder options;
538
539         switch (type) {
540         case ICD_CRUD_GET:
541                 g_variant_builder_init(&options, G_VARIANT_TYPE("a(qs)"));
542                 payload = icd_payload_representation_empty_gvariant();
543                 value = g_variant_new("(a(qs)vi)", &options, payload, ret_val);
544                 ic_dbus_complete_get(icd_dbus_get_object(), invocation, value);
545                 break;
546         case ICD_CRUD_PUT:
547                 g_variant_builder_init(&options, G_VARIANT_TYPE("a(qs)"));
548                 payload = icd_payload_representation_empty_gvariant();
549                 value = g_variant_new("(a(qs)vi)", &options, payload, ret_val);
550                 ic_dbus_complete_put(icd_dbus_get_object(), invocation, value);
551                 break;
552         case ICD_CRUD_POST:
553                 g_variant_builder_init(&options, G_VARIANT_TYPE("a(qs)"));
554                 payload = icd_payload_representation_empty_gvariant();
555                 value = g_variant_new("(a(qs)vi)", &options, payload, ret_val);
556                 ic_dbus_complete_post(icd_dbus_get_object(), invocation, value);
557                 break;
558         case ICD_CRUD_DELETE:
559                 g_variant_builder_init(&options, G_VARIANT_TYPE("a(qs)"));
560                 value = g_variant_new("(a(qs)i)", &options, ret_val);
561                 ic_dbus_complete_delete(icd_dbus_get_object(), invocation, value);
562                 break;
563         case ICD_TIZEN_INFO:
564                 value = g_variant_new("(ssi)", IC_STR_NULL, IC_STR_NULL, ret_val);
565                 ic_dbus_complete_get_tizen_info(icd_dbus_get_object(), invocation, value);
566                 break;
567         }
568
569 }
570
571
572 static gboolean _icd_ioty_crud(int type,
573                 icDbus *object,
574                 GDBusMethodInvocation *invocation,
575                 GVariant *resource,
576                 GVariant *query,
577                 GVariant *repr)
578 {
579         bool is_secure;
580         OCMethod rest_type;
581         OCStackResult result;
582         GVariantIter *options;
583         OCCallbackData cbdata = {0};
584         int conn_type, options_size;
585         char *uri_path, *host, *uri, *dev_host, *ptr = NULL;
586         OCHeaderOption oic_options[MAX_HEADER_OPTIONS];
587         OCHeaderOption *oic_options_ptr = NULL;
588         OCPayload *payload = NULL;
589         OCConnectivityType oic_conn_type;
590         OCDevAddr dev_addr = {0};
591
592         switch (type) {
593         case ICD_CRUD_GET:
594                 cbdata.cb = icd_ioty_ocprocess_get_cb;
595                 rest_type = OC_REST_GET;
596                 break;
597         case ICD_CRUD_PUT:
598                 cbdata.cb = icd_ioty_ocprocess_put_cb;
599                 rest_type = OC_REST_PUT;
600                 break;
601         case ICD_CRUD_POST:
602                 cbdata.cb = icd_ioty_ocprocess_post_cb;
603                 rest_type = OC_REST_POST;
604                 break;
605         case ICD_CRUD_DELETE:
606                 cbdata.cb = icd_ioty_ocprocess_delete_cb;
607                 rest_type = OC_REST_DELETE;
608                 break;
609         default:
610                 ERR("Invalid CRUD Type(%d)", type);
611                 return FALSE;
612         }
613
614         g_variant_get(resource, "(&s&sba(qs)i)", &uri_path, &host, &is_secure, &options,
615                         &conn_type);
616
617         switch (type) {
618         case ICD_CRUD_GET:
619         case ICD_CRUD_PUT:
620         case ICD_CRUD_POST:
621                 uri = _icd_ioty_resource_generate_uri(uri_path, query);
622                 if (NULL == uri) {
623                         ERR("_icd_ioty_resource_generate_uri() Fail");
624                         g_variant_iter_free(options);
625                         icd_ioty_complete_error(type, invocation, IOTCON_ERROR_INVALID_PARAMETER);
626                         return TRUE;
627                 }
628                 break;
629         case ICD_CRUD_DELETE:
630                 uri = strdup(uri_path);
631                 break;
632         }
633
634         cbdata.context = invocation;
635
636         options_size = g_variant_iter_n_children(options);
637         if (0 != options_size) {
638                 int ret = _ioty_get_header_options(options, options_size, oic_options,
639                                 sizeof(oic_options) / sizeof(oic_options[0]));
640                 if (IOTCON_ERROR_NONE != ret) {
641                         ERR("_ioty_get_header_options() Fail(%d)", ret);
642                         free(uri);
643                         g_variant_iter_free(options);
644                         icd_ioty_complete_error(type, invocation, ret);
645                         return TRUE;
646                 }
647                 oic_options_ptr = oic_options;
648         }
649         g_variant_iter_free(options);
650
651         if (repr)
652                 payload = (OCPayload*)icd_payload_representation_from_gvariant(repr);
653
654         oic_conn_type = icd_ioty_conn_type_to_oic_conn_type(conn_type);
655
656         icd_ioty_conn_type_to_oic_transport_type(conn_type, &dev_addr.adapter,
657                         &dev_addr.flags);
658
659         switch (conn_type) {
660         case IOTCON_CONNECTIVITY_IPV4:
661                 dev_host = strtok_r(host, ":", &ptr);
662                 snprintf(dev_addr.addr, sizeof(dev_addr.addr), "%s", dev_host);
663                 dev_addr.port = atoi(strtok_r(NULL, ":", &ptr));
664                 break;
665         case IOTCON_CONNECTIVITY_IPV6:
666                 dev_host = strtok_r(host, "]", &ptr);
667                 snprintf(dev_addr.addr, sizeof(dev_addr.addr), "%s", dev_host);
668                 dev_addr.port = atoi(strtok_r(NULL, "]", &ptr));
669                 break;
670         default:
671                 ERR("Invalid Connectivitiy Type");
672                 icd_ioty_complete_error(type, invocation, IOTCON_ERROR_IOTIVITY);
673                 free(uri);
674                 return TRUE;
675         }
676
677         icd_ioty_csdk_lock();
678         /* TODO : QoS is come from lib. And user can set QoS to client structure.  */
679         result = OCDoResource(NULL, rest_type, uri, &dev_addr, payload, oic_conn_type,
680                         OC_LOW_QOS, &cbdata, oic_options_ptr, options_size);
681         icd_ioty_csdk_unlock();
682
683         free(uri);
684
685         if (OC_STACK_OK != result) {
686                 ERR("OCDoResource() Fail(%d)", result);
687                 icd_ioty_complete_error(type, invocation, icd_ioty_convert_error(result));
688                 return TRUE;
689         }
690
691         return TRUE;
692 }
693
694 gboolean icd_ioty_get(icDbus *object, GDBusMethodInvocation *invocation,
695                 GVariant *resource, GVariant *query)
696 {
697         return _icd_ioty_crud(ICD_CRUD_GET, object, invocation, resource, query, NULL);
698 }
699
700
701 gboolean icd_ioty_put(icDbus *object, GDBusMethodInvocation *invocation,
702                 GVariant *resource, GVariant *repr, GVariant *query)
703 {
704         return _icd_ioty_crud(ICD_CRUD_PUT, object, invocation, resource, query, repr);
705 }
706
707
708 gboolean icd_ioty_post(icDbus *object, GDBusMethodInvocation *invocation,
709                 GVariant *resource, GVariant *repr, GVariant *query)
710 {
711         return _icd_ioty_crud(ICD_CRUD_POST, object, invocation, resource, query, repr);
712 }
713
714
715 gboolean icd_ioty_delete(icDbus *object, GDBusMethodInvocation *invocation,
716                 GVariant *resource)
717 {
718         return _icd_ioty_crud(ICD_CRUD_DELETE, object, invocation, resource, NULL, NULL);
719 }
720
721
722 OCDoHandle icd_ioty_observer_start(GVariant *resource, int observe_type,
723                 GVariant *query, unsigned int signal_number, const char *bus_name)
724 {
725         bool is_secure;
726         OCMethod method;
727         OCDoHandle handle;
728         OCStackResult result;
729         GVariantIter *options;
730         icd_sig_ctx_s *context;
731         OCCallbackData cbdata = {0};
732         int conn_type, options_size;
733         char *uri_path, *host, *uri, *dev_host, *ptr = NULL;
734         OCHeaderOption oic_options[MAX_HEADER_OPTIONS];
735         OCHeaderOption *oic_options_ptr = NULL;
736         OCConnectivityType oic_conn_type;
737         OCDevAddr dev_addr = {0};
738
739         g_variant_get(resource, "(&s&sba(qs)i)", &uri_path, &host, &is_secure, &options,
740                         &conn_type);
741
742         uri = _icd_ioty_resource_generate_uri(uri_path, query);
743         if (NULL == uri) {
744                 ERR("_icd_ioty_resource_generate_uri() Fail");
745                 g_variant_iter_free(options);
746                 return NULL;
747         }
748
749         if (IOTCON_OBSERVE == observe_type)
750                 method = OC_REST_OBSERVE;
751         else if (IOTCON_OBSERVE_ALL == observe_type)
752                 method = OC_REST_OBSERVE_ALL;
753         else
754                 method = OC_REST_OBSERVE_ALL;
755
756         context = calloc(1, sizeof(icd_sig_ctx_s));
757         if (NULL == context) {
758                 ERR("calloc() Fail(%d)", errno);
759                 return NULL;
760         }
761         context->bus_name = ic_utils_strdup(bus_name);
762         context->signal_number = signal_number;
763
764         cbdata.context = context;
765         cbdata.cb = icd_ioty_ocprocess_observe_cb;
766         cbdata.cd = _ioty_free_signal_context;
767
768         options_size = g_variant_iter_n_children(options);
769         if (0 != options_size) {
770                 int ret = _ioty_get_header_options(options, options_size, oic_options,
771                                 sizeof(oic_options) / sizeof(oic_options[0]));
772                 if (IOTCON_ERROR_NONE != ret) {
773                         ERR("_ioty_get_header_options() Fail(%d)", ret);
774                         free(context->bus_name);
775                         free(context);
776                         free(uri);
777                         g_variant_iter_free(options);
778                         return NULL;
779                 }
780                 oic_options_ptr = oic_options;
781         }
782         g_variant_iter_free(options);
783
784         oic_conn_type = icd_ioty_conn_type_to_oic_conn_type(conn_type);
785
786         icd_ioty_conn_type_to_oic_transport_type(conn_type, &dev_addr.adapter,
787                         &dev_addr.flags);
788
789         switch (conn_type) {
790         case IOTCON_CONNECTIVITY_IPV4:
791                 dev_host = strtok_r(host, ":", &ptr);
792                 snprintf(dev_addr.addr, sizeof(dev_addr.addr), "%s", dev_host);
793                 dev_addr.port = atoi(strtok_r(NULL, ":", &ptr));
794                 break;
795         case IOTCON_CONNECTIVITY_IPV6:
796                 dev_host = strtok_r(host, "]", &ptr);
797                 snprintf(dev_addr.addr, sizeof(dev_addr.addr), "%s", dev_host);
798                 dev_addr.port = atoi(strtok_r(NULL, "]", &ptr));
799                 break;
800         default:
801                 ERR("Invalid Connectivitiy Type");
802                 free(context->bus_name);
803                 free(context);
804                 free(uri);
805                 return NULL;
806         }
807
808         icd_ioty_csdk_lock();
809         /* TODO : QoS is come from lib. And user can set QoS to client structure.  */
810         result = OCDoResource(&handle, method, uri, &dev_addr, NULL, oic_conn_type,
811                         OC_LOW_QOS, &cbdata, oic_options_ptr, options_size);
812         icd_ioty_csdk_unlock();
813         free(uri);
814         if (OC_STACK_OK != result) {
815                 ERR("OCDoResource() Fail(%d)", result);
816                 free(context->bus_name);
817                 free(context);
818                 return NULL;
819         }
820
821         return handle;
822 }
823
824
825 int icd_ioty_observer_stop(OCDoHandle handle, GVariant *options)
826 {
827         int options_size;
828         OCStackResult ret;
829         GVariantIter options_iter;
830         OCHeaderOption oic_options[MAX_HEADER_OPTIONS];
831         OCHeaderOption *oic_options_ptr = NULL;
832
833         g_variant_iter_init(&options_iter, options);
834
835         options_size = g_variant_iter_n_children(&options_iter);
836         if (0 != options_size) {
837                 int ret = _ioty_get_header_options(&options_iter, options_size, oic_options,
838                                 sizeof(oic_options) / sizeof(oic_options[0]));
839                 if (IOTCON_ERROR_NONE != ret) {
840                         ERR("_ioty_get_header_options() Fail(%d)", ret);
841                         return ret;
842                 }
843                 oic_options_ptr = oic_options;
844         }
845
846         icd_ioty_csdk_lock();
847         ret = OCCancel(handle, OC_HIGH_QOS, oic_options_ptr, options_size);
848         icd_ioty_csdk_unlock();
849         if (OC_STACK_OK != ret) {
850                 ERR("OCCancel() Fail(%d)", ret);
851                 return icd_ioty_convert_error(ret);
852         }
853
854         return IOTCON_ERROR_NONE;
855 }
856
857 int icd_ioty_get_info(int type, const char *host_address, int conn_type,
858                 unsigned int signal_number, const char *bus_name)
859 {
860         OCStackResult result;
861         icd_sig_ctx_s *context;
862         OCCallbackData cbdata = {0};
863         char uri[PATH_MAX] = {0};
864         char *uri_path = NULL;
865         OCConnectivityType oic_conn_type;
866
867         if (ICD_DEVICE_INFO == type)
868                 uri_path = OC_RSRVD_DEVICE_URI;
869         else if (ICD_PLATFORM_INFO == type)
870                 uri_path = OC_RSRVD_PLATFORM_URI;
871         else
872                 return IOTCON_ERROR_INVALID_PARAMETER;
873
874         if (IC_STR_EQUAL == strcmp(IOTCON_MULTICAST_ADDRESS, host_address))
875                 snprintf(uri, sizeof(uri), "%s", uri_path);
876         else
877                 snprintf(uri, sizeof(uri), "%s%s", host_address, uri_path);
878
879         context = calloc(1, sizeof(icd_sig_ctx_s));
880         if (NULL == context) {
881                 ERR("calloc() Fail(%d)", errno);
882                 return IOTCON_ERROR_OUT_OF_MEMORY;
883         }
884         context->bus_name = ic_utils_strdup(bus_name);
885         context->signal_number = signal_number;
886
887         cbdata.context = context;
888         cbdata.cb = icd_ioty_ocprocess_info_cb;
889         cbdata.cd = _ioty_free_signal_context;
890
891         oic_conn_type = icd_ioty_conn_type_to_oic_conn_type(conn_type);
892
893         icd_ioty_csdk_lock();
894         /* TODO : QoS is come from lib. And user can set QoS to client structure.  */
895         result = OCDoResource(NULL, OC_REST_DISCOVER, uri, NULL, NULL, oic_conn_type,
896                         OC_LOW_QOS, &cbdata, NULL, 0);
897         icd_ioty_csdk_unlock();
898
899         if (OC_STACK_OK != result) {
900                 ERR("OCDoResource() Fail(%d)", result);
901                 free(context->bus_name);
902                 free(context);
903                 return icd_ioty_convert_error(result);
904         }
905
906         return IOTCON_ERROR_NONE;
907 }
908
909 static int _icd_ioty_get_tizen_id(char **tizen_device_id)
910 {
911         int ret;
912         char *tizen_id = NULL;
913
914         ret = system_info_get_platform_string(ICD_SYSTEM_INFO_TIZEN_ID, &tizen_id);
915         if (SYSTEM_INFO_ERROR_NONE != ret) {
916                 ERR("system_info_get_platform_string() Fail(%d)", ret);
917                 return IOTCON_ERROR_SYSTEM;
918         }
919         *tizen_device_id = tizen_id;
920
921         return IOTCON_ERROR_NONE;
922 }
923
924 static int _ioty_set_device_info()
925 {
926         int ret;
927         char *device_name = NULL;
928         OCDeviceInfo device_info = {0};
929
930         ret = system_settings_get_value_string(SYSTEM_SETTINGS_KEY_DEVICE_NAME, &device_name);
931         if (SYSTEM_SETTINGS_ERROR_NONE != ret) {
932                 ERR("system_settings_get_value_string() Fail(%d)", ret);
933                 return IOTCON_ERROR_SYSTEM;
934         }
935
936         device_info.deviceName = device_name;
937
938         icd_ioty_csdk_lock();
939         ret = OCSetDeviceInfo(device_info);
940         icd_ioty_csdk_unlock();
941
942         if (OC_STACK_OK != ret) {
943                 ERR("OCSetDeviceInfo() Fail(%d)", ret);
944                 free(device_name);
945                 return icd_ioty_convert_error(ret);
946         }
947
948         free(icd_tizen_info.device_name);
949         icd_tizen_info.device_name = device_name;
950
951         return IOTCON_ERROR_NONE;
952 }
953
954 static void _icd_ioty_on_device_name_changed_cb(system_settings_key_e key,
955                 void *user_data)
956 {
957         FN_CALL;
958         int ret;
959
960         ret = _ioty_set_device_info();
961         if (IOTCON_ERROR_NONE != ret) {
962                 ERR("_ioty_set_device_info() Fail(%d)", ret);
963                 return;
964         }
965 }
966
967 int icd_ioty_set_device_info()
968 {
969         int ret;
970
971         ret = system_settings_set_changed_cb(SYSTEM_SETTINGS_KEY_DEVICE_NAME,
972                         _icd_ioty_on_device_name_changed_cb, NULL);
973         if (SYSTEM_SETTINGS_ERROR_NONE != ret) {
974                 ERR("system_settings_set_changed_cb() Fail(%d)", ret);
975                 return IOTCON_ERROR_SYSTEM;
976         }
977
978         ret = _ioty_set_device_info();
979         if (IOTCON_ERROR_NONE != ret) {
980                 ERR("_ioty_set_device_info() Fail(%d)", ret);
981                 return ret;
982         }
983
984         return IOTCON_ERROR_NONE;
985 }
986
987 static void _ioty_free_platform_info(OCPlatformInfo platform_info)
988 {
989         free(platform_info.manufacturerName);
990         free(platform_info.manufacturerUrl);
991         free(platform_info.modelNumber);
992         free(platform_info.dateOfManufacture);
993         free(platform_info.platformVersion);
994         free(platform_info.operatingSystemVersion);
995         free(platform_info.hardwareVersion);
996         free(platform_info.firmwareVersion);
997         free(platform_info.supportUrl);
998         free(platform_info.systemTime);
999 }
1000
1001 int icd_ioty_set_platform_info()
1002 {
1003         int ret;
1004         OCPlatformInfo platform_info = {0};
1005
1006         ret = system_info_get_platform_string(ICD_SYSTEM_INFO_PLATFORM_NAME,
1007                         &platform_info.platformID);
1008         if (SYSTEM_INFO_ERROR_NONE != ret) {
1009                 ERR("system_info_get_platform_string() Fail(%d)", ret);
1010                 _ioty_free_platform_info(platform_info);
1011                 return IOTCON_ERROR_SYSTEM;
1012         }
1013
1014         ret = system_info_get_platform_string(ICD_SYSTEM_INFO_MANUF_NAME,
1015                         &platform_info.manufacturerName);
1016         if (SYSTEM_INFO_ERROR_NONE != ret) {
1017                 ERR("system_info_get_platform_string() Fail(%d)", ret);
1018                 _ioty_free_platform_info(platform_info);
1019                 return IOTCON_ERROR_SYSTEM;
1020         }
1021
1022         ret = system_info_get_platform_string(ICD_SYSTEM_INFO_MODEL_NAME,
1023                         &platform_info.modelNumber);
1024         if (SYSTEM_INFO_ERROR_NONE != ret) {
1025                 ERR("system_info_get_platform_string() Fail(%d)", ret);
1026                 _ioty_free_platform_info(platform_info);
1027                 return IOTCON_ERROR_SYSTEM;
1028         }
1029
1030         ret = system_info_get_platform_string(ICD_SYSTEM_INFO_PLATFORM_VERSION,
1031                         &platform_info.platformVersion);
1032         if (SYSTEM_INFO_ERROR_NONE != ret) {
1033                 ERR("system_info_get_platform_string() Fail(%d)", ret);
1034                 _ioty_free_platform_info(platform_info);
1035                 return IOTCON_ERROR_SYSTEM;
1036         }
1037
1038         ret = system_info_get_platform_string(ICD_SYSTEM_INFO_BUILD_STRING,
1039                         &platform_info.firmwareVersion);
1040         if (SYSTEM_INFO_ERROR_NONE != ret) {
1041                 ERR("system_info_get_platform_string() Fail(%d)", ret);
1042                 _ioty_free_platform_info(platform_info);
1043                 return IOTCON_ERROR_SYSTEM;
1044         }
1045
1046         /* platform_info.manufacturerUrl */
1047         /* platform_info.dateOfManufacture */
1048         /* platform_info.operatingSystemVersion */
1049         /* platform_info.hardwareVersion */
1050         /* platform_info.supportUrl */
1051         /* platform_info.systemTime */
1052
1053         icd_ioty_csdk_lock();
1054         ret = OCSetPlatformInfo(platform_info);
1055         icd_ioty_csdk_unlock();
1056
1057         if (OC_STACK_OK != ret) {
1058                 ERR("OCSetPlatformInfo() Fail(%d)", ret);
1059                 _ioty_free_platform_info(platform_info);
1060                 return icd_ioty_convert_error(ret);
1061         }
1062         _ioty_free_platform_info(platform_info);
1063
1064         return IOTCON_ERROR_NONE;
1065 }
1066
1067 int icd_ioty_set_tizen_info()
1068 {
1069         int result;
1070         OCStackResult ret;
1071         OCResourceHandle handle;
1072         char *tizen_device_id = NULL;
1073
1074         result = _icd_ioty_get_tizen_id(&tizen_device_id);
1075         if (IOTCON_ERROR_NONE != result) {
1076                 ERR("_icd_ioty_get_tizen_id() Fail(%d)", result);
1077                 return result;
1078         }
1079
1080         icd_tizen_info.tizen_device_id = tizen_device_id;
1081         DBG("tizen_device_id : %s", icd_tizen_info.tizen_device_id);
1082
1083         icd_ioty_csdk_lock();
1084         ret = OCCreateResource(&handle,
1085                         ICD_IOTY_TIZEN_INFO_TYPE,
1086                         IC_INTERFACE_DEFAULT,
1087                         ICD_IOTY_TIZEN_INFO_URI,
1088                         icd_ioty_ocprocess_tizen_info_handler,
1089                         NULL,
1090                         OC_EXPLICIT_DISCOVERABLE);
1091         icd_ioty_csdk_unlock();
1092         if (OC_STACK_OK != ret) {
1093                 ERR("OCCreateResource() Fail(%d)", ret);
1094                 return icd_ioty_convert_error(ret);
1095         }
1096
1097         return IOTCON_ERROR_NONE;
1098 }
1099
1100
1101 gboolean icd_ioty_get_tizen_info(icDbus *object, GDBusMethodInvocation *invocation,
1102                 const gchar *host_address, int conn_type)
1103 {
1104         OCStackResult result;
1105         OCDevAddr dev_addr = {0};
1106         OCCallbackData cbdata = {0};
1107         OCConnectivityType oic_conn_type;
1108         char host[PATH_MAX] = {0};
1109         char *dev_host, *ptr = NULL;
1110
1111         snprintf(host, sizeof(host), "%s", host_address);
1112
1113         cbdata.cb = icd_ioty_ocprocess_get_tizen_info_cb;
1114         cbdata.context = invocation;
1115
1116         oic_conn_type = icd_ioty_conn_type_to_oic_conn_type(conn_type);
1117         icd_ioty_conn_type_to_oic_transport_type(conn_type, &dev_addr.adapter,
1118                         &dev_addr.flags);
1119
1120         switch (conn_type) {
1121         case IOTCON_CONNECTIVITY_IPV4:
1122                 dev_host = strtok_r(host, ":", &ptr);
1123                 snprintf(dev_addr.addr, sizeof(dev_addr.addr), "%s", dev_host);
1124                 dev_addr.port = atoi(strtok_r(NULL, ":", &ptr));
1125                 break;
1126         case IOTCON_CONNECTIVITY_IPV6:
1127                 dev_host = strtok_r(host, "]", &ptr);
1128                 snprintf(dev_addr.addr, sizeof(dev_addr.addr), "%s", dev_host);
1129                 dev_addr.port = atoi(strtok_r(NULL, "]", &ptr));
1130                 break;
1131         default:
1132                 ERR("Invalid Connectivitiy Type");
1133                 icd_ioty_complete_error(ICD_TIZEN_INFO, invocation, IOTCON_ERROR_IOTIVITY);
1134                 return TRUE;
1135         }
1136
1137         icd_ioty_csdk_lock();
1138         result = OCDoResource(NULL, OC_REST_GET, ICD_IOTY_TIZEN_INFO_URI, &dev_addr, NULL,
1139                         oic_conn_type, OC_LOW_QOS, &cbdata, NULL, 0);
1140         icd_ioty_csdk_unlock();
1141
1142         if (OC_STACK_OK != result) {
1143                 ERR("OCDoResource() Fail(%d)", result);
1144                 icd_ioty_complete_error(ICD_TIZEN_INFO, invocation, icd_ioty_convert_error(result));
1145                 return TRUE;
1146         }
1147
1148         return TRUE;
1149 }
1150
1151
1152 int icd_ioty_tizen_info_get_property(char **device_name, char **tizen_device_id)
1153 {
1154         RETV_IF(NULL == device_name, IOTCON_ERROR_INVALID_PARAMETER);
1155         RETV_IF(NULL == tizen_device_id, IOTCON_ERROR_INVALID_PARAMETER);
1156
1157         *device_name = icd_tizen_info.device_name;
1158         *tizen_device_id = icd_tizen_info.tizen_device_id;
1159
1160         return IOTCON_ERROR_NONE;
1161 }
1162
1163
1164 OCDoHandle icd_ioty_subscribe_presence(const char *host_address, int conn_type,
1165                 const char *resource_type, unsigned int signal_number, const char *bus_name)
1166 {
1167         int len;
1168         OCDoHandle handle;
1169         OCStackResult result;
1170         icd_sig_ctx_s *context;
1171         char uri[PATH_MAX] = {0};
1172         OCCallbackData cbdata = {0};
1173         OCConnectivityType oic_conn_type;
1174
1175         len = snprintf(uri, sizeof(uri), "%s%s", host_address, OC_RSRVD_PRESENCE_URI);
1176         if (len <= 0 || sizeof(uri) <= len) {
1177                 ERR("snprintf() Fail(%d)", len);
1178                 return NULL;
1179         }
1180
1181         if (IC_STR_EQUAL != strcmp(IC_STR_NULL, resource_type))
1182                 snprintf(uri + len, sizeof(uri) - len, "?rt=%s", resource_type);
1183
1184         context = calloc(1, sizeof(icd_sig_ctx_s));
1185         if (NULL == context) {
1186                 ERR("calloc() Fail(%d)", errno);
1187                 return NULL;
1188         }
1189         context->bus_name = ic_utils_strdup(bus_name);
1190         context->signal_number = signal_number;
1191
1192         cbdata.context = context;
1193         cbdata.cb = icd_ioty_ocprocess_presence_cb;
1194         cbdata.cd = _ioty_free_signal_context;
1195
1196         oic_conn_type = icd_ioty_conn_type_to_oic_conn_type(conn_type);
1197
1198         icd_ioty_csdk_lock();
1199         result = OCDoResource(&handle, OC_REST_PRESENCE, uri, NULL, NULL, oic_conn_type,
1200                         OC_LOW_QOS, &cbdata, NULL, 0);
1201         icd_ioty_csdk_unlock();
1202
1203         if (OC_STACK_OK != result) {
1204                 ERR("OCDoResource() Fail(%d)", result);
1205                 free(context->bus_name);
1206                 free(context);
1207                 return NULL;
1208         }
1209         return handle;
1210 }
1211
1212
1213 int icd_ioty_unsubscribe_presence(OCDoHandle handle)
1214 {
1215         OCStackResult ret;
1216
1217         icd_ioty_csdk_lock();
1218         ret = OCCancel(handle, OC_LOW_QOS, NULL, 0);
1219         icd_ioty_csdk_unlock();
1220         if (OC_STACK_OK != ret) {
1221                 ERR("OCCancel() Fail(%d)", ret);
1222                 return icd_ioty_convert_error(ret);
1223         }
1224
1225         return IOTCON_ERROR_NONE;
1226 }
1227
1228
1229 int icd_ioty_start_presence(unsigned int time_to_live)
1230 {
1231         OCStackResult ret;
1232
1233         icd_ioty_csdk_lock();
1234         ret = OCStartPresence(time_to_live);
1235         icd_ioty_csdk_unlock();
1236         if (OC_STACK_OK != ret) {
1237                 ERR("OCStartPresence() Fail(%d)", ret);
1238                 return icd_ioty_convert_error(ret);
1239         }
1240
1241         return IOTCON_ERROR_NONE;
1242 }
1243
1244
1245 int icd_ioty_stop_presence()
1246 {
1247         OCStackResult ret;
1248
1249         icd_ioty_csdk_lock();
1250         ret = OCStopPresence();
1251         icd_ioty_csdk_unlock();
1252         if (OC_STACK_OK != ret) {
1253                 ERR("OCStopPresence() Fail(%d)", ret);
1254                 return icd_ioty_convert_error(ret);
1255         }
1256
1257         return IOTCON_ERROR_NONE;
1258 }