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