123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279 |
- /*
- This file is part of GNUnet.
- Copyright (C) 2009-2013 GNUnet e.V.
- GNUnet is free software: you can redistribute it and/or modify it
- under the terms of the GNU Affero General Public License as published
- by the Free Software Foundation, either version 3 of the License,
- or (at your option) any later version.
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Affero General Public License for more details.
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- SPDX-License-Identifier: AGPL3.0-or-later
- */
- /**
- * @file json/json_gnsrecord.c
- * @brief JSON handling of GNS record data
- * @author Philippe Buschmann
- */
- #include "platform.h"
- #include "gnunet_util_lib.h"
- #include "gnunet_json_lib.h"
- #define GNUNET_JSON_GNSRECORD_VALUE "value"
- #define GNUNET_JSON_GNSRECORD_RECORD_DATA "data"
- #define GNUNET_JSON_GNSRECORD_TYPE "record_type"
- #define GNUNET_JSON_GNSRECORD_EXPIRATION_TIME "expiration_time"
- #define GNUNET_JSON_GNSRECORD_FLAG_PRIVATE "private"
- #define GNUNET_JSON_GNSRECORD_FLAG_SUPPLEMENTAL "supplemental"
- #define GNUNET_JSON_GNSRECORD_FLAG_RELATIVE "relative_expiration"
- #define GNUNET_JSON_GNSRECORD_FLAG_SHADOW "shadow"
- #define GNUNET_JSON_GNSRECORD_RECORD_NAME "record_name"
- #define GNUNET_JSON_GNSRECORD_NEVER "never"
- struct GnsRecordInfo
- {
- char **name;
- unsigned int *rd_count;
- struct GNUNET_GNSRECORD_Data **rd;
- };
- static void
- cleanup_recordinfo (struct GnsRecordInfo *gnsrecord_info)
- {
- char *tmp;
- if (NULL != *(gnsrecord_info->rd))
- {
- for (int i = 0; i < *(gnsrecord_info->rd_count); i++)
- {
- tmp = (char*) (*(gnsrecord_info->rd))[i].data;
- if (NULL != tmp)
- GNUNET_free (tmp);
- }
- GNUNET_free (*(gnsrecord_info->rd));
- *(gnsrecord_info->rd) = NULL;
- }
- if (NULL != *(gnsrecord_info->name))
- GNUNET_free (*(gnsrecord_info->name));
- *(gnsrecord_info->name) = NULL;
- }
- /**
- * Parse given JSON object to gns record
- *
- * @param cls closure, NULL
- * @param root the json object representing data
- * @param spec where to write the data
- * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
- */
- static int
- parse_record (json_t *data, struct GNUNET_GNSRECORD_Data *rd)
- {
- struct GNUNET_TIME_Absolute abs_expiration_time;
- struct GNUNET_TIME_Relative rel_expiration_time;
- const char *value;
- const char *record_type;
- const char *expiration_time;
- int private;
- int supplemental;
- int rel_exp;
- int shadow;
- int unpack_state = 0;
- // interpret single gns record
- unpack_state = json_unpack (data,
- "{s:s, s:s, s:s, s:b, s:b, s:b, s:b}",
- GNUNET_JSON_GNSRECORD_VALUE,
- &value,
- GNUNET_JSON_GNSRECORD_TYPE,
- &record_type,
- GNUNET_JSON_GNSRECORD_EXPIRATION_TIME,
- &expiration_time,
- GNUNET_JSON_GNSRECORD_FLAG_PRIVATE,
- &private,
- GNUNET_JSON_GNSRECORD_FLAG_SUPPLEMENTAL,
- &supplemental,
- GNUNET_JSON_GNSRECORD_FLAG_RELATIVE,
- &rel_exp,
- GNUNET_JSON_GNSRECORD_FLAG_SHADOW,
- &shadow);
- if (0 != unpack_state)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Error gnsdata object has a wrong format!\n");
- return GNUNET_SYSERR;
- }
- rd->record_type = GNUNET_GNSRECORD_typename_to_number (record_type);
- if (UINT32_MAX == rd->record_type)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unsupported type\n");
- return GNUNET_SYSERR;
- }
- if (GNUNET_OK != GNUNET_GNSRECORD_string_to_value (rd->record_type,
- value,
- (void **) &rd->data,
- &rd->data_size))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Value invalid for record type\n");
- return GNUNET_SYSERR;
- }
- if (0 == strcmp (expiration_time, GNUNET_JSON_GNSRECORD_NEVER))
- {
- rd->expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us;
- }
- else if ((1 != rel_exp) &&
- (GNUNET_OK ==
- GNUNET_STRINGS_fancy_time_to_absolute (expiration_time,
- &abs_expiration_time)))
- {
- rd->expiration_time = abs_expiration_time.abs_value_us;
- }
- else if (GNUNET_OK ==
- GNUNET_STRINGS_fancy_time_to_relative (expiration_time,
- &rel_expiration_time))
- {
- rd->flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
- rd->expiration_time = rel_expiration_time.rel_value_us;
- }
- else
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Expiration time invalid\n");
- return GNUNET_SYSERR;
- }
- if (1 == private)
- rd->flags |= GNUNET_GNSRECORD_RF_PRIVATE;
- if (1 == supplemental)
- rd->flags |= GNUNET_GNSRECORD_RF_SUPPLEMENTAL;
- if (1 == shadow)
- rd->flags |= GNUNET_GNSRECORD_RF_SHADOW_RECORD;
- return GNUNET_OK;
- }
- /**
- * Parse given JSON object to gns record
- *
- * @param cls closure, NULL
- * @param root the json object representing data
- * @param spec where to write the data
- * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
- */
- static int
- parse_record_data (struct GnsRecordInfo *gnsrecord_info, json_t *data)
- {
- GNUNET_assert (NULL != data);
- if (! json_is_array (data))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Error gns record data JSON is not an array!\n");
- return GNUNET_SYSERR;
- }
- *(gnsrecord_info->rd_count) = json_array_size (data);
- *(gnsrecord_info->rd) = GNUNET_malloc (sizeof(struct GNUNET_GNSRECORD_Data)
- * json_array_size (data));
- size_t index;
- json_t *value;
- json_array_foreach (data, index, value)
- {
- if (GNUNET_OK != parse_record (value, &(*(gnsrecord_info->rd))[index]))
- return GNUNET_SYSERR;
- }
- return GNUNET_OK;
- }
- static int
- parse_gnsrecordobject (void *cls,
- json_t *root,
- struct GNUNET_JSON_Specification *spec)
- {
- struct GnsRecordInfo *gnsrecord_info;
- int unpack_state = 0;
- const char *name;
- json_t *data;
- GNUNET_assert (NULL != root);
- if (! json_is_object (root))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Error record JSON is not an object!\n");
- return GNUNET_SYSERR;
- }
- // interpret single gns record
- unpack_state = json_unpack (root,
- "{s:s, s:o!}",
- GNUNET_JSON_GNSRECORD_RECORD_NAME,
- &name,
- GNUNET_JSON_GNSRECORD_RECORD_DATA,
- &data);
- if (0 != unpack_state)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Error namestore records object has a wrong format!\n");
- return GNUNET_SYSERR;
- }
- gnsrecord_info = (struct GnsRecordInfo *) spec->ptr;
- *(gnsrecord_info->name) = GNUNET_strdup (name);
- if (GNUNET_OK != parse_record_data (gnsrecord_info, data))
- {
- cleanup_recordinfo (gnsrecord_info);
- return GNUNET_SYSERR;
- }
- return GNUNET_OK;
- }
- /**
- * Cleanup data left from parsing the record.
- *
- * @param cls closure, NULL
- * @param[out] spec where to free the data
- */
- static void
- clean_gnsrecordobject (void *cls, struct GNUNET_JSON_Specification *spec)
- {
- struct GnsRecordInfo *gnsrecord_info = (struct GnsRecordInfo *) spec->ptr;
- GNUNET_free (gnsrecord_info);
- }
- /**
- * JSON Specification for GNS Records.
- *
- * @param gnsrecord_object struct of GNUNET_GNSRECORD_Data to fill
- * @return JSON Specification
- */
- struct GNUNET_JSON_Specification
- GNUNET_JSON_spec_gnsrecord (struct GNUNET_GNSRECORD_Data **rd,
- unsigned int *rd_count,
- char **name)
- {
- struct GnsRecordInfo *gnsrecord_info = GNUNET_new (struct GnsRecordInfo);
- gnsrecord_info->rd = rd;
- gnsrecord_info->name = name;
- gnsrecord_info->rd_count = rd_count;
- struct GNUNET_JSON_Specification ret = { .parser = &parse_gnsrecordobject,
- .cleaner = &clean_gnsrecordobject,
- .cls = NULL,
- .field = NULL,
- .ptr = (struct GnsRecordInfo *)
- gnsrecord_info,
- .ptr_size = 0,
- .size_ptr = NULL };
- return ret;
- }
|