(ACR) remove set_device/platform_info API, hide start/stop_presence API
[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, uint8_t 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
511         switch (type) {
512         case ICD_CRUD_GET:
513                 value = g_variant_new("(a(qs)vi)", NULL, NULL, ret_val);
514                 ic_dbus_complete_get(icd_dbus_get_object(), invocation, value);
515                 break;
516         case ICD_CRUD_PUT:
517                 value = g_variant_new("(a(qs)vi)", NULL, NULL, ret_val);
518                 ic_dbus_complete_put(icd_dbus_get_object(), invocation, value);
519                 break;
520         case ICD_CRUD_POST:
521                 value = g_variant_new("(a(qs)vi)", NULL, NULL, ret_val);
522                 ic_dbus_complete_post(icd_dbus_get_object(), invocation, value);
523                 break;
524         case ICD_CRUD_DELETE:
525                 value = g_variant_new("(a(qs)i)", NULL, ret_val);
526                 ic_dbus_complete_delete(icd_dbus_get_object(), invocation, value);
527                 break;
528         case ICD_TIZEN_INFO:
529                 value = g_variant_new("(ssi)", IC_STR_NULL, IC_STR_NULL, ret_val);
530                 ic_dbus_complete_get_tizen_info(icd_dbus_get_object(), invocation, value);
531                 break;
532         }
533 }
534
535
536 static gboolean _icd_ioty_crud(int type, icDbus *object, GDBusMethodInvocation *invocation,
537                 GVariant *resource, GVariant *query, GVariant *repr)
538 {
539         bool is_secure;
540         OCMethod rest_type;
541         OCStackResult result;
542         GVariantIter *options;
543         OCCallbackData cbdata = {0};
544         int conn_type, options_size;
545         char *uri_path, *host, *uri, *dev_host, *ptr = NULL;
546         OCHeaderOption oic_options[MAX_HEADER_OPTIONS];
547         OCHeaderOption *oic_options_ptr = NULL;
548         OCPayload *payload = NULL;
549         OCConnectivityType oic_conn_type;
550         OCDevAddr dev_addr = {0};
551
552         switch (type) {
553         case ICD_CRUD_GET:
554                 cbdata.cb = icd_ioty_ocprocess_get_cb;
555                 rest_type = OC_REST_GET;
556                 break;
557         case ICD_CRUD_PUT:
558                 cbdata.cb = icd_ioty_ocprocess_put_cb;
559                 rest_type = OC_REST_PUT;
560                 break;
561         case ICD_CRUD_POST:
562                 cbdata.cb = icd_ioty_ocprocess_post_cb;
563                 rest_type = OC_REST_POST;
564                 break;
565         case ICD_CRUD_DELETE:
566                 cbdata.cb = icd_ioty_ocprocess_delete_cb;
567                 rest_type = OC_REST_DELETE;
568                 break;
569         default:
570                 ERR("Invalid CRUD Type(%d)", type);
571                 return FALSE;
572         }
573
574         g_variant_get(resource, "(&s&sba(qs)i)", &uri_path, &host, &is_secure, &options,
575                         &conn_type);
576
577         switch (type) {
578         case ICD_CRUD_GET:
579         case ICD_CRUD_PUT:
580         case ICD_CRUD_POST:
581                 uri = _icd_ioty_resource_generate_uri(uri_path, query);
582                 if (NULL == uri) {
583                         ERR("_icd_ioty_resource_generate_uri() Fail");
584                         g_variant_iter_free(options);
585                         icd_ioty_complete_error(type, invocation, IOTCON_ERROR_INVALID_PARAMETER);
586                         return TRUE;
587                 }
588                 break;
589         case ICD_CRUD_DELETE:
590                 uri = strdup(uri_path);
591                 break;
592         }
593
594         cbdata.context = invocation;
595
596         options_size = g_variant_iter_n_children(options);
597         if (0 != options_size) {
598                 int ret = _ioty_get_header_options(options, options_size, oic_options,
599                                 sizeof(oic_options) / sizeof(oic_options[0]));
600                 if (IOTCON_ERROR_NONE != ret) {
601                         ERR("_ioty_get_header_options() Fail(%d)", ret);
602                         free(uri);
603                         g_variant_iter_free(options);
604                         icd_ioty_complete_error(type, invocation, ret);
605                         return TRUE;
606                 }
607                 oic_options_ptr = oic_options;
608         }
609         g_variant_iter_free(options);
610
611         if (repr)
612                 payload = (OCPayload*)icd_payload_representation_from_gvariant(repr);
613
614         oic_conn_type = icd_ioty_conn_type_to_oic_conn_type(conn_type);
615
616         icd_ioty_conn_type_to_oic_transport_type(conn_type, &dev_addr.adapter,
617                         &dev_addr.flags);
618
619         switch (conn_type) {
620         case IOTCON_CONNECTIVITY_IPV4:
621                 dev_host = strtok_r(host, ":", &ptr);
622                 snprintf(dev_addr.addr, sizeof(dev_addr.addr), "%s", dev_host);
623                 dev_addr.port = atoi(strtok_r(NULL, ":", &ptr));
624                 break;
625         case IOTCON_CONNECTIVITY_IPV6:
626                 dev_host = strtok_r(host, "]", &ptr);
627                 snprintf(dev_addr.addr, sizeof(dev_addr.addr), "%s", dev_host);
628                 dev_addr.port = atoi(strtok_r(NULL, "]", &ptr));
629                 break;
630         default:
631                 ERR("Invalid Connectivitiy Type");
632                 icd_ioty_complete_error(type, invocation, IOTCON_ERROR_IOTIVITY);
633                 free(uri);
634                 return TRUE;
635         }
636
637         icd_ioty_csdk_lock();
638         /* TODO : QoS is come from lib. And user can set QoS to client structure.  */
639         result = OCDoResource(NULL, rest_type, uri, &dev_addr, payload, oic_conn_type,
640                         OC_LOW_QOS, &cbdata, oic_options_ptr, options_size);
641         icd_ioty_csdk_unlock();
642
643         free(uri);
644
645         if (OC_STACK_OK != result) {
646                 ERR("OCDoResource() Fail(%d)", result);
647                 icd_ioty_complete_error(type, invocation, icd_ioty_convert_error(result));
648                 return TRUE;
649         }
650
651         return TRUE;
652 }
653
654 gboolean icd_ioty_get(icDbus *object, GDBusMethodInvocation *invocation,
655                 GVariant *resource, GVariant *query)
656 {
657         return _icd_ioty_crud(ICD_CRUD_GET, object, invocation, resource, query, NULL);
658 }
659
660
661 gboolean icd_ioty_put(icDbus *object, GDBusMethodInvocation *invocation,
662                 GVariant *resource, GVariant *repr, GVariant *query)
663 {
664         return _icd_ioty_crud(ICD_CRUD_PUT, object, invocation, resource, query, repr);
665 }
666
667
668 gboolean icd_ioty_post(icDbus *object, GDBusMethodInvocation *invocation,
669                 GVariant *resource, GVariant *repr, GVariant *query)
670 {
671         return _icd_ioty_crud(ICD_CRUD_POST, object, invocation, resource, query, repr);
672 }
673
674
675 gboolean icd_ioty_delete(icDbus *object, GDBusMethodInvocation *invocation,
676                 GVariant *resource)
677 {
678         return _icd_ioty_crud(ICD_CRUD_DELETE, object, invocation, resource, NULL, NULL);
679 }
680
681
682 OCDoHandle icd_ioty_observer_start(GVariant *resource, int observe_type, GVariant *query,
683                 unsigned int signal_number, const char *bus_name)
684 {
685         bool is_secure;
686         OCMethod method;
687         OCDoHandle handle;
688         OCStackResult result;
689         GVariantIter *options;
690         icd_sig_ctx_s *context;
691         OCCallbackData cbdata = {0};
692         int conn_type, options_size;
693         char *uri_path, *host, *uri, *dev_host, *ptr = NULL;
694         OCHeaderOption oic_options[MAX_HEADER_OPTIONS];
695         OCHeaderOption *oic_options_ptr = NULL;
696         OCConnectivityType oic_conn_type;
697         OCDevAddr dev_addr = {0};
698
699         g_variant_get(resource, "(&s&sba(qs)i)", &uri_path, &host, &is_secure, &options,
700                         &conn_type);
701
702         uri = _icd_ioty_resource_generate_uri(uri_path, query);
703         if (NULL == uri) {
704                 ERR("_icd_ioty_resource_generate_uri() Fail");
705                 g_variant_iter_free(options);
706                 return NULL;
707         }
708
709         if (IOTCON_OBSERVE == observe_type)
710                 method = OC_REST_OBSERVE;
711         else if (IOTCON_OBSERVE_ALL == observe_type)
712                 method = OC_REST_OBSERVE_ALL;
713         else
714                 method = OC_REST_OBSERVE_ALL;
715
716         context = calloc(1, sizeof(icd_sig_ctx_s));
717         if (NULL == context) {
718                 ERR("calloc() Fail(%d)", errno);
719                 return NULL;
720         }
721         context->bus_name = ic_utils_strdup(bus_name);
722         context->signum = signal_number;
723
724         cbdata.context = context;
725         cbdata.cb = icd_ioty_ocprocess_observe_cb;
726         cbdata.cd = _ioty_free_signal_context;
727
728         options_size = g_variant_iter_n_children(options);
729         if (0 != options_size) {
730                 int ret = _ioty_get_header_options(options, options_size, oic_options,
731                                 sizeof(oic_options) / sizeof(oic_options[0]));
732                 if (IOTCON_ERROR_NONE != ret) {
733                         ERR("_ioty_get_header_options() Fail(%d)", ret);
734                         free(context->bus_name);
735                         free(context);
736                         free(uri);
737                         g_variant_iter_free(options);
738                         return NULL;
739                 }
740                 oic_options_ptr = oic_options;
741         }
742         g_variant_iter_free(options);
743
744         oic_conn_type = icd_ioty_conn_type_to_oic_conn_type(conn_type);
745
746         icd_ioty_conn_type_to_oic_transport_type(conn_type, &dev_addr.adapter,
747                         &dev_addr.flags);
748
749         switch (conn_type) {
750         case IOTCON_CONNECTIVITY_IPV4:
751                 dev_host = strtok_r(host, ":", &ptr);
752                 snprintf(dev_addr.addr, sizeof(dev_addr.addr), "%s", dev_host);
753                 dev_addr.port = atoi(strtok_r(NULL, ":", &ptr));
754                 break;
755         case IOTCON_CONNECTIVITY_IPV6:
756                 dev_host = strtok_r(host, "]", &ptr);
757                 snprintf(dev_addr.addr, sizeof(dev_addr.addr), "%s", dev_host);
758                 dev_addr.port = atoi(strtok_r(NULL, "]", &ptr));
759                 break;
760         default:
761                 ERR("Invalid Connectivitiy Type");
762                 free(context->bus_name);
763                 free(context);
764                 free(uri);
765                 return NULL;
766         }
767
768         icd_ioty_csdk_lock();
769         /* TODO : QoS is come from lib. And user can set QoS to client structure.  */
770         result = OCDoResource(&handle, method, uri, &dev_addr, NULL, oic_conn_type,
771                         OC_LOW_QOS, &cbdata, oic_options_ptr, options_size);
772         icd_ioty_csdk_unlock();
773         free(uri);
774         if (OC_STACK_OK != result) {
775                 ERR("OCDoResource() Fail(%d)", result);
776                 free(context->bus_name);
777                 free(context);
778                 return NULL;
779         }
780
781         return handle;
782 }
783
784
785 int icd_ioty_observer_stop(OCDoHandle handle, GVariant *options)
786 {
787         int options_size;
788         OCStackResult ret;
789         GVariantIter options_iter;
790         OCHeaderOption oic_options[MAX_HEADER_OPTIONS];
791         OCHeaderOption *oic_options_ptr = NULL;
792
793         g_variant_iter_init(&options_iter, options);
794
795         options_size = g_variant_iter_n_children(&options_iter);
796         if (0 != options_size) {
797                 int ret = _ioty_get_header_options(&options_iter, options_size, oic_options,
798                                 sizeof(oic_options) / sizeof(oic_options[0]));
799                 if (IOTCON_ERROR_NONE != ret) {
800                         ERR("_ioty_get_header_options() Fail(%d)", ret);
801                         return ret;
802                 }
803                 oic_options_ptr = oic_options;
804         }
805
806         icd_ioty_csdk_lock();
807         ret = OCCancel(handle, OC_HIGH_QOS, oic_options_ptr, options_size);
808         icd_ioty_csdk_unlock();
809         if (OC_STACK_OK != ret) {
810                 ERR("OCCancel() Fail(%d)", ret);
811                 return icd_ioty_convert_error(ret);
812         }
813
814         return IOTCON_ERROR_NONE;
815 }
816
817
818 int icd_ioty_register_device_info(char *device_name)
819 {
820         OCStackResult result;
821         OCDeviceInfo device_info = {0};
822
823         RETV_IF(NULL == device_name, IOTCON_ERROR_INVALID_PARAMETER);
824
825         device_info.deviceName = device_name;
826
827         icd_ioty_csdk_lock();
828         result = OCSetDeviceInfo(device_info);
829         icd_ioty_csdk_unlock();
830
831         if (OC_STACK_OK != result) {
832                 ERR("OCSetDeviceInfo() Fail(%d)", result);
833                 return icd_ioty_convert_error(result);
834         }
835
836         icd_tizen_info.device_name = strdup(device_name);
837
838         return IOTCON_ERROR_NONE;
839 }
840
841
842 int icd_ioty_register_platform_info(char *platform_id,
843                 char *manufacturer_name,
844                 char *manufacturer_url,
845                 char *model_number,
846                 char *date_of_manufacture,
847                 char *platform_version,
848                 char *os_version,
849                 char *hw_version,
850                 char *firmware_version,
851                 char *support_url,
852                 char *system_time)
853 {
854         OCStackResult result;
855         OCPlatformInfo platform_info = {0};
856
857         platform_info.platformID = platform_id;
858         platform_info.manufacturerName = manufacturer_name;
859         platform_info.manufacturerUrl = manufacturer_url;
860         platform_info.modelNumber = model_number;
861         platform_info.dateOfManufacture = date_of_manufacture;
862         platform_info.platformVersion = platform_version;
863         platform_info.operatingSystemVersion = os_version;
864         platform_info.hardwareVersion = hw_version;
865         platform_info.firmwareVersion = firmware_version;
866         platform_info.supportUrl = support_url;
867         platform_info.systemTime = system_time;
868
869         icd_ioty_csdk_lock();
870         result = OCSetPlatformInfo(platform_info);
871         icd_ioty_csdk_unlock();
872
873         if (OC_STACK_OK != result) {
874                 ERR("OCSetPlatformInfo() Fail(%d)", result);
875                 return icd_ioty_convert_error(result);
876         }
877
878         return IOTCON_ERROR_NONE;
879 }
880
881
882 int icd_ioty_get_info(int type, const char *host_address, unsigned int signal_number,
883                 const char *bus_name)
884 {
885         OCStackResult result;
886         icd_sig_ctx_s *context;
887         OCCallbackData cbdata = {0};
888         char uri[PATH_MAX] = {0};
889         char *uri_path = NULL;
890         iotcon_connectivity_type_e conn_type = IOTCON_CONNECTIVITY_IPV4;
891         OCConnectivityType oic_conn_type;
892
893         if (ICD_DEVICE_INFO == type)
894                 uri_path = OC_RSRVD_DEVICE_URI;
895         else if (ICD_PLATFORM_INFO == type)
896                 uri_path = OC_RSRVD_PLATFORM_URI;
897         else
898                 return IOTCON_ERROR_INVALID_PARAMETER;
899
900         if (IC_STR_EQUAL == strcmp(IOTCON_MULTICAST_ADDRESS, host_address))
901                 snprintf(uri, sizeof(uri), "%s", uri_path);
902         else
903                 snprintf(uri, sizeof(uri), "%s%s", host_address, uri_path);
904
905         context = calloc(1, sizeof(icd_sig_ctx_s));
906         if (NULL == context) {
907                 ERR("calloc() Fail(%d)", errno);
908                 return IOTCON_ERROR_OUT_OF_MEMORY;
909         }
910         context->bus_name = ic_utils_strdup(bus_name);
911         context->signum = signal_number;
912
913         cbdata.context = context;
914         cbdata.cb = icd_ioty_ocprocess_info_cb;
915         cbdata.cd = _ioty_free_signal_context;
916
917         oic_conn_type = icd_ioty_conn_type_to_oic_conn_type(conn_type);
918
919         icd_ioty_csdk_lock();
920         /* TODO : QoS is come from lib. And user can set QoS to client structure.  */
921         result = OCDoResource(NULL, OC_REST_DISCOVER, uri, NULL, NULL, oic_conn_type,
922                         OC_LOW_QOS, &cbdata, NULL, 0);
923         icd_ioty_csdk_unlock();
924
925         if (OC_STACK_OK != result) {
926                 ERR("OCDoResource() Fail(%d)", result);
927                 free(context->bus_name);
928                 free(context);
929                 return icd_ioty_convert_error(result);
930         }
931
932         return IOTCON_ERROR_NONE;
933 }
934
935 static int _icd_ioty_get_tizen_id(char **tizen_device_id)
936 {
937         int ret;
938         char *tizen_id = NULL;
939
940         ret = system_info_get_platform_string(ICD_SYSTEM_INFO_TIZEN_ID, &tizen_id);
941         if (SYSTEM_INFO_ERROR_NONE != ret) {
942                 ERR("system_info_get_platform_string() Fail(%d)", ret);
943                 return IOTCON_ERROR_SYSTEM;
944         }
945         *tizen_device_id = tizen_id;
946
947         return IOTCON_ERROR_NONE;
948 }
949
950
951 int icd_ioty_set_tizen_info()
952 {
953         int result;
954         OCStackResult ret;
955         OCResourceHandle handle;
956         char *tizen_device_id = NULL;
957
958         result = _icd_ioty_get_tizen_id(&tizen_device_id);
959         if (IOTCON_ERROR_NONE != result) {
960                 ERR("_icd_ioty_get_tizen_id() Fail(%d)", result);
961                 return result;
962         }
963
964         icd_tizen_info.tizen_device_id = tizen_device_id;
965         DBG("tizen_device_id : %s", icd_tizen_info.tizen_device_id);
966
967         icd_ioty_csdk_lock();
968         ret = OCCreateResource(&handle,
969                         ICD_IOTY_TIZEN_INFO_TYPE,
970                         IC_INTERFACE_DEFAULT,
971                         ICD_IOTY_TIZEN_INFO_URI,
972                         icd_ioty_ocprocess_tizen_info_handler,
973                         NULL,
974                         OC_RES_PROP_NONE);
975         icd_ioty_csdk_unlock();
976         if (OC_STACK_OK != ret) {
977                 ERR("OCCreateResource() Fail(%d)", ret);
978                 return icd_ioty_convert_error(ret);
979         }
980
981         return IOTCON_ERROR_NONE;
982 }
983
984
985 gboolean icd_ioty_get_tizen_info(icDbus *object, GDBusMethodInvocation *invocation,
986                 const gchar *host_address)
987 {
988         OCStackResult result;
989         OCDevAddr dev_addr = {0};
990         OCCallbackData cbdata = {0};
991         OCConnectivityType oic_conn_type;
992         char host[PATH_MAX] = {0};
993         char *dev_host, *ptr = NULL;
994         int conn_type = IOTCON_CONNECTIVITY_IPV4;
995
996         snprintf(host, sizeof(host), "%s", host_address);
997
998         cbdata.cb = icd_ioty_ocprocess_get_tizen_info_cb;
999         cbdata.context = invocation;
1000
1001         oic_conn_type = icd_ioty_conn_type_to_oic_conn_type(conn_type);
1002         icd_ioty_conn_type_to_oic_transport_type(conn_type, &dev_addr.adapter,
1003                         &dev_addr.flags);
1004
1005         switch (conn_type) {
1006         case IOTCON_CONNECTIVITY_IPV4:
1007                 dev_host = strtok_r(host, ":", &ptr);
1008                 snprintf(dev_addr.addr, sizeof(dev_addr.addr), "%s", dev_host);
1009                 dev_addr.port = atoi(strtok_r(NULL, ":", &ptr));
1010                 break;
1011         case IOTCON_CONNECTIVITY_IPV6:
1012                 dev_host = strtok_r(host, "]", &ptr);
1013                 snprintf(dev_addr.addr, sizeof(dev_addr.addr), "%s", dev_host);
1014                 dev_addr.port = atoi(strtok_r(NULL, "]", &ptr));
1015                 break;
1016         default:
1017                 ERR("Invalid Connectivitiy Type");
1018                 icd_ioty_complete_error(ICD_TIZEN_INFO, invocation, IOTCON_ERROR_IOTIVITY);
1019                 return TRUE;
1020         }
1021
1022         icd_ioty_csdk_lock();
1023         result = OCDoResource(NULL, OC_REST_GET, ICD_IOTY_TIZEN_INFO_URI, &dev_addr, NULL,
1024                         oic_conn_type, OC_LOW_QOS, &cbdata, NULL, 0);
1025         icd_ioty_csdk_unlock();
1026
1027         if (OC_STACK_OK != result) {
1028                 ERR("OCDoResource() Fail(%d)", result);
1029                 icd_ioty_complete_error(ICD_TIZEN_INFO, invocation, icd_ioty_convert_error(result));
1030                 return TRUE;
1031         }
1032
1033         return TRUE;
1034 }
1035
1036
1037 int icd_ioty_tizen_info_get_property(char **device_name, char **tizen_device_id)
1038 {
1039         RETV_IF(NULL == device_name, IOTCON_ERROR_INVALID_PARAMETER);
1040         RETV_IF(NULL == tizen_device_id, IOTCON_ERROR_INVALID_PARAMETER);
1041
1042         *device_name = icd_tizen_info.device_name;
1043         *tizen_device_id = icd_tizen_info.tizen_device_id;
1044
1045         return IOTCON_ERROR_NONE;
1046 }
1047
1048
1049 OCDoHandle icd_ioty_subscribe_presence(const char *host_address,
1050                 const char *resource_type, unsigned int signal_number, const char *bus_name)
1051 {
1052         int len;
1053         OCDoHandle handle;
1054         OCStackResult result;
1055         char uri[PATH_MAX] = {0};
1056         OCCallbackData cbdata = {0};
1057         icd_sig_ctx_s *context;
1058
1059         len = snprintf(uri, sizeof(uri), "%s%s", host_address, OC_RSRVD_PRESENCE_URI);
1060         if (len <= 0 || sizeof(uri) <= len) {
1061                 ERR("snprintf() Fail(%d)", len);
1062                 return NULL;
1063         }
1064
1065         if (IC_STR_EQUAL != strcmp(IC_STR_NULL, resource_type))
1066                 snprintf(uri + len, sizeof(uri) - len, "?rt=%s", resource_type);
1067
1068         context = calloc(1, sizeof(icd_sig_ctx_s));
1069         if (NULL == context) {
1070                 ERR("calloc() Fail(%d)", errno);
1071                 return NULL;
1072         }
1073         context->bus_name = ic_utils_strdup(bus_name);
1074         context->signum = signal_number;
1075
1076         cbdata.context = context;
1077         cbdata.cb = icd_ioty_ocprocess_presence_cb;
1078         cbdata.cd = _ioty_free_signal_context;
1079
1080         /* In case of IPV4 or IPV6, connectivity type is CT_ADAPTER_IP in iotivity 0.9.2 */
1081         icd_ioty_csdk_lock();
1082         result = OCDoResource(&handle, OC_REST_PRESENCE, uri, NULL, NULL, CT_ADAPTER_IP,
1083                         OC_LOW_QOS, &cbdata, NULL, 0);
1084         icd_ioty_csdk_unlock();
1085
1086         if (OC_STACK_OK != result) {
1087                 ERR("OCDoResource() Fail(%d)", result);
1088                 free(context->bus_name);
1089                 free(context);
1090                 return NULL;
1091         }
1092         return handle;
1093 }
1094
1095
1096 int icd_ioty_unsubscribe_presence(OCDoHandle handle)
1097 {
1098         OCStackResult ret;
1099
1100         icd_ioty_csdk_lock();
1101         ret = OCCancel(handle, OC_LOW_QOS, NULL, 0);
1102         icd_ioty_csdk_unlock();
1103         if (OC_STACK_OK != ret) {
1104                 ERR("OCCancel() Fail(%d)", ret);
1105                 return icd_ioty_convert_error(ret);
1106         }
1107
1108         return IOTCON_ERROR_NONE;
1109 }
1110
1111
1112 int icd_ioty_start_presence(unsigned int time_to_live)
1113 {
1114         OCStackResult ret;
1115
1116         icd_ioty_csdk_lock();
1117         ret = OCStartPresence(time_to_live);
1118         icd_ioty_csdk_unlock();
1119         if (OC_STACK_OK != ret) {
1120                 ERR("OCStartPresence() Fail(%d)", ret);
1121                 return icd_ioty_convert_error(ret);
1122         }
1123
1124         return IOTCON_ERROR_NONE;
1125 }
1126
1127
1128 int icd_ioty_stop_presence()
1129 {
1130         OCStackResult ret;
1131
1132         icd_ioty_csdk_lock();
1133         ret = OCStopPresence();
1134         icd_ioty_csdk_unlock();
1135         if (OC_STACK_OK != ret) {
1136                 ERR("OCStopPresence() Fail(%d)", ret);
1137                 return icd_ioty_convert_error(ret);
1138         }
1139
1140         return IOTCON_ERROR_NONE;
1141 }