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