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, gboolean is_parent)
252 GVariant *child, *value;
253 OCRepPayload *child_node;
254 iotcon_interface_e iface;
255 GVariantBuilder *repr_gvar;
256 GVariantBuilder children, types_builder;
258 RETV_IF(NULL == repr, NULL);
261 g_variant_builder_init(&types_builder, G_VARIANT_TYPE("as"));
265 g_variant_builder_add(&types_builder, "s", node->value);
269 /* Resource Interfaces */
270 node = repr->interfaces;
272 ret = ic_utils_convert_interface_string(node->value, &iface);
273 if (IOTCON_ERROR_NONE != ret) {
274 ERR("ic_utils_convert_interface_string() Fail(%d)", ret);
283 repr_gvar = _icd_state_value_to_gvariant(repr);
286 g_variant_builder_init(&children, G_VARIANT_TYPE("av"));
288 child_node = repr->next;
289 while (is_parent && child_node) {
290 /* generate recursively */
291 child = _icd_payload_representation_to_gvariant(child_node, FALSE);
292 g_variant_builder_add(&children, "v", child);
293 child_node = child_node->next;
296 value = g_variant_new("(siasa{sv}av)", ic_utils_dbus_encode_str(repr->uri), ifaces,
297 &types_builder, repr_gvar, &children);
303 static GVariant* _icd_payload_platform_to_gvariant(OCPlatformPayload *repr)
307 value = g_variant_new("(ssssssssssss)",
309 repr->info.platformID,
310 repr->info.manufacturerName,
311 repr->info.manufacturerUrl,
312 repr->info.modelNumber,
313 repr->info.dateOfManufacture,
314 repr->info.platformVersion,
315 repr->info.operatingSystemVersion,
316 repr->info.hardwareVersion,
317 repr->info.firmwareVersion,
318 repr->info.supportUrl,
319 repr->info.systemTime);
325 static GVariant* _icd_payload_device_to_gvariant(OCDevicePayload *repr)
328 OCRandomUuidResult random_res;
329 char device_id[UUID_STRING_SIZE] = {0};
331 random_res = OCConvertUuidToString(repr->sid, device_id);
332 if (RAND_UUID_OK != random_res) {
333 ERR("OCConvertUuidToString() Fail(%d)", random_res);
337 value = g_variant_new("(sssss)", repr->uri, repr->deviceName, repr->specVersion,
338 device_id, repr->dataModelVersion);
344 GVariant* icd_payload_to_gvariant(OCPayload *repr)
346 GVariant *value = NULL;
351 switch (repr->type) {
352 case PAYLOAD_TYPE_REPRESENTATION:
353 value = _icd_payload_representation_to_gvariant((OCRepPayload*)repr, TRUE);
355 case PAYLOAD_TYPE_PLATFORM:
356 value = _icd_payload_platform_to_gvariant((OCPlatformPayload*)repr);
358 case PAYLOAD_TYPE_DEVICE:
359 value = _icd_payload_device_to_gvariant((OCDevicePayload*)repr);
361 case PAYLOAD_TYPE_PRESENCE:
362 case PAYLOAD_TYPE_SECURITY:
371 static void _icd_state_list_from_gvariant(GVariant *var,
372 struct icd_state_list_s *value_list, int depth)
375 const GVariantType *type;
376 union icd_state_value_u *value;
378 type = g_variant_get_type(var);
380 g_variant_iter_init(&iter, var);
382 value_list->dimensions[depth] = g_variant_iter_n_children(&iter);
383 DBG("[%d]list dim : %d", depth, value_list->dimensions[depth]);
385 if (g_variant_type_equal(G_VARIANT_TYPE("ab"), type)) {
387 value_list->type = OCREP_PROP_BOOL;
388 while (g_variant_iter_loop(&iter, "b", &b)) {
389 value = calloc(1, sizeof(union icd_state_value_u));
391 ERR("calloc() Fail(%d)", errno);
395 value_list->list = g_list_append(value_list->list, value);
397 } else if (g_variant_type_equal(G_VARIANT_TYPE("ai"), type)) {
399 value_list->type = OCREP_PROP_INT;
400 while (g_variant_iter_loop(&iter, "i", &i)) {
401 value = calloc(1, sizeof(union icd_state_value_u));
403 ERR("calloc() Fail(%d)", errno);
407 value_list->list = g_list_append(value_list->list, value);
409 } else if (g_variant_type_equal(G_VARIANT_TYPE("ad"), type)) {
411 value_list->type = OCREP_PROP_DOUBLE;
412 while (g_variant_iter_loop(&iter, "d", &d)) {
413 value = calloc(1, sizeof(union icd_state_value_u));
415 ERR("calloc() Fail(%d)", errno);
419 value_list->list = g_list_append(value_list->list, value);
421 } else if (g_variant_type_equal(G_VARIANT_TYPE("as"), type)) {
423 value_list->type = OCREP_PROP_STRING;
424 while (g_variant_iter_next(&iter, "s", &s))
425 value_list->list = g_list_append(value_list->list, s);
426 } else if (g_variant_type_equal(G_VARIANT_TYPE("av"), type)) {
429 if (g_variant_iter_loop(&iter, "v", &value)) {
430 if (g_variant_is_of_type(value, G_VARIANT_TYPE("(siasa{sv}av)"))) {
431 OCRepPayload *repr_value;
432 value_list->type = OCREP_PROP_OBJECT;
434 repr_value = icd_payload_representation_from_gvariant(value);
435 value_list->list = g_list_append(value_list->list, repr_value);
437 } while (g_variant_iter_loop(&iter, "v", &value));
439 } else if (g_variant_is_of_type(value, G_VARIANT_TYPE_ARRAY)) {
441 _icd_state_list_from_gvariant(value, value_list, depth + 1);
442 } while (g_variant_iter_loop(&iter, "v", &value));
451 static void _icd_state_list_free(gpointer node)
453 OCRepPayloadDestroy(node);
457 static void _icd_state_array_from_list(OCRepPayload *repr,
458 struct icd_state_list_s *value_list, const char *key)
466 union icd_state_value_u *value;
467 struct OCRepPayload **state_arr;
469 len = calcDimTotal(value_list->dimensions);
471 switch (value_list->type) {
473 i_arr = calloc(len, sizeof(int64_t));
475 ERR("calloc() Fail(%d)", errno);
478 for (node = value_list->list, i = 0; node; node = node->next, i++) {
482 g_list_free_full(value_list->list, free);
483 OCRepPayloadSetIntArrayAsOwner(repr, key, i_arr, value_list->dimensions);
485 case OCREP_PROP_BOOL:
486 b_arr = calloc(len, sizeof(bool));
488 ERR("calloc() Fail(%d)", errno);
491 for (node = value_list->list, i = 0; node; node = node->next, i++) {
495 g_list_free_full(value_list->list, free);
496 OCRepPayloadSetBoolArrayAsOwner(repr, key, b_arr, value_list->dimensions);
498 case OCREP_PROP_DOUBLE:
499 d_arr = calloc(len, sizeof(double));
501 ERR("calloc() Fail(%d)", errno);
504 for (node = value_list->list, i = 0; node; node = node->next, i++) {
508 g_list_free_full(value_list->list, free);
509 OCRepPayloadSetDoubleArrayAsOwner(repr, key, d_arr, value_list->dimensions);
511 case OCREP_PROP_STRING:
512 str_arr = calloc(len, sizeof(char *));
513 if (NULL == str_arr) {
514 ERR("calloc() Fail(%d)", errno);
517 for (node = value_list->list, i = 0; node; node = node->next, i++)
518 str_arr[i] = strdup(node->data);
519 g_list_free_full(value_list->list, free);
520 OCRepPayloadSetStringArrayAsOwner(repr, key, str_arr, value_list->dimensions);
522 case OCREP_PROP_OBJECT:
523 state_arr = calloc(len, sizeof(struct OCRepPayload *));
524 if (NULL == state_arr) {
525 ERR("calloc() Fail(%d)", errno);
528 for (node = value_list->list, i = 0; node; node = node->next, i++)
529 state_arr[i] = OCRepPayloadClone(node->data);
530 g_list_free_full(value_list->list, _icd_state_list_free);
531 OCRepPayloadSetPropObjectArrayAsOwner(repr, key, state_arr,
532 value_list->dimensions);
534 case OCREP_PROP_ARRAY:
535 case OCREP_PROP_NULL:
542 static void _icd_state_value_from_gvariant(OCRepPayload *repr, GVariantIter *iter)
546 const char *str_value;
547 OCRepPayload *repr_value;
548 struct icd_state_list_s value_list = {0};
550 while (g_variant_iter_loop(iter, "{sv}", &key, &var)) {
552 if (g_variant_is_of_type(var, G_VARIANT_TYPE_BOOLEAN)) {
553 OCRepPayloadSetPropBool(repr, key, g_variant_get_boolean(var));
555 } else if (g_variant_is_of_type(var, G_VARIANT_TYPE_INT32)) {
556 OCRepPayloadSetPropInt(repr, key, g_variant_get_int32(var));
558 } else if (g_variant_is_of_type(var, G_VARIANT_TYPE_DOUBLE)) {
559 OCRepPayloadSetPropDouble(repr, key, g_variant_get_double(var));
561 } else if (g_variant_is_of_type(var, G_VARIANT_TYPE_STRING)) {
562 str_value = g_variant_get_string(var, NULL);
563 if (IC_STR_EQUAL == strcmp(IC_STR_NULL, str_value))
564 OCRepPayloadSetNull(repr, key);
566 OCRepPayloadSetPropString(repr, key, str_value);
568 } else if (g_variant_is_of_type(var, G_VARIANT_TYPE_ARRAY)) {
569 memset(&value_list, 0, sizeof(struct icd_state_list_s));
570 _icd_state_list_from_gvariant(var, &value_list, 0);
571 _icd_state_array_from_list(repr, &value_list, key);
573 } else if (g_variant_is_of_type(var, G_VARIANT_TYPE("(siasa{sv}av)"))) {
574 repr_value = icd_payload_representation_from_gvariant(var);
575 OCRepPayloadSetPropObjectAsOwner(repr, key, repr_value);
583 OCRepPayload* icd_payload_representation_from_gvariant(GVariant *var)
586 int ret, i, ifaces = 0;
587 OCRepPayload *repr, *cur;
588 char *uri_path, *iface_str, *resource_type;
589 GVariantIter *resource_types, *repr_gvar, *children;
591 repr = OCRepPayloadCreate();
593 g_variant_get(var, "(&siasa{sv}av)", &uri_path, &ifaces, &resource_types, &repr_gvar,
596 if (IC_STR_EQUAL != strcmp(IC_STR_NULL, uri_path))
597 OCRepPayloadSetUri(repr, uri_path);
599 for (i = 1; i <= IC_INTERFACE_MAX; i = i << 1) {
600 if (IOTCON_INTERFACE_NONE == (ifaces & i)) /* this interface not exist */
602 ret = ic_utils_convert_interface_flag((ifaces & i), &iface_str);
603 if (IOTCON_ERROR_NONE != ret) {
604 ERR("ic_utils_convert_interface_flag(%d) Fail(%d)", i, ret);
605 OCRepPayloadDestroy(repr);
608 OCRepPayloadAddInterface(repr, iface_str);
610 while (g_variant_iter_loop(resource_types, "s", &resource_type))
611 OCRepPayloadAddResourceType(repr, resource_type);
613 _icd_state_value_from_gvariant(repr, repr_gvar);
616 while (g_variant_iter_loop(children, "v", &child)) {
617 cur->next = icd_payload_representation_from_gvariant(child);