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>
28 #include "icd-payload.h"
30 union icd_repr_value_u {
36 struct icd_repr_list_s {
37 OCRepPayloadPropType type;
38 size_t dimensions[MAX_REP_ARRAY_DEPTH];
42 static GVariant* _icd_payload_repr_to_gvariant(OCRepPayload *repr, gboolean is_parent);
44 GVariant** icd_payload_res_to_gvariant(OCPayload *payload, OCDevAddr *dev_addr)
50 iotcon_interface_e iface;
51 GVariantBuilder types;
52 OCRandomUuidResult random_res;
53 OCDiscoveryPayload *discovered;
54 char sid[UUID_STRING_SIZE] = {0};
55 struct OCResourcePayload *resource;
56 int i, is_observable, ret, res_count;
58 discovered = (OCDiscoveryPayload*)payload;
59 resource = discovered->resources;
61 res_count = OCDiscoveryPayloadGetResourceCount(discovered);
63 value = calloc(res_count, sizeof(GVariant*));
65 ERR("calloc() Fail(%d)", errno);
68 for (i = 0; resource; i++) {
70 if (NULL == resource->uri) {
71 ERR("resource uri is NULL");
72 resource = resource->next;
76 random_res = OCConvertUuidToString(resource->sid, sid);
77 if (RAND_UUID_OK != random_res) {
78 ERR("OCConvertUuidToString() Fail(%d)", random_res);
79 resource = resource->next;
83 g_variant_builder_init(&types, G_VARIANT_TYPE("as"));
84 node = resource->types;
86 ERR("resource types is NULL");
87 resource = resource->next;
90 g_variant_builder_add(&types, "s", node->value);
94 /* Resource Interfaces */
95 node = resource->interfaces;
97 ERR("resource interfaces is NULL");
98 resource = resource->next;
101 ret = ic_utils_convert_interface_string(node->value, &iface);
102 if (IOTCON_ERROR_NONE != ret) {
103 ERR("ic_utils_convert_interface_string() Fail(%d)", ret);
104 resource = resource->next;
112 is_observable = resource->bitmap & OC_OBSERVABLE;
115 port = (resource->port)? resource->port:dev_addr->port;
117 value[i] = g_variant_new("(ssiasibsi)", resource->uri, sid, ifaces, &types,
118 is_observable, resource->secure, dev_addr->addr, port);
119 DBG("found resource[%d] : %s", i, g_variant_print(value[i], FALSE));
121 resource = resource->next;
128 static GVariant* _icd_repr_array_attr_to_gvariant(OCRepPayloadValueArray *arr, int len,
133 GVariantBuilder builder;
135 g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY);
139 for (i = 0; i < len; i++)
140 g_variant_builder_add(&builder, "i", arr->iArray[index + i]);
142 case OCREP_PROP_BOOL:
143 for (i = 0; i < len; i++)
144 g_variant_builder_add(&builder, "b", arr->bArray[index + i]);
146 case OCREP_PROP_DOUBLE:
147 for (i = 0; i < len; i++)
148 g_variant_builder_add(&builder, "d", arr->dArray[index + i]);
150 case OCREP_PROP_STRING:
151 for (i = 0; i < len; i++)
152 g_variant_builder_add(&builder, "s", arr->strArray[index + i]);
154 case OCREP_PROP_NULL:
155 for (i = 0; i < len; i++)
156 g_variant_builder_add(&builder, "s", IC_STR_NULL);
158 case OCREP_PROP_OBJECT:
159 for (i = 0; i < len; i++) {
160 var = _icd_payload_repr_to_gvariant(arr->objArray[index + i], TRUE);
161 g_variant_builder_add(&builder, "v", var);
164 case OCREP_PROP_ARRAY:
169 return g_variant_builder_end(&builder);
173 static GVariant* _icd_repr_array_to_gvariant(OCRepPayloadValueArray *arr,
174 int current_depth, int current_len, int index)
177 GVariantBuilder builder;
178 GVariant *arr_var = NULL;
180 if ((MAX_REP_ARRAY_DEPTH - 1) == current_depth
181 || 0 == arr->dimensions[current_depth + 1])
182 return _icd_repr_array_attr_to_gvariant(arr, current_len, index);
184 i = current_len + index;
186 next_len = current_len / arr->dimensions[current_depth];
189 g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY);
191 while ((index += next_len) < i) {
192 arr_var = _icd_repr_array_to_gvariant(arr, current_depth + 1, next_len, index);
193 g_variant_builder_add(&builder, "v", arr_var);
196 return g_variant_builder_end(&builder);
200 static GVariantBuilder* _icd_repr_value_to_gvariant(OCRepPayload *repr)
203 GVariant *var = NULL;
204 GVariantBuilder *builder;
205 OCRepPayloadValue *val = repr->values;
207 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
212 var = g_variant_new_int32(val->i);
214 case OCREP_PROP_BOOL:
215 var = g_variant_new_boolean(val->b);
217 case OCREP_PROP_DOUBLE:
218 var = g_variant_new_double(val->d);
220 case OCREP_PROP_STRING:
221 var = g_variant_new_string(val->str);
223 case OCREP_PROP_NULL:
224 var = g_variant_new_string(IC_STR_NULL);
226 case OCREP_PROP_ARRAY:
227 total_len = calcDimTotal(val->arr.dimensions);
228 var = _icd_repr_array_to_gvariant(&(val->arr), 0, total_len, 0);
230 case OCREP_PROP_OBJECT:
231 var = _icd_payload_repr_to_gvariant(val->obj, TRUE);
237 g_variant_builder_add(builder, "{sv}", val->name, var);
247 static GVariant* _icd_payload_repr_to_gvariant(OCRepPayload *repr, gboolean is_parent)
251 GVariant *child, *value;
252 OCRepPayload *child_node;
253 iotcon_interface_e iface;
254 GVariantBuilder *repr_gvar;
255 GVariantBuilder children, types_builder;
257 RETV_IF(NULL == repr, NULL);
260 g_variant_builder_init(&types_builder, G_VARIANT_TYPE("as"));
264 g_variant_builder_add(&types_builder, "s", node->value);
268 /* Resource Interfaces */
269 node = repr->interfaces;
271 ret = ic_utils_convert_interface_string(node->value, &iface);
272 if (IOTCON_ERROR_NONE != ret) {
273 ERR("ic_utils_convert_interface_string() Fail(%d)", ret);
282 repr_gvar = _icd_repr_value_to_gvariant(repr);
285 g_variant_builder_init(&children, G_VARIANT_TYPE("av"));
287 child_node = repr->next;
288 while (is_parent && child_node) {
289 /* generate recursively */
290 child = _icd_payload_repr_to_gvariant(child_node, FALSE);
291 g_variant_builder_add(&children, "v", child);
292 child_node = child_node->next;
295 value = g_variant_new("(siasa{sv}av)", ic_utils_dbus_encode_str(repr->uri), ifaces,
296 &types_builder, repr_gvar, &children);
302 static GVariant* _icd_payload_platform_to_gvariant(OCPlatformPayload *repr)
306 value = g_variant_new("(ssssssssssss)",
308 repr->info.platformID,
309 repr->info.manufacturerName,
310 repr->info.manufacturerUrl,
311 repr->info.modelNumber,
312 repr->info.dateOfManufacture,
313 repr->info.platformVersion,
314 repr->info.operatingSystemVersion,
315 repr->info.hardwareVersion,
316 repr->info.firmwareVersion,
317 repr->info.supportUrl,
318 repr->info.systemTime);
324 static GVariant* _icd_payload_device_to_gvariant(OCDevicePayload *repr)
327 OCRandomUuidResult random_res;
328 char sid[UUID_STRING_SIZE] = {0};
330 random_res = OCConvertUuidToString(repr->sid, sid);
331 if (RAND_UUID_OK != random_res) {
332 ERR("OCConvertUuidToString() Fail(%d)", random_res);
336 value = g_variant_new("(ssss)", repr->deviceName, sid, repr->specVersion,
337 repr->dataModelVersion);
343 GVariant* icd_payload_to_gvariant(OCPayload *repr)
345 GVariant *value = NULL;
350 switch (repr->type) {
351 case PAYLOAD_TYPE_REPRESENTATION:
352 value = _icd_payload_repr_to_gvariant((OCRepPayload*)repr, TRUE);
354 case PAYLOAD_TYPE_PLATFORM:
355 value = _icd_payload_platform_to_gvariant((OCPlatformPayload*)repr);
357 case PAYLOAD_TYPE_DEVICE:
358 value = _icd_payload_device_to_gvariant((OCDevicePayload*)repr);
360 case PAYLOAD_TYPE_PRESENCE:
361 case PAYLOAD_TYPE_SECURITY:
370 static void _icd_repr_list_from_gvariant(GVariant *var,
371 struct icd_repr_list_s *value_list, int depth)
374 const GVariantType *type;
375 union icd_repr_value_u *value;
377 type = g_variant_get_type(var);
379 g_variant_iter_init(&iter, var);
381 value_list->dimensions[depth] = g_variant_iter_n_children(&iter);
382 DBG("[%d]list dim : %d", depth, value_list->dimensions[depth]);
384 if (g_variant_type_equal(G_VARIANT_TYPE("ab"), type)) {
386 value_list->type = OCREP_PROP_BOOL;
387 while (g_variant_iter_loop(&iter, "b", &b)) {
388 value = calloc(1, sizeof(union icd_repr_value_u));
390 ERR("calloc() Fail(%d)", errno);
394 value_list->list = g_list_append(value_list->list, value);
396 } else if (g_variant_type_equal(G_VARIANT_TYPE("ai"), type)) {
398 value_list->type = OCREP_PROP_INT;
399 while (g_variant_iter_loop(&iter, "i", &i)) {
400 value = calloc(1, sizeof(union icd_repr_value_u));
402 ERR("calloc() Fail(%d)", errno);
406 value_list->list = g_list_append(value_list->list, value);
408 } else if (g_variant_type_equal(G_VARIANT_TYPE("ad"), type)) {
410 value_list->type = OCREP_PROP_DOUBLE;
411 while (g_variant_iter_loop(&iter, "d", &d)) {
412 value = calloc(1, sizeof(union icd_repr_value_u));
414 ERR("calloc() Fail(%d)", errno);
418 value_list->list = g_list_append(value_list->list, value);
420 } else if (g_variant_type_equal(G_VARIANT_TYPE("as"), type)) {
422 value_list->type = OCREP_PROP_STRING;
423 while (g_variant_iter_next(&iter, "s", &s))
424 value_list->list = g_list_append(value_list->list, s);
425 } else if (g_variant_type_equal(G_VARIANT_TYPE("av"), type)) {
428 if (g_variant_iter_loop(&iter, "v", &value)) {
429 if (g_variant_is_of_type(value, G_VARIANT_TYPE("(siasa{sv}av)"))) {
430 OCRepPayload *repr_value;
431 value_list->type = OCREP_PROP_OBJECT;
433 repr_value = icd_payload_repr_from_gvariant(value);
434 value_list->list = g_list_append(value_list->list, repr_value);
436 } while (g_variant_iter_loop(&iter, "v", &value));
438 } else if (g_variant_is_of_type(value, G_VARIANT_TYPE_ARRAY)) {
440 _icd_repr_list_from_gvariant(value, value_list, depth + 1);
441 } while (g_variant_iter_loop(&iter, "v", &value));
450 static void _icd_repr_list_free(gpointer node)
452 OCRepPayloadDestroy(node);
456 static void _icd_repr_array_from_list(OCRepPayload *repr,
457 struct icd_repr_list_s *value_list, const char *key)
465 union icd_repr_value_u *value;
466 struct OCRepPayload **repr_arr;
468 len = calcDimTotal(value_list->dimensions);
470 switch (value_list->type) {
472 i_arr = calloc(len, sizeof(int64_t));
474 ERR("calloc() Fail(%d)", errno);
477 for (node = value_list->list, i = 0; node; node = node->next, i++) {
481 g_list_free_full(value_list->list, free);
482 OCRepPayloadSetIntArrayAsOwner(repr, key, i_arr, value_list->dimensions);
484 case OCREP_PROP_BOOL:
485 b_arr = calloc(len, sizeof(bool));
487 ERR("calloc() Fail(%d)", errno);
490 for (node = value_list->list, i = 0; node; node = node->next, i++) {
494 g_list_free_full(value_list->list, free);
495 OCRepPayloadSetBoolArrayAsOwner(repr, key, b_arr, value_list->dimensions);
497 case OCREP_PROP_DOUBLE:
498 d_arr = calloc(len, sizeof(double));
500 ERR("calloc() Fail(%d)", errno);
503 for (node = value_list->list, i = 0; node; node = node->next, i++) {
507 g_list_free_full(value_list->list, free);
508 OCRepPayloadSetDoubleArrayAsOwner(repr, key, d_arr, value_list->dimensions);
510 case OCREP_PROP_STRING:
511 str_arr = calloc(len, sizeof(char *));
512 if (NULL == str_arr) {
513 ERR("calloc() Fail(%d)", errno);
516 for (node = value_list->list, i = 0; node; node = node->next, i++)
517 str_arr[i] = strdup(node->data);
518 g_list_free_full(value_list->list, free);
519 OCRepPayloadSetStringArrayAsOwner(repr, key, str_arr, value_list->dimensions);
521 case OCREP_PROP_OBJECT:
522 repr_arr = calloc(len, sizeof(struct OCRepPayload *));
523 if (NULL == repr_arr) {
524 ERR("calloc() Fail(%d)", errno);
527 for (node = value_list->list, i = 0; node; node = node->next, i++)
528 repr_arr[i] = OCRepPayloadClone(node->data);
529 g_list_free_full(value_list->list, _icd_repr_list_free);
530 OCRepPayloadSetPropObjectArrayAsOwner(repr, key, repr_arr,
531 value_list->dimensions);
533 case OCREP_PROP_ARRAY:
534 case OCREP_PROP_NULL:
541 static void _icd_repr_value_from_gvariant(OCRepPayload *repr, GVariantIter *iter)
545 const char *str_value;
546 OCRepPayload *repr_value;
547 struct icd_repr_list_s value_list = {0};
549 while (g_variant_iter_loop(iter, "{sv}", &key, &var)) {
551 if (g_variant_is_of_type(var, G_VARIANT_TYPE_BOOLEAN)) {
552 OCRepPayloadSetPropBool(repr, key, g_variant_get_boolean(var));
554 } else if (g_variant_is_of_type(var, G_VARIANT_TYPE_INT32)) {
555 OCRepPayloadSetPropInt(repr, key, g_variant_get_int32(var));
557 } else if (g_variant_is_of_type(var, G_VARIANT_TYPE_DOUBLE)) {
558 OCRepPayloadSetPropDouble(repr, key, g_variant_get_double(var));
560 } else if (g_variant_is_of_type(var, G_VARIANT_TYPE_STRING)) {
561 str_value = g_variant_get_string(var, NULL);
562 if (IC_STR_EQUAL == strcmp(IC_STR_NULL, str_value))
563 OCRepPayloadSetNull(repr, key);
565 OCRepPayloadSetPropString(repr, key, str_value);
567 } else if (g_variant_is_of_type(var, G_VARIANT_TYPE_ARRAY)) {
568 memset(&value_list, 0, sizeof(struct icd_repr_list_s));
569 _icd_repr_list_from_gvariant(var, &value_list, 0);
570 _icd_repr_array_from_list(repr, &value_list, key);
572 } else if (g_variant_is_of_type(var, G_VARIANT_TYPE("(siasa{sv}av)"))) {
573 repr_value = icd_payload_repr_from_gvariant(var);
574 OCRepPayloadSetPropObjectAsOwner(repr, key, repr_value);
582 OCRepPayload* icd_payload_repr_from_gvariant(GVariant *var)
585 int ret, i, ifaces = 0;
586 OCRepPayload *repr, *cur;
587 char *uri_path, *iface_str, *resource_type;
588 GVariantIter *resource_types, *repr_gvar, *children;
590 repr = OCRepPayloadCreate();
592 g_variant_get(var, "(&siasa{sv}av)", &uri_path, &ifaces, &resource_types, &repr_gvar,
595 if (IC_STR_EQUAL != strcmp(IC_STR_NULL, uri_path))
596 OCRepPayloadSetUri(repr, uri_path);
598 for (i = 1; i <= IC_INTERFACE_MAX; i = i << 1) {
599 if (IOTCON_INTERFACE_NONE == (ifaces & i)) /* this interface not exist */
601 ret = ic_utils_convert_interface_flag((ifaces & i), &iface_str);
602 if (IOTCON_ERROR_NONE != ret) {
603 ERR("ic_utils_convert_interface_flag(%d) Fail(%d)", i, ret);
604 OCRepPayloadDestroy(repr);
607 OCRepPayloadAddInterface(repr, iface_str);
609 while (g_variant_iter_loop(resource_types, "s", &resource_type))
610 OCRepPayloadAddResourceType(repr, resource_type);
612 _icd_repr_value_from_gvariant(repr, repr_gvar);
615 while (g_variant_iter_loop(children, "v", &child)) {
616 cur->next = icd_payload_repr_from_gvariant(child);