2 * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 #include <ocpayload.h>
29 #include "icd-payload.h"
31 union icd_state_value_u {
37 struct icd_state_list_s {
38 OCRepPayloadPropType type;
39 size_t dimensions[MAX_REP_ARRAY_DEPTH];
43 static GVariant* _icd_payload_representation_to_gvariant(OCRepPayload *repr, gboolean is_parent);
45 GVariant** icd_payload_res_to_gvariant(OCPayload *payload, OCDevAddr *dev_addr)
51 iotcon_interface_e iface;
52 GVariantBuilder types;
53 OCRandomUuidResult random_res;
54 OCDiscoveryPayload *discovered;
55 struct OCResourcePayload *resource;
56 int i, is_observable, ret, res_count;
57 char device_id[UUID_STRING_SIZE] = {0};
59 discovered = (OCDiscoveryPayload*)payload;
60 resource = discovered->resources;
62 res_count = OCDiscoveryPayloadGetResourceCount(discovered);
64 value = calloc(res_count, sizeof(GVariant*));
66 ERR("calloc() Fail(%d)", errno);
69 for (i = 0; resource; i++) {
71 if (NULL == resource->uri) {
72 ERR("resource uri is NULL");
73 resource = resource->next;
77 random_res = OCConvertUuidToString(resource->sid, device_id);
78 if (RAND_UUID_OK != random_res) {
79 ERR("OCConvertUuidToString() Fail(%d)", random_res);
80 resource = resource->next;
84 g_variant_builder_init(&types, G_VARIANT_TYPE("as"));
85 node = resource->types;
87 ERR("resource types is NULL");
88 resource = resource->next;
91 g_variant_builder_add(&types, "s", node->value);
95 /* Resource Interfaces */
96 node = resource->interfaces;
98 ERR("resource interfaces is NULL");
99 resource = resource->next;
102 ret = ic_utils_convert_interface_string(node->value, &iface);
103 if (IOTCON_ERROR_NONE != ret) {
104 ERR("ic_utils_convert_interface_string() Fail(%d)", ret);
105 resource = resource->next;
113 is_observable = resource->bitmap & OC_OBSERVABLE;
116 port = (resource->port)? resource->port:dev_addr->port;
118 value[i] = g_variant_new("(ssiasibsi)", resource->uri, device_id, ifaces, &types,
119 is_observable, resource->secure, dev_addr->addr, port);
120 DBG("found resource[%d] : %s", i, g_variant_print(value[i], FALSE));
122 resource = resource->next;
129 static GVariant* _icd_state_array_attr_to_gvariant(OCRepPayloadValueArray *arr, int len,
134 GVariantBuilder builder;
136 g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY);
140 for (i = 0; i < len; i++)
141 g_variant_builder_add(&builder, "i", arr->iArray[index + i]);
143 case OCREP_PROP_BOOL:
144 for (i = 0; i < len; i++)
145 g_variant_builder_add(&builder, "b", arr->bArray[index + i]);
147 case OCREP_PROP_DOUBLE:
148 for (i = 0; i < len; i++)
149 g_variant_builder_add(&builder, "d", arr->dArray[index + i]);
151 case OCREP_PROP_STRING:
152 for (i = 0; i < len; i++)
153 g_variant_builder_add(&builder, "s", arr->strArray[index + i]);
155 case OCREP_PROP_NULL:
156 for (i = 0; i < len; i++)
157 g_variant_builder_add(&builder, "s", IC_STR_NULL);
159 case OCREP_PROP_OBJECT:
160 for (i = 0; i < len; i++) {
161 var = _icd_payload_representation_to_gvariant(arr->objArray[index + i], TRUE);
162 g_variant_builder_add(&builder, "v", var);
165 case OCREP_PROP_ARRAY:
170 return g_variant_builder_end(&builder);
174 static GVariant* _icd_state_array_to_gvariant(OCRepPayloadValueArray *arr,
175 int current_depth, int current_len, int index)
178 GVariantBuilder builder;
179 GVariant *arr_var = NULL;
181 if ((MAX_REP_ARRAY_DEPTH - 1) == current_depth
182 || 0 == arr->dimensions[current_depth + 1])
183 return _icd_state_array_attr_to_gvariant(arr, current_len, index);
185 i = current_len + index;
187 next_len = current_len / arr->dimensions[current_depth];
190 g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY);
192 while ((index += next_len) < i) {
193 arr_var = _icd_state_array_to_gvariant(arr, current_depth + 1, next_len, index);
194 g_variant_builder_add(&builder, "v", arr_var);
197 return g_variant_builder_end(&builder);
201 static GVariantBuilder* _icd_state_value_to_gvariant(OCRepPayload *repr)
204 GVariant *var = NULL;
205 GVariantBuilder *builder;
206 OCRepPayloadValue *val = repr->values;
208 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
213 var = g_variant_new_int32(val->i);
215 case OCREP_PROP_BOOL:
216 var = g_variant_new_boolean(val->b);
218 case OCREP_PROP_DOUBLE:
219 var = g_variant_new_double(val->d);
221 case OCREP_PROP_STRING:
222 var = g_variant_new_string(val->str);
224 case OCREP_PROP_NULL:
225 var = g_variant_new_string(IC_STR_NULL);
227 case OCREP_PROP_ARRAY:
228 total_len = calcDimTotal(val->arr.dimensions);
229 var = _icd_state_array_to_gvariant(&(val->arr), 0, total_len, 0);
231 case OCREP_PROP_OBJECT:
232 var = _icd_payload_representation_to_gvariant(val->obj, TRUE);
238 g_variant_builder_add(builder, "{sv}", val->name, var);
248 static GVariant* _icd_payload_representation_to_gvariant(OCRepPayload *repr,
253 GVariant *child, *value;
254 OCRepPayload *child_node;
255 iotcon_interface_e iface;
256 GVariantBuilder *repr_gvar;
257 GVariantBuilder children, types_builder;
259 RETV_IF(NULL == repr, NULL);
262 g_variant_builder_init(&types_builder, G_VARIANT_TYPE("as"));
266 g_variant_builder_add(&types_builder, "s", node->value);
270 /* Resource Interfaces */
271 node = repr->interfaces;
273 ret = ic_utils_convert_interface_string(node->value, &iface);
274 if (IOTCON_ERROR_NONE != ret) {
275 ERR("ic_utils_convert_interface_string() Fail(%d)", ret);
284 repr_gvar = _icd_state_value_to_gvariant(repr);
287 g_variant_builder_init(&children, G_VARIANT_TYPE("av"));
289 child_node = repr->next;
290 while (is_parent && child_node) {
291 /* generate recursively */
292 child = _icd_payload_representation_to_gvariant(child_node, FALSE);
293 g_variant_builder_add(&children, "v", child);
294 child_node = child_node->next;
297 value = g_variant_new("(siasa{sv}av)", ic_utils_dbus_encode_str(repr->uri), ifaces,
298 &types_builder, repr_gvar, &children);
304 GVariant* icd_payload_representation_empty_gvariant(void)
307 GVariantBuilder types, repr, children;
309 g_variant_builder_init(&types, G_VARIANT_TYPE("as"));
310 g_variant_builder_init(&repr, G_VARIANT_TYPE("a{sv}"));
311 g_variant_builder_init(&children, G_VARIANT_TYPE("av"));
313 value = g_variant_new("(siasa{sv}av)", IC_STR_NULL, 0, &types, &repr, &children);
319 static GVariant* _icd_payload_platform_to_gvariant(OCPlatformPayload *repr)
323 value = g_variant_new("(ssssssssssss)",
325 repr->info.platformID,
326 repr->info.manufacturerName,
327 ic_utils_dbus_encode_str(repr->info.manufacturerUrl),
328 ic_utils_dbus_encode_str(repr->info.modelNumber),
329 ic_utils_dbus_encode_str(repr->info.dateOfManufacture),
330 ic_utils_dbus_encode_str(repr->info.platformVersion),
331 ic_utils_dbus_encode_str(repr->info.operatingSystemVersion),
332 ic_utils_dbus_encode_str(repr->info.hardwareVersion),
333 ic_utils_dbus_encode_str(repr->info.firmwareVersion),
334 ic_utils_dbus_encode_str(repr->info.supportUrl),
335 ic_utils_dbus_encode_str(repr->info.systemTime));
341 static GVariant* _icd_payload_device_to_gvariant(OCDevicePayload *repr)
344 OCRandomUuidResult random_res;
345 char device_id[UUID_STRING_SIZE] = {0};
347 random_res = OCConvertUuidToString(repr->sid, device_id);
348 if (RAND_UUID_OK != random_res) {
349 ERR("OCConvertUuidToString() Fail(%d)", random_res);
353 value = g_variant_new("(sssss)", repr->uri, repr->deviceName, repr->specVersion,
354 device_id, repr->dataModelVersion);
360 GVariant* icd_payload_to_gvariant(OCPayload *repr)
362 GVariant *value = NULL;
367 switch (repr->type) {
368 case PAYLOAD_TYPE_REPRESENTATION:
369 value = _icd_payload_representation_to_gvariant((OCRepPayload*)repr, TRUE);
371 case PAYLOAD_TYPE_PLATFORM:
372 value = _icd_payload_platform_to_gvariant((OCPlatformPayload*)repr);
374 case PAYLOAD_TYPE_DEVICE:
375 value = _icd_payload_device_to_gvariant((OCDevicePayload*)repr);
377 case PAYLOAD_TYPE_PRESENCE:
378 case PAYLOAD_TYPE_SECURITY:
387 static void _icd_state_list_from_gvariant(GVariant *var,
388 struct icd_state_list_s *value_list, int depth)
391 const GVariantType *type;
392 union icd_state_value_u *value;
394 type = g_variant_get_type(var);
396 g_variant_iter_init(&iter, var);
398 value_list->dimensions[depth] = g_variant_iter_n_children(&iter);
399 DBG("[%d]list dim : %d", depth, value_list->dimensions[depth]);
401 if (g_variant_type_equal(G_VARIANT_TYPE("ab"), type)) {
403 value_list->type = OCREP_PROP_BOOL;
404 while (g_variant_iter_loop(&iter, "b", &b)) {
405 value = calloc(1, sizeof(union icd_state_value_u));
407 ERR("calloc() Fail(%d)", errno);
411 value_list->list = g_list_append(value_list->list, value);
413 } else if (g_variant_type_equal(G_VARIANT_TYPE("ai"), type)) {
415 value_list->type = OCREP_PROP_INT;
416 while (g_variant_iter_loop(&iter, "i", &i)) {
417 value = calloc(1, sizeof(union icd_state_value_u));
419 ERR("calloc() Fail(%d)", errno);
423 value_list->list = g_list_append(value_list->list, value);
425 } else if (g_variant_type_equal(G_VARIANT_TYPE("ad"), type)) {
427 value_list->type = OCREP_PROP_DOUBLE;
428 while (g_variant_iter_loop(&iter, "d", &d)) {
429 value = calloc(1, sizeof(union icd_state_value_u));
431 ERR("calloc() Fail(%d)", errno);
435 value_list->list = g_list_append(value_list->list, value);
437 } else if (g_variant_type_equal(G_VARIANT_TYPE("as"), type)) {
439 value_list->type = OCREP_PROP_STRING;
440 while (g_variant_iter_next(&iter, "s", &s))
441 value_list->list = g_list_append(value_list->list, s);
442 } else if (g_variant_type_equal(G_VARIANT_TYPE("av"), type)) {
445 if (g_variant_iter_loop(&iter, "v", &value)) {
446 if (g_variant_is_of_type(value, G_VARIANT_TYPE("(siasa{sv}av)"))) {
447 OCRepPayload *repr_value;
448 value_list->type = OCREP_PROP_OBJECT;
450 repr_value = icd_payload_representation_from_gvariant(value);
451 value_list->list = g_list_append(value_list->list, repr_value);
453 } while (g_variant_iter_loop(&iter, "v", &value));
455 } else if (g_variant_is_of_type(value, G_VARIANT_TYPE_ARRAY)) {
457 _icd_state_list_from_gvariant(value, value_list, depth + 1);
458 } while (g_variant_iter_loop(&iter, "v", &value));
467 static void _icd_state_list_free(gpointer node)
469 OCRepPayloadDestroy(node);
473 static void _icd_state_array_from_list(OCRepPayload *repr,
474 struct icd_state_list_s *value_list, const char *key)
482 union icd_state_value_u *value;
483 struct OCRepPayload **state_arr;
485 len = calcDimTotal(value_list->dimensions);
487 switch (value_list->type) {
489 i_arr = calloc(len, sizeof(int64_t));
491 ERR("calloc() Fail(%d)", errno);
494 for (node = value_list->list, i = 0; node; node = node->next, i++) {
498 g_list_free_full(value_list->list, free);
499 OCRepPayloadSetIntArrayAsOwner(repr, key, i_arr, value_list->dimensions);
501 case OCREP_PROP_BOOL:
502 b_arr = calloc(len, sizeof(bool));
504 ERR("calloc() Fail(%d)", errno);
507 for (node = value_list->list, i = 0; node; node = node->next, i++) {
511 g_list_free_full(value_list->list, free);
512 OCRepPayloadSetBoolArrayAsOwner(repr, key, b_arr, value_list->dimensions);
514 case OCREP_PROP_DOUBLE:
515 d_arr = calloc(len, sizeof(double));
517 ERR("calloc() Fail(%d)", errno);
520 for (node = value_list->list, i = 0; node; node = node->next, i++) {
524 g_list_free_full(value_list->list, free);
525 OCRepPayloadSetDoubleArrayAsOwner(repr, key, d_arr, value_list->dimensions);
527 case OCREP_PROP_STRING:
528 str_arr = calloc(len, sizeof(char *));
529 if (NULL == str_arr) {
530 ERR("calloc() Fail(%d)", errno);
533 for (node = value_list->list, i = 0; node; node = node->next, i++)
534 str_arr[i] = strdup(node->data);
535 g_list_free_full(value_list->list, free);
536 OCRepPayloadSetStringArrayAsOwner(repr, key, str_arr, value_list->dimensions);
538 case OCREP_PROP_OBJECT:
539 state_arr = calloc(len, sizeof(struct OCRepPayload *));
540 if (NULL == state_arr) {
541 ERR("calloc() Fail(%d)", errno);
544 for (node = value_list->list, i = 0; node; node = node->next, i++)
545 state_arr[i] = OCRepPayloadClone(node->data);
546 g_list_free_full(value_list->list, _icd_state_list_free);
547 OCRepPayloadSetPropObjectArrayAsOwner(repr, key, state_arr,
548 value_list->dimensions);
550 case OCREP_PROP_ARRAY:
551 case OCREP_PROP_NULL:
558 static void _icd_state_value_from_gvariant(OCRepPayload *repr, GVariantIter *iter)
562 const char *str_value;
563 OCRepPayload *repr_value;
564 struct icd_state_list_s value_list = {0};
566 while (g_variant_iter_loop(iter, "{sv}", &key, &var)) {
568 if (g_variant_is_of_type(var, G_VARIANT_TYPE_BOOLEAN)) {
569 OCRepPayloadSetPropBool(repr, key, g_variant_get_boolean(var));
571 } else if (g_variant_is_of_type(var, G_VARIANT_TYPE_INT32)) {
572 OCRepPayloadSetPropInt(repr, key, g_variant_get_int32(var));
574 } else if (g_variant_is_of_type(var, G_VARIANT_TYPE_DOUBLE)) {
575 OCRepPayloadSetPropDouble(repr, key, g_variant_get_double(var));
577 } else if (g_variant_is_of_type(var, G_VARIANT_TYPE_STRING)) {
578 str_value = g_variant_get_string(var, NULL);
579 if (IC_STR_EQUAL == strcmp(IC_STR_NULL, str_value))
580 OCRepPayloadSetNull(repr, key);
582 OCRepPayloadSetPropString(repr, key, str_value);
584 } else if (g_variant_is_of_type(var, G_VARIANT_TYPE_ARRAY)) {
585 memset(&value_list, 0, sizeof(struct icd_state_list_s));
586 _icd_state_list_from_gvariant(var, &value_list, 0);
587 _icd_state_array_from_list(repr, &value_list, key);
589 } else if (g_variant_is_of_type(var, G_VARIANT_TYPE("(siasa{sv}av)"))) {
590 repr_value = icd_payload_representation_from_gvariant(var);
591 OCRepPayloadSetPropObjectAsOwner(repr, key, repr_value);
599 OCRepPayload* icd_payload_representation_from_gvariant(GVariant *var)
602 int ret, i, ifaces = 0;
603 OCRepPayload *repr, *cur;
604 char *uri_path, *iface_str, *resource_type;
605 GVariantIter *resource_types, *repr_gvar, *children;
607 repr = OCRepPayloadCreate();
609 g_variant_get(var, "(&siasa{sv}av)", &uri_path, &ifaces, &resource_types, &repr_gvar,
612 if (IC_STR_EQUAL != strcmp(IC_STR_NULL, uri_path))
613 OCRepPayloadSetUri(repr, uri_path);
615 for (i = 1; i <= IC_INTERFACE_MAX; i = i << 1) {
616 if (IOTCON_INTERFACE_NONE == (ifaces & i)) /* this interface not exist */
618 ret = ic_utils_convert_interface_flag((ifaces & i), &iface_str);
619 if (IOTCON_ERROR_NONE != ret) {
620 ERR("ic_utils_convert_interface_flag(%d) Fail(%d)", i, ret);
621 OCRepPayloadDestroy(repr);
624 OCRepPayloadAddInterface(repr, iface_str);
626 while (g_variant_iter_loop(resource_types, "s", &resource_type))
627 OCRepPayloadAddResourceType(repr, resource_type);
629 _icd_state_value_from_gvariant(repr, repr_gvar);
632 while (g_variant_iter_loop(children, "v", &child)) {
633 cur->next = icd_payload_representation_from_gvariant(child);