anastasis_api_redux_serialize.c (28861B)
1 /* 2 This file is part of Anastasis 3 Copyright (C) 2020, 2021, 2022 Anastasis SARL 4 5 Anastasis is free software; you can redistribute it and/or modify it under the 6 terms of the GNU General Public License as published by the Free Software 7 Foundation; either version 3, or (at your option) any later version. 8 9 Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY 10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 11 A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 13 You should have received a copy of the GNU General Public License along with 14 Anastasis; see the file COPYING.GPL. If not, see <http://www.gnu.org/licenses/> 15 */ 16 /** 17 * @file reducer/anastasis_api_redux_serialize.c 18 * @brief write a reducer state back out as JSON 19 * @author Christian Grothoff 20 * 21 * The inverse of anastasis_api_redux_parse.c. Fields that are not set are 22 * omitted rather than serialized as null, matching what the JSON-based 23 * implementation this replaced produced. 24 */ 25 #include "platform.h" 26 #include "anastasis_redux.h" 27 #include "anastasis_api_redux.h" 28 #include "anastasis_api_redux_state.h" 29 #include <taler/taler_json_lib.h> 30 31 32 /** 33 * Add @a val to @a obj under @a key, unless @a val is NULL. 34 * 35 * @param[in,out] obj object to extend 36 * @param key field name 37 * @param[in] val value to add, reference is consumed 38 */ 39 static void 40 set_opt (json_t *obj, 41 const char *key, 42 json_t *val) 43 { 44 if (NULL == val) 45 return; 46 GNUNET_assert (0 == 47 json_object_set_new (obj, 48 key, 49 val)); 50 } 51 52 53 /** 54 * Serialize the `continents` array. 55 * 56 * @param common state to serialize 57 * @return JSON array 58 */ 59 static json_t * 60 serialize_continents (const struct ANASTASIS_ReduxCommon *common) 61 { 62 json_t *arr; 63 64 arr = json_array (); 65 GNUNET_assert (NULL != arr); 66 for (unsigned int i = 0; i < common->continents_len; i++) 67 { 68 const struct ANASTASIS_ReduxContinent *c = &common->continents[i]; 69 json_t *co; 70 71 if (c->bare) 72 { 73 GNUNET_assert (0 == 74 json_array_append_new (arr, 75 json_string (c->name))); 76 continue; 77 } 78 co = GNUNET_JSON_PACK ( 79 GNUNET_JSON_pack_string ("name", 80 c->name)); 81 set_opt (co, 82 "name_i18n", 83 json_incref (c->name_i18n)); 84 GNUNET_assert (0 == 85 json_array_append_new (arr, 86 co)); 87 } 88 return arr; 89 } 90 91 92 /** 93 * Serialize the `countries` array. 94 * 95 * @param common state to serialize 96 * @return JSON array 97 */ 98 static json_t * 99 serialize_countries (const struct ANASTASIS_ReduxCommon *common) 100 { 101 json_t *arr; 102 103 arr = json_array (); 104 GNUNET_assert (NULL != arr); 105 for (unsigned int i = 0; i < common->countries_len; i++) 106 { 107 const struct ANASTASIS_ReduxCountry *c = &common->countries[i]; 108 json_t *co; 109 110 co = GNUNET_JSON_PACK ( 111 GNUNET_JSON_pack_string ("code", 112 c->code), 113 GNUNET_JSON_pack_string ("name", 114 c->name), 115 GNUNET_JSON_pack_string ("continent", 116 c->continent), 117 GNUNET_JSON_pack_conditional ( 118 NULL != c->call_code, 119 GNUNET_JSON_pack_string ("call_code", 120 c->call_code))); 121 set_opt (co, 122 "name_i18n", 123 json_incref (c->name_i18n)); 124 set_opt (co, 125 "continent_i18n", 126 json_incref (c->continent_i18n)); 127 if (NULL != c->currency) 128 set_opt (co, 129 "currency", 130 json_string (c->currency)); 131 GNUNET_assert (0 == 132 json_array_append_new (arr, 133 co)); 134 } 135 return arr; 136 } 137 138 139 /** 140 * Serialize the `required_attributes` array. 141 * 142 * @param common state to serialize 143 * @return JSON array 144 */ 145 static json_t * 146 serialize_required_attributes (const struct ANASTASIS_ReduxCommon *common) 147 { 148 json_t *arr; 149 150 arr = json_array (); 151 GNUNET_assert (NULL != arr); 152 for (unsigned int i = 0; i < common->required_attributes_len; i++) 153 { 154 const struct ANASTASIS_ReduxAttributeSpec *a 155 = &common->required_attributes[i]; 156 json_t *ao; 157 158 ao = GNUNET_JSON_PACK ( 159 GNUNET_JSON_pack_string ("type", 160 a->type), 161 GNUNET_JSON_pack_string ("name", 162 a->name), 163 GNUNET_JSON_pack_string ("label", 164 a->label), 165 GNUNET_JSON_pack_string ("widget", 166 a->widget), 167 GNUNET_JSON_pack_conditional ( 168 NULL != a->uuid, 169 GNUNET_JSON_pack_string ("uuid", 170 a->uuid)), 171 GNUNET_JSON_pack_conditional ( 172 NULL != a->tooltip, 173 GNUNET_JSON_pack_string ("tooltip", 174 a->tooltip)), 175 GNUNET_JSON_pack_conditional ( 176 NULL != a->validation_regex, 177 GNUNET_JSON_pack_string ("validation-regex", 178 a->validation_regex)), 179 GNUNET_JSON_pack_conditional ( 180 NULL != a->validation_logic, 181 GNUNET_JSON_pack_string ("validation-logic", 182 a->validation_logic)), 183 GNUNET_JSON_pack_conditional ( 184 NULL != a->autocomplete, 185 GNUNET_JSON_pack_string ("autocomplete", 186 a->autocomplete)), 187 GNUNET_JSON_pack_conditional ( 188 a->have_optional, 189 GNUNET_JSON_pack_bool ("optional", 190 a->optional))); 191 set_opt (ao, 192 "label_i18n", 193 json_incref (a->label_i18n)); 194 GNUNET_assert (0 == 195 json_array_append_new (arr, 196 ao)); 197 } 198 return arr; 199 } 200 201 202 /** 203 * Serialize the `authentication_providers` object. 204 * 205 * @param common state to serialize 206 * @return JSON object 207 */ 208 static json_t * 209 serialize_providers (const struct ANASTASIS_ReduxCommon *common) 210 { 211 json_t *obj; 212 213 obj = json_object (); 214 GNUNET_assert (NULL != obj); 215 for (unsigned int i = 0; i < common->providers_len; i++) 216 { 217 const struct ANASTASIS_ReduxProvider *p = &common->providers[i]; 218 const char *status; 219 json_t *po; 220 221 switch (p->status) 222 { 223 case ANASTASIS_RPS_NOT_CONTACTED: 224 status = "not-contacted"; 225 break; 226 case ANASTASIS_RPS_OK: 227 status = "ok"; 228 break; 229 case ANASTASIS_RPS_DISABLED: 230 status = "disabled"; 231 break; 232 case ANASTASIS_RPS_ERROR: 233 status = "error"; 234 break; 235 default: 236 GNUNET_assert (0); 237 } 238 if (ANASTASIS_RPS_ERROR == p->status) 239 { 240 po = GNUNET_JSON_PACK ( 241 GNUNET_JSON_pack_string ("status", 242 status), 243 GNUNET_JSON_pack_uint64 ("error_code", 244 p->error.ec), 245 GNUNET_JSON_pack_uint64 ("http_status", 246 p->error.http_status)); 247 } 248 else if (! p->have_config) 249 { 250 po = GNUNET_JSON_PACK ( 251 GNUNET_JSON_pack_string ("status", 252 status)); 253 } 254 else 255 { 256 const struct ANASTASIS_ReduxProviderConfig *cfg = &p->config; 257 json_t *methods; 258 259 methods = json_array (); 260 GNUNET_assert (NULL != methods); 261 for (unsigned int j = 0; j < cfg->methods_len; j++) 262 { 263 const struct ANASTASIS_ReduxMethodSpec *ms = &cfg->methods[j]; 264 265 GNUNET_assert (0 == 266 json_array_append_new ( 267 methods, 268 GNUNET_JSON_PACK ( 269 GNUNET_JSON_pack_string ("type", 270 ms->type), 271 TALER_JSON_pack_amount ("usage_fee", 272 &ms->usage_fee)))); 273 } 274 po = GNUNET_JSON_PACK ( 275 GNUNET_JSON_pack_string ("status", 276 status), 277 GNUNET_JSON_pack_array_steal ("methods", 278 methods), 279 TALER_JSON_pack_amount ("annual_fee", 280 &cfg->annual_fee), 281 TALER_JSON_pack_amount ("truth_upload_fee", 282 &cfg->truth_upload_fee), 283 TALER_JSON_pack_amount ("liability_limit", 284 &cfg->liability_limit), 285 GNUNET_JSON_pack_string ("business_name", 286 cfg->business_name), 287 GNUNET_JSON_pack_uint64 ("storage_limit_in_megabytes", 288 cfg->storage_limit_in_megabytes), 289 GNUNET_JSON_pack_data_auto ("provider_salt", 290 &cfg->provider_salt), 291 GNUNET_JSON_pack_uint64 ("http_status", 292 cfg->http_status), 293 GNUNET_JSON_pack_conditional ( 294 NULL != cfg->currency, 295 GNUNET_JSON_pack_string ("currency", 296 cfg->currency))); 297 } 298 GNUNET_assert (0 == 299 json_object_set_new (obj, 300 p->url.url, 301 po)); 302 } 303 return obj; 304 } 305 306 307 /** 308 * Add the fields shared by the backup and recovery variants to @a obj. 309 * 310 * @param[in,out] obj object to extend 311 * @param common state to serialize 312 */ 313 static void 314 serialize_common (json_t *obj, 315 const struct ANASTASIS_ReduxCommon *common) 316 { 317 if (common->have_continents) 318 set_opt (obj, 319 "continents", 320 serialize_continents (common)); 321 if (common->have_countries) 322 set_opt (obj, 323 "countries", 324 serialize_countries (common)); 325 if (common->have_required_attributes) 326 set_opt (obj, 327 "required_attributes", 328 serialize_required_attributes (common)); 329 if (common->have_providers) 330 set_opt (obj, 331 "authentication_providers", 332 serialize_providers (common)); 333 if (NULL != common->identity_attributes) 334 set_opt (obj, 335 "identity_attributes", 336 json_incref (common->identity_attributes)); 337 if (common->have_currencies) 338 { 339 json_t *arr; 340 341 arr = json_array (); 342 GNUNET_assert (NULL != arr); 343 for (unsigned int i = 0; i < common->currencies_len; i++) 344 GNUNET_assert (0 == 345 json_array_append_new ( 346 arr, 347 json_string (common->currencies[i]))); 348 set_opt (obj, 349 "currencies", 350 arr); 351 } 352 if (NULL != common->selected_continent) 353 set_opt (obj, 354 "selected_continent", 355 json_string (common->selected_continent)); 356 if (NULL != common->selected_country) 357 set_opt (obj, 358 "selected_country", 359 json_string (common->selected_country)); 360 } 361 362 363 /** 364 * Serialize the backup-specific fields into @a obj. 365 * 366 * @param[in,out] obj object to extend 367 * @param b backup state to serialize 368 */ 369 static void 370 serialize_backup (json_t *obj, 371 const struct ANASTASIS_ReduxBackup *b) 372 { 373 if (b->have_authentication_methods) 374 { 375 json_t *arr; 376 377 arr = json_array (); 378 GNUNET_assert (NULL != arr); 379 for (unsigned int i = 0; i < b->authentication_methods_len; i++) 380 { 381 const struct ANASTASIS_ReduxAuthMethod *am 382 = &b->authentication_methods[i]; 383 384 GNUNET_assert (0 == 385 json_array_append_new ( 386 arr, 387 GNUNET_JSON_PACK ( 388 GNUNET_JSON_pack_string ("type", 389 am->type), 390 GNUNET_JSON_pack_string ("instructions", 391 am->instructions), 392 GNUNET_JSON_pack_data_varsize ("challenge", 393 am->challenge, 394 am->challenge_size), 395 GNUNET_JSON_pack_conditional ( 396 NULL != am->mime_type, 397 GNUNET_JSON_pack_string ("mime_type", 398 am->mime_type))))); 399 } 400 set_opt (obj, 401 "authentication_methods", 402 arr); 403 } 404 if (b->have_policies) 405 { 406 json_t *arr; 407 408 arr = json_array (); 409 GNUNET_assert (NULL != arr); 410 for (unsigned int i = 0; i < b->policies_len; i++) 411 { 412 const struct ANASTASIS_ReduxPolicy *p = &b->policies[i]; 413 json_t *methods; 414 415 methods = json_array (); 416 GNUNET_assert (NULL != methods); 417 for (unsigned int j = 0; j < p->methods_len; j++) 418 { 419 const struct ANASTASIS_ReduxPolicyMethod *pm = &p->methods[j]; 420 json_t *mo; 421 422 mo = GNUNET_JSON_PACK ( 423 GNUNET_JSON_pack_uint64 ("authentication_method", 424 pm->authentication_method.idx), 425 GNUNET_JSON_pack_string ("provider", 426 pm->provider.url)); 427 if (NULL != pm->truth) 428 { 429 json_t *truth = ANASTASIS_truth_to_json (pm->truth); 430 431 GNUNET_assert (NULL != truth); 432 GNUNET_assert (0 == 433 json_object_set_new (truth, 434 "upload_status", 435 json_integer ( 436 pm->upload_status))); 437 GNUNET_assert (0 == 438 json_object_set_new (mo, 439 "truth", 440 truth)); 441 } 442 GNUNET_assert (0 == 443 json_array_append_new (methods, 444 mo)); 445 } 446 GNUNET_assert (0 == 447 json_array_append_new ( 448 arr, 449 GNUNET_JSON_PACK ( 450 GNUNET_JSON_pack_conditional ( 451 p->have_recovery_cost, 452 TALER_JSON_pack_amount ("recovery_cost", 453 &p->recovery_cost)), 454 GNUNET_JSON_pack_array_steal ("methods", 455 methods)))); 456 } 457 set_opt (obj, 458 "policies", 459 arr); 460 } 461 if (b->have_policy_providers) 462 { 463 json_t *arr; 464 465 arr = json_array (); 466 GNUNET_assert (NULL != arr); 467 for (unsigned int i = 0; i < b->policy_providers_len; i++) 468 { 469 const struct ANASTASIS_ReduxPolicyProvider *pp 470 = &b->policy_providers[i]; 471 472 GNUNET_assert (0 == 473 json_array_append_new ( 474 arr, 475 GNUNET_JSON_PACK ( 476 GNUNET_JSON_pack_string ("provider_url", 477 pp->provider_url.url), 478 GNUNET_JSON_pack_conditional ( 479 pp->have_payment_secret, 480 GNUNET_JSON_pack_data_auto ( 481 "payment_secret", 482 &pp->payment_secret))))); 483 } 484 set_opt (obj, 485 "policy_providers", 486 arr); 487 } 488 if (b->have_upload_fees) 489 { 490 json_t *arr; 491 492 arr = json_array (); 493 GNUNET_assert (NULL != arr); 494 for (unsigned int i = 0; i < b->upload_fees_len; i++) 495 GNUNET_assert (0 == 496 json_array_append_new ( 497 arr, 498 GNUNET_JSON_PACK ( 499 TALER_JSON_pack_amount ("fee", 500 &b->upload_fees[i])))); 501 set_opt (obj, 502 "upload_fees", 503 arr); 504 } 505 if (b->have_payments) 506 { 507 json_t *arr; 508 509 arr = json_array (); 510 GNUNET_assert (NULL != arr); 511 for (unsigned int i = 0; i < b->payments_len; i++) 512 GNUNET_assert (0 == 513 json_array_append_new (arr, 514 json_string (b->payments[i]))); 515 set_opt (obj, 516 "payments", 517 arr); 518 } 519 if (b->have_policy_payment_requests) 520 { 521 json_t *arr; 522 523 arr = json_array (); 524 GNUNET_assert (NULL != arr); 525 for (unsigned int i = 0; i < b->policy_payment_requests_len; i++) 526 { 527 const struct ANASTASIS_ReduxPolicyPaymentRequest *ppr 528 = &b->policy_payment_requests[i]; 529 530 GNUNET_assert (0 == 531 json_array_append_new ( 532 arr, 533 GNUNET_JSON_PACK ( 534 GNUNET_JSON_pack_string ("payto", 535 ppr->payto), 536 GNUNET_JSON_pack_string ("provider", 537 ppr->provider.url)))); 538 } 539 set_opt (obj, 540 "policy_payment_requests", 541 arr); 542 } 543 if (b->have_success_details) 544 { 545 json_t *sd; 546 547 sd = json_object (); 548 GNUNET_assert (NULL != sd); 549 for (unsigned int i = 0; i < b->success_details_len; i++) 550 { 551 const struct ANASTASIS_ReduxSuccessDetail *d = &b->success_details[i]; 552 553 GNUNET_assert (0 == 554 json_object_set_new ( 555 sd, 556 d->provider_url.url, 557 GNUNET_JSON_PACK ( 558 GNUNET_JSON_pack_uint64 ("policy_version", 559 d->policy_version), 560 GNUNET_JSON_pack_timestamp ("policy_expiration", 561 d->policy_expiration)))); 562 } 563 set_opt (obj, 564 "success_details", 565 sd); 566 } 567 if (NULL != b->core_secret) 568 set_opt (obj, 569 "core_secret", 570 json_incref (b->core_secret)); 571 if (NULL != b->secret_name) 572 set_opt (obj, 573 "secret_name", 574 json_string (b->secret_name)); 575 if (b->have_expiration) 576 set_opt (obj, 577 "expiration", 578 GNUNET_JSON_from_timestamp (b->expiration)); 579 if (b->have_pay_arguments) 580 { 581 json_t *pa; 582 583 pa = json_object (); 584 GNUNET_assert (NULL != pa); 585 if (b->pay_arguments.have_timeout) 586 set_opt (pa, 587 "timeout", 588 GNUNET_JSON_from_time_rel (b->pay_arguments.timeout)); 589 set_opt (obj, 590 "pay_arguments", 591 pa); 592 } 593 } 594 595 596 /** 597 * Serialize the recovery information @a ri. 598 * 599 * @param ri recovery information to serialize 600 * @return JSON object 601 */ 602 static json_t * 603 serialize_recovery_info (const struct ANASTASIS_ReduxRecoveryInfo *ri) 604 { 605 json_t *challenges; 606 json_t *policies; 607 608 challenges = json_array (); 609 GNUNET_assert (NULL != challenges); 610 for (unsigned int i = 0; i < ri->challenges_len; i++) 611 { 612 const struct ANASTASIS_ReduxChallengeInfo *ci = &ri->challenges[i]; 613 614 GNUNET_assert (0 == 615 json_array_append_new ( 616 challenges, 617 GNUNET_JSON_PACK ( 618 GNUNET_JSON_pack_data_auto ("uuid", 619 &ci->uuid), 620 GNUNET_JSON_pack_string ("type", 621 ci->type), 622 GNUNET_JSON_pack_string ("uuid-display", 623 ANASTASIS_CRYPTO_uuid2s ( 624 &ci->uuid)), 625 GNUNET_JSON_pack_string ("instructions", 626 ci->instructions), 627 GNUNET_JSON_pack_conditional ( 628 NULL != ci->answer, 629 GNUNET_JSON_pack_string ("answer", 630 ci->answer)), 631 GNUNET_JSON_pack_conditional ( 632 ci->have_payment_secret, 633 GNUNET_JSON_pack_data_auto ("payment_secret", 634 &ci->payment_secret))))); 635 } 636 policies = json_array (); 637 GNUNET_assert (NULL != policies); 638 for (unsigned int i = 0; i < ri->policies_len; i++) 639 { 640 const struct ANASTASIS_ReduxRecoveryPolicy *p = &ri->policies[i]; 641 json_t *pa; 642 643 pa = json_array (); 644 GNUNET_assert (NULL != pa); 645 for (unsigned int j = 0; j < p->uuids_len; j++) 646 GNUNET_assert (0 == 647 json_array_append_new ( 648 pa, 649 GNUNET_JSON_PACK ( 650 GNUNET_JSON_pack_data_auto ("uuid", 651 &p->uuids[j])))); 652 GNUNET_assert (0 == 653 json_array_append_new (policies, 654 pa)); 655 } 656 return GNUNET_JSON_PACK ( 657 GNUNET_JSON_pack_array_steal ("challenges", 658 challenges), 659 GNUNET_JSON_pack_array_steal ("policies", 660 policies), 661 GNUNET_JSON_pack_allow_null ( 662 GNUNET_JSON_pack_string ("secret_name", 663 ri->secret_name)), 664 GNUNET_JSON_pack_string ("provider_url", 665 ri->provider_url.url), 666 GNUNET_JSON_pack_uint64 ("version", 667 ri->version)); 668 } 669 670 671 /** 672 * Serialize one challenge feedback entry. 673 * 674 * @param fb feedback to serialize 675 * @return JSON object 676 */ 677 static json_t * 678 serialize_feedback (const struct ANASTASIS_ReduxFeedback *fb) 679 { 680 json_t *fo; 681 682 switch (fb->status) 683 { 684 case ANASTASIS_RFS_CODE_IN_FILE: 685 fo = GNUNET_JSON_PACK ( 686 GNUNET_JSON_pack_string ("state", 687 "code-in-file"), 688 GNUNET_JSON_pack_string ("filename", 689 fb->details.code_in_file.filename)); 690 break; 691 case ANASTASIS_RFS_SEND_TO_ADDRESS: 692 fo = GNUNET_JSON_PACK ( 693 GNUNET_JSON_pack_string ("state", 694 "send-to-address"), 695 GNUNET_JSON_pack_conditional ( 696 NULL != fb->details.send_to_address.address_hint, 697 GNUNET_JSON_pack_string ("address_hint", 698 fb->details.send_to_address.address_hint))); 699 break; 700 case ANASTASIS_RFS_TALER_PAYMENT: 701 fo = GNUNET_JSON_PACK ( 702 GNUNET_JSON_pack_string ("state", 703 "taler-payment"), 704 GNUNET_JSON_pack_string ("taler_pay_uri", 705 fb->details.taler_payment.taler_pay_uri), 706 GNUNET_JSON_pack_string ("provider", 707 fb->details.taler_payment.provider.url), 708 GNUNET_JSON_pack_data_auto ("payment_secret", 709 &fb->details.taler_payment.payment_secret)); 710 break; 711 case ANASTASIS_RFS_SERVER_FAILURE: 712 fo = GNUNET_JSON_PACK ( 713 GNUNET_JSON_pack_string ("state", 714 "server-failure"), 715 GNUNET_JSON_pack_uint64 ("http_status", 716 fb->details.server_failure.http_status), 717 GNUNET_JSON_pack_uint64 ("error_code", 718 fb->details.server_failure.ec)); 719 break; 720 case ANASTASIS_RFS_TRUTH_UNKNOWN: 721 fo = GNUNET_JSON_PACK ( 722 GNUNET_JSON_pack_string ("state", 723 "truth-unknown"), 724 GNUNET_JSON_pack_uint64 ("http_status", 725 fb->details.server_failure.http_status), 726 GNUNET_JSON_pack_uint64 ("error_code", 727 fb->details.server_failure.ec)); 728 break; 729 case ANASTASIS_RFS_IBAN_INSTRUCTIONS: 730 fo = GNUNET_JSON_PACK ( 731 GNUNET_JSON_pack_string ("state", 732 "iban-instructions"), 733 GNUNET_JSON_pack_string ("target_iban", 734 fb->details.iban_instructions.target_iban), 735 GNUNET_JSON_pack_string ( 736 "target_business_name", 737 fb->details.iban_instructions.target_business_name), 738 GNUNET_JSON_pack_string ( 739 "wire_transfer_subject", 740 fb->details.iban_instructions.wire_transfer_subject), 741 TALER_JSON_pack_amount ("challenge_amount", 742 &fb->details.iban_instructions.amount)); 743 break; 744 case ANASTASIS_RFS_SOLVED: 745 fo = GNUNET_JSON_PACK ( 746 GNUNET_JSON_pack_string ("state", 747 "solved")); 748 break; 749 case ANASTASIS_RFS_INCORRECT_ANSWER: 750 fo = GNUNET_JSON_PACK ( 751 GNUNET_JSON_pack_string ("state", 752 "incorrect-answer"), 753 GNUNET_JSON_pack_uint64 ("error_code", 754 fb->details.incorrect_answer.ec)); 755 break; 756 case ANASTASIS_RFS_RATE_LIMIT_EXCEEDED: 757 fo = GNUNET_JSON_PACK ( 758 GNUNET_JSON_pack_string ("state", 759 "rate-limit-exceeded"), 760 GNUNET_JSON_pack_uint64 ( 761 "request_limit", 762 fb->details.rate_limit_exceeded.request_limit), 763 GNUNET_JSON_pack_time_rel ( 764 "request_frequency", 765 fb->details.rate_limit_exceeded.request_frequency), 766 GNUNET_JSON_pack_uint64 ("error_code", 767 fb->details.rate_limit_exceeded.ec)); 768 break; 769 default: 770 GNUNET_assert (0); 771 } 772 if (NULL != fb->display_hint) 773 set_opt (fo, 774 "display_hint", 775 json_string (fb->display_hint)); 776 return fo; 777 } 778 779 780 /** 781 * Serialize the recovery-specific fields into @a obj. 782 * 783 * @param[in,out] obj object to extend 784 * @param rr recovery state to serialize 785 */ 786 static void 787 serialize_recovery (json_t *obj, 788 const struct ANASTASIS_ReduxRecovery *rr) 789 { 790 if (NULL != rr->ri) 791 set_opt (obj, 792 "recovery_information", 793 serialize_recovery_info (rr->ri)); 794 if (NULL != rr->r) 795 set_opt (obj, 796 "recovery_document", 797 ANASTASIS_recovery_serialize (rr->r)); 798 if (rr->have_challenge_feedback) 799 { 800 json_t *cf; 801 802 cf = json_object (); 803 GNUNET_assert (NULL != cf); 804 for (unsigned int i = 0; i < rr->challenge_feedback_len; i++) 805 { 806 const struct ANASTASIS_ReduxFeedback *fb = &rr->challenge_feedback[i]; 807 char uuid[sizeof (fb->uuid) * 2]; 808 char *end; 809 810 end = GNUNET_STRINGS_data_to_string (&fb->uuid, 811 sizeof (fb->uuid), 812 uuid, 813 sizeof (uuid)); 814 GNUNET_assert (NULL != end); 815 *end = '\0'; 816 GNUNET_assert (0 == 817 json_object_set_new (cf, 818 uuid, 819 serialize_feedback (fb))); 820 } 821 set_opt (obj, 822 "challenge_feedback", 823 cf); 824 } 825 if (rr->have_selected_challenge) 826 set_opt (obj, 827 "selected_challenge_uuid", 828 GNUNET_JSON_from_data_auto (&rr->selected_challenge)); 829 if (NULL != rr->core_secret) 830 set_opt (obj, 831 "core_secret", 832 json_incref (rr->core_secret)); 833 } 834 835 836 json_t * 837 ANASTASIS_REDUX_state_serialize_ (const struct ANASTASIS_ReduxState *rs) 838 { 839 json_t *obj; 840 841 switch (rs->type) 842 { 843 case ANASTASIS_RT_BACKUP: 844 obj = GNUNET_JSON_PACK ( 845 GNUNET_JSON_pack_string ("reducer_type", 846 "backup"), 847 GNUNET_JSON_pack_string ("backup_state", 848 ANASTASIS_backup_state_to_string_ ( 849 rs->details.backup.state))); 850 serialize_common (obj, 851 &rs->common); 852 serialize_backup (obj, 853 &rs->details.backup); 854 return obj; 855 case ANASTASIS_RT_RECOVERY: 856 obj = GNUNET_JSON_PACK ( 857 GNUNET_JSON_pack_string ("reducer_type", 858 "recovery"), 859 GNUNET_JSON_pack_string ("recovery_state", 860 ANASTASIS_recovery_state_to_string_ ( 861 rs->details.recovery.state))); 862 serialize_common (obj, 863 &rs->common); 864 serialize_recovery (obj, 865 &rs->details.recovery); 866 return obj; 867 case ANASTASIS_RT_ERROR: 868 return GNUNET_JSON_PACK ( 869 GNUNET_JSON_pack_string ("reducer_type", 870 "error"), 871 GNUNET_JSON_pack_uint64 ("code", 872 rs->details.error.code), 873 GNUNET_JSON_pack_allow_null ( 874 GNUNET_JSON_pack_string ("hint", 875 rs->details.error.hint)), 876 GNUNET_JSON_pack_allow_null ( 877 GNUNET_JSON_pack_string ("detail", 878 rs->details.error.detail))); 879 } 880 GNUNET_assert (0); 881 return NULL; 882 } 883 884 885 /* end of anastasis_api_redux_serialize.c */