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);
44 static void _icd_state_value_from_gvariant(OCRepPayload *repr, GVariantIter *iter);
45 static GVariantBuilder* _icd_state_value_to_gvariant_builder(OCRepPayload *repr);
47 GVariant** icd_payload_res_to_gvariant(OCPayload *payload, OCDevAddr *dev_addr)
53 iotcon_interface_e iface;
54 GVariantBuilder types;
55 OCRandomUuidResult random_res;
56 OCDiscoveryPayload *discovered;
57 struct OCResourcePayload *resource;
58 int i, is_observable, ret, res_count;
59 char device_id[UUID_STRING_SIZE] = {0};
61 discovered = (OCDiscoveryPayload*)payload;
62 resource = discovered->resources;
64 res_count = OCDiscoveryPayloadGetResourceCount(discovered);
66 value = calloc(res_count, sizeof(GVariant*));
68 ERR("calloc() Fail(%d)", errno);
71 for (i = 0; resource; i++) {
73 if (NULL == resource->uri) {
74 ERR("resource uri is NULL");
75 resource = resource->next;
79 random_res = OCConvertUuidToString(resource->sid, device_id);
80 if (RAND_UUID_OK != random_res) {
81 ERR("OCConvertUuidToString() Fail(%d)", random_res);
82 resource = resource->next;
86 g_variant_builder_init(&types, G_VARIANT_TYPE("as"));
87 node = resource->types;
89 ERR("resource types is NULL");
90 resource = resource->next;
93 g_variant_builder_add(&types, "s", node->value);
97 /* Resource Interfaces */
98 node = resource->interfaces;
100 ERR("resource interfaces is NULL");
101 resource = resource->next;
104 ret = ic_utils_convert_interface_string(node->value, &iface);
105 if (IOTCON_ERROR_NONE != ret) {
106 ERR("ic_utils_convert_interface_string() Fail(%d)", ret);
107 resource = resource->next;
115 is_observable = resource->bitmap & OC_OBSERVABLE;
118 port = (resource->port)? resource->port:dev_addr->port;
120 value[i] = g_variant_new("(ssiasibsi)", resource->uri, device_id, ifaces, &types,
121 is_observable, resource->secure, dev_addr->addr, port);
122 DBG("found resource[%d] : %s", i, g_variant_print(value[i], FALSE));
124 resource = resource->next;
131 static GVariant* _icd_state_array_attr_to_gvariant(OCRepPayloadValueArray *arr, int len,
136 GVariantBuilder builder;
138 g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY);
142 for (i = 0; i < len; i++)
143 g_variant_builder_add(&builder, "i", arr->iArray[index + i]);
145 case OCREP_PROP_BOOL:
146 for (i = 0; i < len; i++)
147 g_variant_builder_add(&builder, "b", arr->bArray[index + i]);
149 case OCREP_PROP_DOUBLE:
150 for (i = 0; i < len; i++)
151 g_variant_builder_add(&builder, "d", arr->dArray[index + i]);
153 case OCREP_PROP_STRING:
154 for (i = 0; i < len; i++)
155 g_variant_builder_add(&builder, "s", arr->strArray[index + i]);
157 case OCREP_PROP_NULL:
158 for (i = 0; i < len; i++)
159 g_variant_builder_add(&builder, "s", IC_STR_NULL);
161 case OCREP_PROP_OBJECT:
162 for (i = 0; i < len; i++) {
163 GVariantBuilder *state_var = _icd_state_value_to_gvariant_builder(arr->objArray[index + i]);
164 var = g_variant_builder_end(state_var);
165 g_variant_builder_add(&builder, "v", var);
168 case OCREP_PROP_ARRAY:
173 return g_variant_builder_end(&builder);
177 static GVariant* _icd_state_array_to_gvariant(OCRepPayloadValueArray *arr,
178 int current_depth, int current_len, int index)
181 GVariantBuilder builder;
182 GVariant *arr_var = NULL;
184 if ((MAX_REP_ARRAY_DEPTH - 1) == current_depth
185 || 0 == arr->dimensions[current_depth + 1])
186 return _icd_state_array_attr_to_gvariant(arr, current_len, index);
188 i = current_len + index;
190 next_len = current_len / arr->dimensions[current_depth];
193 g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY);
195 while ((index += next_len) < i) {
196 arr_var = _icd_state_array_to_gvariant(arr, current_depth + 1, next_len, index);
197 g_variant_builder_add(&builder, "v", arr_var);
200 return g_variant_builder_end(&builder);
203 static GVariant* _icd_state_value_to_gvariant(OCRepPayload *state)
205 GVariantBuilder *builder;
208 builder = _icd_state_value_to_gvariant_builder(state);
209 var = g_variant_builder_end(builder);
214 static GVariantBuilder* _icd_state_value_to_gvariant_builder(OCRepPayload *repr)
217 GVariant *var = NULL;
218 GVariantBuilder *builder;
219 OCRepPayloadValue *val = repr->values;
221 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
226 var = g_variant_new_int32(val->i);
228 case OCREP_PROP_BOOL:
229 var = g_variant_new_boolean(val->b);
231 case OCREP_PROP_DOUBLE:
232 var = g_variant_new_double(val->d);
234 case OCREP_PROP_STRING:
235 var = g_variant_new_string(val->str);
237 case OCREP_PROP_NULL:
238 var = g_variant_new_string(IC_STR_NULL);
240 case OCREP_PROP_ARRAY:
241 total_len = calcDimTotal(val->arr.dimensions);
242 var = _icd_state_array_to_gvariant(&(val->arr), 0, total_len, 0);
244 case OCREP_PROP_OBJECT:
245 var = _icd_state_value_to_gvariant(val->obj);
251 g_variant_builder_add(builder, "{sv}", val->name, var);
261 static GVariant* _icd_payload_representation_to_gvariant(OCRepPayload *repr,
266 GVariant *child, *value;
267 OCRepPayload *child_node;
268 iotcon_interface_e iface;
269 GVariantBuilder *repr_gvar;
270 GVariantBuilder children, types_builder;
272 RETV_IF(NULL == repr, NULL);
275 g_variant_builder_init(&types_builder, G_VARIANT_TYPE("as"));
279 g_variant_builder_add(&types_builder, "s", node->value);
283 /* Resource Interfaces */
284 node = repr->interfaces;
286 ret = ic_utils_convert_interface_string(node->value, &iface);
287 if (IOTCON_ERROR_NONE != ret) {
288 ERR("ic_utils_convert_interface_string() Fail(%d)", ret);
297 repr_gvar = _icd_state_value_to_gvariant_builder(repr);
300 g_variant_builder_init(&children, G_VARIANT_TYPE("av"));
302 child_node = repr->next;
303 while (is_parent && child_node) {
304 /* generate recursively */
305 child = _icd_payload_representation_to_gvariant(child_node, FALSE);
306 g_variant_builder_add(&children, "v", child);
307 child_node = child_node->next;
310 value = g_variant_new("(siasa{sv}av)", ic_utils_dbus_encode_str(repr->uri), ifaces,
311 &types_builder, repr_gvar, &children);
317 GVariant* icd_payload_representation_empty_gvariant(void)
320 GVariantBuilder types, repr, children;
322 g_variant_builder_init(&types, G_VARIANT_TYPE("as"));
323 g_variant_builder_init(&repr, G_VARIANT_TYPE("a{sv}"));
324 g_variant_builder_init(&children, G_VARIANT_TYPE("av"));
326 value = g_variant_new("(siasa{sv}av)", IC_STR_NULL, 0, &types, &repr, &children);
332 static GVariant* _icd_payload_platform_to_gvariant(OCPlatformPayload *repr)
336 value = g_variant_new("(ssssssssssss)",
338 repr->info.platformID,
339 repr->info.manufacturerName,
340 ic_utils_dbus_encode_str(repr->info.manufacturerUrl),
341 ic_utils_dbus_encode_str(repr->info.modelNumber),
342 ic_utils_dbus_encode_str(repr->info.dateOfManufacture),
343 ic_utils_dbus_encode_str(repr->info.platformVersion),
344 ic_utils_dbus_encode_str(repr->info.operatingSystemVersion),
345 ic_utils_dbus_encode_str(repr->info.hardwareVersion),
346 ic_utils_dbus_encode_str(repr->info.firmwareVersion),
347 ic_utils_dbus_encode_str(repr->info.supportUrl),
348 ic_utils_dbus_encode_str(repr->info.systemTime));
354 static GVariant* _icd_payload_device_to_gvariant(OCDevicePayload *repr)
357 OCRandomUuidResult random_res;
358 char device_id[UUID_STRING_SIZE] = {0};
360 random_res = OCConvertUuidToString(repr->sid, device_id);
361 if (RAND_UUID_OK != random_res) {
362 ERR("OCConvertUuidToString() Fail(%d)", random_res);
366 value = g_variant_new("(sssss)", repr->uri, repr->deviceName, repr->specVersion,
367 device_id, repr->dataModelVersion);
373 GVariant* icd_payload_to_gvariant(OCPayload *repr)
375 GVariant *value = NULL;
380 switch (repr->type) {
381 case PAYLOAD_TYPE_REPRESENTATION:
382 value = _icd_payload_representation_to_gvariant((OCRepPayload*)repr, TRUE);
384 case PAYLOAD_TYPE_PLATFORM:
385 value = _icd_payload_platform_to_gvariant((OCPlatformPayload*)repr);
387 case PAYLOAD_TYPE_DEVICE:
388 value = _icd_payload_device_to_gvariant((OCDevicePayload*)repr);
390 case PAYLOAD_TYPE_PRESENCE:
391 case PAYLOAD_TYPE_SECURITY:
400 static void _icd_state_list_from_gvariant(GVariant *var,
401 struct icd_state_list_s *value_list, int depth)
404 const GVariantType *type;
405 union icd_state_value_u *value;
407 type = g_variant_get_type(var);
409 g_variant_iter_init(&iter, var);
411 value_list->dimensions[depth] = g_variant_iter_n_children(&iter);
412 DBG("[%d]list dim : %d", depth, value_list->dimensions[depth]);
414 if (g_variant_type_equal(G_VARIANT_TYPE("ab"), type)) {
416 value_list->type = OCREP_PROP_BOOL;
417 while (g_variant_iter_loop(&iter, "b", &b)) {
418 value = calloc(1, sizeof(union icd_state_value_u));
420 ERR("calloc() Fail(%d)", errno);
424 value_list->list = g_list_append(value_list->list, value);
426 } else if (g_variant_type_equal(G_VARIANT_TYPE("ai"), type)) {
428 value_list->type = OCREP_PROP_INT;
429 while (g_variant_iter_loop(&iter, "i", &i)) {
430 value = calloc(1, sizeof(union icd_state_value_u));
432 ERR("calloc() Fail(%d)", errno);
436 value_list->list = g_list_append(value_list->list, value);
438 } else if (g_variant_type_equal(G_VARIANT_TYPE("ad"), type)) {
440 value_list->type = OCREP_PROP_DOUBLE;
441 while (g_variant_iter_loop(&iter, "d", &d)) {
442 value = calloc(1, sizeof(union icd_state_value_u));
444 ERR("calloc() Fail(%d)", errno);
448 value_list->list = g_list_append(value_list->list, value);
450 } else if (g_variant_type_equal(G_VARIANT_TYPE("as"), type)) {
452 value_list->type = OCREP_PROP_STRING;
453 while (g_variant_iter_next(&iter, "s", &s))
454 value_list->list = g_list_append(value_list->list, s);
455 } else if (g_variant_type_equal(G_VARIANT_TYPE("av"), type)) {
457 if (g_variant_iter_loop(&iter, "v", &value)) {
458 if (g_variant_is_of_type(value, G_VARIANT_TYPE("a{sv}"))) {
460 GVariantIter state_iter;
461 value_list->type = OCREP_PROP_OBJECT;
463 repr = OCRepPayloadCreate();
464 g_variant_iter_init(&state_iter, value);
465 _icd_state_value_from_gvariant(repr, &state_iter);
466 value_list->list = g_list_append(value_list->list, repr);
467 } while (g_variant_iter_loop(&iter, "v", &value));
469 } else if (g_variant_is_of_type(value, G_VARIANT_TYPE_ARRAY)) {
471 _icd_state_list_from_gvariant(value, value_list, depth + 1);
472 } while (g_variant_iter_loop(&iter, "v", &value));
481 static void _icd_state_list_free(gpointer node)
483 OCRepPayloadDestroy(node);
487 static void _icd_state_array_from_list(OCRepPayload *repr,
488 struct icd_state_list_s *value_list, const char *key)
496 union icd_state_value_u *value;
497 struct OCRepPayload **state_arr;
499 len = calcDimTotal(value_list->dimensions);
501 switch (value_list->type) {
503 i_arr = calloc(len, sizeof(int64_t));
505 ERR("calloc() Fail(%d)", errno);
508 for (node = value_list->list, i = 0; node; node = node->next, i++) {
512 g_list_free_full(value_list->list, free);
513 OCRepPayloadSetIntArrayAsOwner(repr, key, i_arr, value_list->dimensions);
515 case OCREP_PROP_BOOL:
516 b_arr = calloc(len, sizeof(bool));
518 ERR("calloc() Fail(%d)", errno);
521 for (node = value_list->list, i = 0; node; node = node->next, i++) {
525 g_list_free_full(value_list->list, free);
526 OCRepPayloadSetBoolArrayAsOwner(repr, key, b_arr, value_list->dimensions);
528 case OCREP_PROP_DOUBLE:
529 d_arr = calloc(len, sizeof(double));
531 ERR("calloc() Fail(%d)", errno);
534 for (node = value_list->list, i = 0; node; node = node->next, i++) {
538 g_list_free_full(value_list->list, free);
539 OCRepPayloadSetDoubleArrayAsOwner(repr, key, d_arr, value_list->dimensions);
541 case OCREP_PROP_STRING:
542 str_arr = calloc(len, sizeof(char *));
543 if (NULL == str_arr) {
544 ERR("calloc() Fail(%d)", errno);
547 for (node = value_list->list, i = 0; node; node = node->next, i++)
548 str_arr[i] = strdup(node->data);
549 g_list_free_full(value_list->list, free);
550 OCRepPayloadSetStringArrayAsOwner(repr, key, str_arr, value_list->dimensions);
552 case OCREP_PROP_OBJECT:
553 state_arr = calloc(len, sizeof(struct OCRepPayload *));
554 if (NULL == state_arr) {
555 ERR("calloc() Fail(%d)", errno);
558 for (node = value_list->list, i = 0; node; node = node->next, i++)
559 state_arr[i] = OCRepPayloadClone(node->data);
560 g_list_free_full(value_list->list, _icd_state_list_free);
561 OCRepPayloadSetPropObjectArrayAsOwner(repr, key, state_arr,
562 value_list->dimensions);
564 case OCREP_PROP_ARRAY:
565 case OCREP_PROP_NULL:
571 static void _icd_state_value_from_gvariant(OCRepPayload *repr, GVariantIter *iter)
575 const char *str_value;
576 OCRepPayload *repr_value;
577 struct icd_state_list_s value_list = {0};
579 while (g_variant_iter_loop(iter, "{sv}", &key, &var)) {
581 if (g_variant_is_of_type(var, G_VARIANT_TYPE_BOOLEAN)) {
582 OCRepPayloadSetPropBool(repr, key, g_variant_get_boolean(var));
584 } else if (g_variant_is_of_type(var, G_VARIANT_TYPE_INT32)) {
585 OCRepPayloadSetPropInt(repr, key, g_variant_get_int32(var));
587 } else if (g_variant_is_of_type(var, G_VARIANT_TYPE_DOUBLE)) {
588 OCRepPayloadSetPropDouble(repr, key, g_variant_get_double(var));
590 } else if (g_variant_is_of_type(var, G_VARIANT_TYPE_STRING)) {
591 str_value = g_variant_get_string(var, NULL);
592 if (IC_STR_EQUAL == strcmp(IC_STR_NULL, str_value))
593 OCRepPayloadSetNull(repr, key);
595 OCRepPayloadSetPropString(repr, key, str_value);
597 } else if (g_variant_is_of_type(var, G_VARIANT_TYPE_ARRAY)) {
598 memset(&value_list, 0, sizeof(struct icd_state_list_s));
599 _icd_state_list_from_gvariant(var, &value_list, 0);
600 _icd_state_array_from_list(repr, &value_list, key);
602 } else if (g_variant_is_of_type(var, G_VARIANT_TYPE("(siasa{sv}av)"))) {
603 repr_value = icd_payload_representation_from_gvariant(var);
604 OCRepPayloadSetPropObjectAsOwner(repr, key, repr_value);
611 OCRepPayload* icd_payload_representation_from_gvariant(GVariant *var)
614 int ret, i, ifaces = 0;
615 OCRepPayload *repr, *cur;
616 char *uri_path, *iface_str, *resource_type;
617 GVariantIter *resource_types, *repr_gvar, *children;
619 repr = OCRepPayloadCreate();
621 g_variant_get(var, "(&siasa{sv}av)", &uri_path, &ifaces, &resource_types, &repr_gvar,
624 if (IC_STR_EQUAL != strcmp(IC_STR_NULL, uri_path))
625 OCRepPayloadSetUri(repr, uri_path);
627 for (i = 1; i <= IC_INTERFACE_MAX; i = i << 1) {
628 if (IOTCON_INTERFACE_NONE == (ifaces & i)) /* this interface not exist */
630 ret = ic_utils_convert_interface_flag((ifaces & i), &iface_str);
631 if (IOTCON_ERROR_NONE != ret) {
632 ERR("ic_utils_convert_interface_flag(%d) Fail(%d)", i, ret);
633 OCRepPayloadDestroy(repr);
636 OCRepPayloadAddInterface(repr, iface_str);
638 while (g_variant_iter_loop(resource_types, "s", &resource_type))
639 OCRepPayloadAddResourceType(repr, resource_type);
641 _icd_state_value_from_gvariant(repr, repr_gvar);
644 while (g_variant_iter_loop(children, "v", &child)) {
645 cur->next = icd_payload_representation_from_gvariant(child);