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