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