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