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