anastasis_api_redux_serialize.c (30019B)
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 TALER_JSON_pack_amount_list ("usage_fees", 274 &ms->usage_fees)))); 275 } 276 { 277 json_t *currencies = json_array (); 278 279 GNUNET_assert (NULL != currencies); 280 for (unsigned int j = 0; j < cfg->currencies_len; j++) 281 GNUNET_assert (0 == 282 json_array_append_new ( 283 currencies, 284 json_string (cfg->currencies[j]))); 285 po = GNUNET_JSON_PACK ( 286 GNUNET_JSON_pack_string ("status", 287 status), 288 GNUNET_JSON_pack_array_steal ("methods", 289 methods), 290 GNUNET_JSON_pack_array_steal ("currencies", 291 currencies), 292 TALER_JSON_pack_amount ("annual_fee", 293 &cfg->annual_fee), 294 TALER_JSON_pack_amount_list ("annual_fees", 295 &cfg->annual_fees), 296 TALER_JSON_pack_amount ("truth_upload_fee", 297 &cfg->truth_upload_fee), 298 TALER_JSON_pack_amount_list ("truth_upload_fees", 299 &cfg->truth_upload_fees), 300 TALER_JSON_pack_amount ("liability_limit", 301 &cfg->liability_limit), 302 TALER_JSON_pack_amount_list ("liability_limits", 303 &cfg->liability_limits), 304 GNUNET_JSON_pack_string ("business_name", 305 cfg->business_name), 306 GNUNET_JSON_pack_uint64 ("storage_limit_in_megabytes", 307 cfg->storage_limit_in_megabytes), 308 GNUNET_JSON_pack_data_auto ("provider_salt", 309 &cfg->provider_salt), 310 GNUNET_JSON_pack_uint64 ("http_status", 311 cfg->http_status), 312 GNUNET_JSON_pack_conditional ( 313 NULL != cfg->currency, 314 GNUNET_JSON_pack_string ("currency", 315 cfg->currency))); 316 } 317 } 318 GNUNET_assert (0 == 319 json_object_set_new (obj, 320 p->url.url, 321 po)); 322 } 323 return obj; 324 } 325 326 327 /** 328 * Add the fields shared by the backup and recovery variants to @a obj. 329 * 330 * @param[in,out] obj object to extend 331 * @param common state to serialize 332 */ 333 static void 334 serialize_common (json_t *obj, 335 const struct ANASTASIS_ReduxCommon *common) 336 { 337 if (common->have_continents) 338 set_opt (obj, 339 "continents", 340 serialize_continents (common)); 341 if (common->have_countries) 342 set_opt (obj, 343 "countries", 344 serialize_countries (common)); 345 if (common->have_required_attributes) 346 set_opt (obj, 347 "required_attributes", 348 serialize_required_attributes (common)); 349 if (common->have_providers) 350 set_opt (obj, 351 "authentication_providers", 352 serialize_providers (common)); 353 if (NULL != common->identity_attributes) 354 set_opt (obj, 355 "identity_attributes", 356 json_incref (common->identity_attributes)); 357 if (common->have_currencies) 358 { 359 json_t *arr; 360 361 arr = json_array (); 362 GNUNET_assert (NULL != arr); 363 for (unsigned int i = 0; i < common->currencies_len; i++) 364 GNUNET_assert (0 == 365 json_array_append_new ( 366 arr, 367 json_string (common->currencies[i]))); 368 set_opt (obj, 369 "currencies", 370 arr); 371 } 372 if (NULL != common->selected_continent) 373 set_opt (obj, 374 "selected_continent", 375 json_string (common->selected_continent)); 376 if (NULL != common->selected_country) 377 set_opt (obj, 378 "selected_country", 379 json_string (common->selected_country)); 380 if (NULL != common->preferred_currency) 381 set_opt (obj, 382 "preferred_currency", 383 json_string (common->preferred_currency)); 384 } 385 386 387 /** 388 * Serialize the backup-specific fields into @a obj. 389 * 390 * @param[in,out] obj object to extend 391 * @param b backup state to serialize 392 */ 393 static void 394 serialize_backup (json_t *obj, 395 const struct ANASTASIS_ReduxBackup *b) 396 { 397 if (b->have_authentication_methods) 398 { 399 json_t *arr; 400 401 arr = json_array (); 402 GNUNET_assert (NULL != arr); 403 for (unsigned int i = 0; i < b->authentication_methods_len; i++) 404 { 405 const struct ANASTASIS_ReduxAuthMethod *am 406 = &b->authentication_methods[i]; 407 408 GNUNET_assert (0 == 409 json_array_append_new ( 410 arr, 411 GNUNET_JSON_PACK ( 412 GNUNET_JSON_pack_string ("type", 413 am->type), 414 GNUNET_JSON_pack_string ("instructions", 415 am->instructions), 416 GNUNET_JSON_pack_data_varsize ("challenge", 417 am->challenge, 418 am->challenge_size), 419 GNUNET_JSON_pack_conditional ( 420 NULL != am->mime_type, 421 GNUNET_JSON_pack_string ("mime_type", 422 am->mime_type))))); 423 } 424 set_opt (obj, 425 "authentication_methods", 426 arr); 427 } 428 if (b->have_policies) 429 { 430 json_t *arr; 431 432 arr = json_array (); 433 GNUNET_assert (NULL != arr); 434 for (unsigned int i = 0; i < b->policies_len; i++) 435 { 436 const struct ANASTASIS_ReduxPolicy *p = &b->policies[i]; 437 json_t *methods; 438 439 methods = json_array (); 440 GNUNET_assert (NULL != methods); 441 for (unsigned int j = 0; j < p->methods_len; j++) 442 { 443 const struct ANASTASIS_ReduxPolicyMethod *pm = &p->methods[j]; 444 json_t *mo; 445 446 mo = GNUNET_JSON_PACK ( 447 GNUNET_JSON_pack_uint64 ("authentication_method", 448 pm->authentication_method.idx), 449 GNUNET_JSON_pack_string ("provider", 450 pm->provider.url)); 451 if (NULL != pm->truth) 452 { 453 json_t *truth = ANASTASIS_truth_to_json (pm->truth); 454 455 GNUNET_assert (NULL != truth); 456 GNUNET_assert (0 == 457 json_object_set_new (truth, 458 "upload_status", 459 json_integer ( 460 pm->upload_status))); 461 GNUNET_assert (0 == 462 json_object_set_new (mo, 463 "truth", 464 truth)); 465 } 466 GNUNET_assert (0 == 467 json_array_append_new (methods, 468 mo)); 469 } 470 GNUNET_assert (0 == 471 json_array_append_new ( 472 arr, 473 GNUNET_JSON_PACK ( 474 GNUNET_JSON_pack_conditional ( 475 p->have_recovery_cost, 476 TALER_JSON_pack_amount ("recovery_cost", 477 &p->recovery_cost)), 478 GNUNET_JSON_pack_array_steal ("methods", 479 methods)))); 480 } 481 set_opt (obj, 482 "policies", 483 arr); 484 } 485 if (b->have_policy_providers) 486 { 487 json_t *arr; 488 489 arr = json_array (); 490 GNUNET_assert (NULL != arr); 491 for (unsigned int i = 0; i < b->policy_providers_len; i++) 492 { 493 const struct ANASTASIS_ReduxPolicyProvider *pp 494 = &b->policy_providers[i]; 495 496 GNUNET_assert (0 == 497 json_array_append_new ( 498 arr, 499 GNUNET_JSON_PACK ( 500 GNUNET_JSON_pack_string ("provider_url", 501 pp->provider_url.url), 502 GNUNET_JSON_pack_conditional ( 503 pp->have_payment_secret, 504 GNUNET_JSON_pack_data_auto ( 505 "payment_secret", 506 &pp->payment_secret))))); 507 } 508 set_opt (obj, 509 "policy_providers", 510 arr); 511 } 512 if (b->have_upload_fees) 513 { 514 json_t *arr; 515 516 arr = json_array (); 517 GNUNET_assert (NULL != arr); 518 for (unsigned int i = 0; i < b->upload_fees_len; i++) 519 GNUNET_assert (0 == 520 json_array_append_new ( 521 arr, 522 GNUNET_JSON_PACK ( 523 TALER_JSON_pack_amount ("fee", 524 &b->upload_fees[i])))); 525 set_opt (obj, 526 "upload_fees", 527 arr); 528 } 529 if (b->have_payments) 530 { 531 json_t *arr; 532 533 arr = json_array (); 534 GNUNET_assert (NULL != arr); 535 for (unsigned int i = 0; i < b->payments_len; i++) 536 GNUNET_assert (0 == 537 json_array_append_new (arr, 538 json_string (b->payments[i]))); 539 set_opt (obj, 540 "payments", 541 arr); 542 } 543 if (b->have_policy_payment_requests) 544 { 545 json_t *arr; 546 547 arr = json_array (); 548 GNUNET_assert (NULL != arr); 549 for (unsigned int i = 0; i < b->policy_payment_requests_len; i++) 550 { 551 const struct ANASTASIS_ReduxPolicyPaymentRequest *ppr 552 = &b->policy_payment_requests[i]; 553 554 GNUNET_assert (0 == 555 json_array_append_new ( 556 arr, 557 GNUNET_JSON_PACK ( 558 GNUNET_JSON_pack_string ("payto", 559 ppr->payto), 560 GNUNET_JSON_pack_string ("provider", 561 ppr->provider.url)))); 562 } 563 set_opt (obj, 564 "policy_payment_requests", 565 arr); 566 } 567 if (b->have_success_details) 568 { 569 json_t *sd; 570 571 sd = json_object (); 572 GNUNET_assert (NULL != sd); 573 for (unsigned int i = 0; i < b->success_details_len; i++) 574 { 575 const struct ANASTASIS_ReduxSuccessDetail *d = &b->success_details[i]; 576 577 GNUNET_assert (0 == 578 json_object_set_new ( 579 sd, 580 d->provider_url.url, 581 GNUNET_JSON_PACK ( 582 GNUNET_JSON_pack_uint64 ("policy_version", 583 d->policy_version), 584 GNUNET_JSON_pack_timestamp ("policy_expiration", 585 d->policy_expiration)))); 586 } 587 set_opt (obj, 588 "success_details", 589 sd); 590 } 591 if (NULL != b->core_secret) 592 set_opt (obj, 593 "core_secret", 594 json_incref (b->core_secret)); 595 if (NULL != b->secret_name) 596 set_opt (obj, 597 "secret_name", 598 json_string (b->secret_name)); 599 if (b->have_expiration) 600 set_opt (obj, 601 "expiration", 602 GNUNET_JSON_from_timestamp (b->expiration)); 603 if (b->have_pay_arguments) 604 { 605 json_t *pa; 606 607 pa = json_object (); 608 GNUNET_assert (NULL != pa); 609 if (b->pay_arguments.have_timeout) 610 set_opt (pa, 611 "timeout", 612 GNUNET_JSON_from_time_rel (b->pay_arguments.timeout)); 613 set_opt (obj, 614 "pay_arguments", 615 pa); 616 } 617 } 618 619 620 /** 621 * Serialize the recovery information @a ri. 622 * 623 * @param ri recovery information to serialize 624 * @return JSON object 625 */ 626 static json_t * 627 serialize_recovery_info (const struct ANASTASIS_ReduxRecoveryInfo *ri) 628 { 629 json_t *challenges; 630 json_t *policies; 631 632 challenges = json_array (); 633 GNUNET_assert (NULL != challenges); 634 for (unsigned int i = 0; i < ri->challenges_len; i++) 635 { 636 const struct ANASTASIS_ReduxChallengeInfo *ci = &ri->challenges[i]; 637 638 GNUNET_assert (0 == 639 json_array_append_new ( 640 challenges, 641 GNUNET_JSON_PACK ( 642 GNUNET_JSON_pack_data_auto ("uuid", 643 &ci->uuid), 644 GNUNET_JSON_pack_string ("type", 645 ci->type), 646 GNUNET_JSON_pack_string ("uuid-display", 647 ANASTASIS_CRYPTO_uuid2s ( 648 &ci->uuid)), 649 GNUNET_JSON_pack_string ("instructions", 650 ci->instructions), 651 GNUNET_JSON_pack_conditional ( 652 NULL != ci->answer, 653 GNUNET_JSON_pack_string ("answer", 654 ci->answer)), 655 GNUNET_JSON_pack_conditional ( 656 ci->have_payment_secret, 657 GNUNET_JSON_pack_data_auto ("payment_secret", 658 &ci->payment_secret))))); 659 } 660 policies = json_array (); 661 GNUNET_assert (NULL != policies); 662 for (unsigned int i = 0; i < ri->policies_len; i++) 663 { 664 const struct ANASTASIS_ReduxRecoveryPolicy *p = &ri->policies[i]; 665 json_t *pa; 666 667 pa = json_array (); 668 GNUNET_assert (NULL != pa); 669 for (unsigned int j = 0; j < p->uuids_len; j++) 670 GNUNET_assert (0 == 671 json_array_append_new ( 672 pa, 673 GNUNET_JSON_PACK ( 674 GNUNET_JSON_pack_data_auto ("uuid", 675 &p->uuids[j])))); 676 GNUNET_assert (0 == 677 json_array_append_new (policies, 678 pa)); 679 } 680 return GNUNET_JSON_PACK ( 681 GNUNET_JSON_pack_array_steal ("challenges", 682 challenges), 683 GNUNET_JSON_pack_array_steal ("policies", 684 policies), 685 GNUNET_JSON_pack_allow_null ( 686 GNUNET_JSON_pack_string ("secret_name", 687 ri->secret_name)), 688 GNUNET_JSON_pack_string ("provider_url", 689 ri->provider_url.url), 690 GNUNET_JSON_pack_uint64 ("version", 691 ri->version)); 692 } 693 694 695 /** 696 * Serialize one challenge feedback entry. 697 * 698 * @param fb feedback to serialize 699 * @return JSON object 700 */ 701 static json_t * 702 serialize_feedback (const struct ANASTASIS_ReduxFeedback *fb) 703 { 704 json_t *fo; 705 706 switch (fb->status) 707 { 708 case ANASTASIS_RFS_CODE_IN_FILE: 709 fo = GNUNET_JSON_PACK ( 710 GNUNET_JSON_pack_string ("state", 711 "code-in-file"), 712 GNUNET_JSON_pack_string ("filename", 713 fb->details.code_in_file.filename)); 714 break; 715 case ANASTASIS_RFS_SEND_TO_ADDRESS: 716 fo = GNUNET_JSON_PACK ( 717 GNUNET_JSON_pack_string ("state", 718 "send-to-address"), 719 GNUNET_JSON_pack_conditional ( 720 NULL != fb->details.send_to_address.address_hint, 721 GNUNET_JSON_pack_string ("address_hint", 722 fb->details.send_to_address.address_hint))); 723 break; 724 case ANASTASIS_RFS_TALER_PAYMENT: 725 fo = GNUNET_JSON_PACK ( 726 GNUNET_JSON_pack_string ("state", 727 "taler-payment"), 728 GNUNET_JSON_pack_string ("taler_pay_uri", 729 fb->details.taler_payment.taler_pay_uri), 730 GNUNET_JSON_pack_string ("provider", 731 fb->details.taler_payment.provider.url), 732 GNUNET_JSON_pack_data_auto ("payment_secret", 733 &fb->details.taler_payment.payment_secret)); 734 break; 735 case ANASTASIS_RFS_SERVER_FAILURE: 736 fo = GNUNET_JSON_PACK ( 737 GNUNET_JSON_pack_string ("state", 738 "server-failure"), 739 GNUNET_JSON_pack_uint64 ("http_status", 740 fb->details.server_failure.http_status), 741 GNUNET_JSON_pack_uint64 ("error_code", 742 fb->details.server_failure.ec)); 743 break; 744 case ANASTASIS_RFS_TRUTH_UNKNOWN: 745 fo = GNUNET_JSON_PACK ( 746 GNUNET_JSON_pack_string ("state", 747 "truth-unknown"), 748 GNUNET_JSON_pack_uint64 ("http_status", 749 fb->details.server_failure.http_status), 750 GNUNET_JSON_pack_uint64 ("error_code", 751 fb->details.server_failure.ec)); 752 break; 753 case ANASTASIS_RFS_IBAN_INSTRUCTIONS: 754 fo = GNUNET_JSON_PACK ( 755 GNUNET_JSON_pack_string ("state", 756 "iban-instructions"), 757 GNUNET_JSON_pack_string ("target_iban", 758 fb->details.iban_instructions.target_iban), 759 GNUNET_JSON_pack_string ( 760 "target_business_name", 761 fb->details.iban_instructions.target_business_name), 762 GNUNET_JSON_pack_string ( 763 "wire_transfer_subject", 764 fb->details.iban_instructions.wire_transfer_subject), 765 TALER_JSON_pack_amount ("challenge_amount", 766 &fb->details.iban_instructions.amount)); 767 break; 768 case ANASTASIS_RFS_SOLVED: 769 fo = GNUNET_JSON_PACK ( 770 GNUNET_JSON_pack_string ("state", 771 "solved")); 772 break; 773 case ANASTASIS_RFS_INCORRECT_ANSWER: 774 fo = GNUNET_JSON_PACK ( 775 GNUNET_JSON_pack_string ("state", 776 "incorrect-answer"), 777 GNUNET_JSON_pack_uint64 ("error_code", 778 fb->details.incorrect_answer.ec)); 779 break; 780 case ANASTASIS_RFS_RATE_LIMIT_EXCEEDED: 781 fo = GNUNET_JSON_PACK ( 782 GNUNET_JSON_pack_string ("state", 783 "rate-limit-exceeded"), 784 GNUNET_JSON_pack_uint64 ( 785 "request_limit", 786 fb->details.rate_limit_exceeded.request_limit), 787 GNUNET_JSON_pack_time_rel ( 788 "request_frequency", 789 fb->details.rate_limit_exceeded.request_frequency), 790 GNUNET_JSON_pack_uint64 ("error_code", 791 fb->details.rate_limit_exceeded.ec)); 792 break; 793 default: 794 GNUNET_assert (0); 795 } 796 if (NULL != fb->display_hint) 797 set_opt (fo, 798 "display_hint", 799 json_string (fb->display_hint)); 800 return fo; 801 } 802 803 804 /** 805 * Serialize the recovery-specific fields into @a obj. 806 * 807 * @param[in,out] obj object to extend 808 * @param rr recovery state to serialize 809 */ 810 static void 811 serialize_recovery (json_t *obj, 812 const struct ANASTASIS_ReduxRecovery *rr) 813 { 814 if (NULL != rr->ri) 815 set_opt (obj, 816 "recovery_information", 817 serialize_recovery_info (rr->ri)); 818 if (NULL != rr->r) 819 set_opt (obj, 820 "recovery_document", 821 ANASTASIS_recovery_serialize (rr->r)); 822 if (rr->have_challenge_feedback) 823 { 824 json_t *cf; 825 826 cf = json_object (); 827 GNUNET_assert (NULL != cf); 828 for (unsigned int i = 0; i < rr->challenge_feedback_len; i++) 829 { 830 const struct ANASTASIS_ReduxFeedback *fb = &rr->challenge_feedback[i]; 831 char uuid[sizeof (fb->uuid) * 2]; 832 char *end; 833 834 end = GNUNET_STRINGS_data_to_string (&fb->uuid, 835 sizeof (fb->uuid), 836 uuid, 837 sizeof (uuid)); 838 GNUNET_assert (NULL != end); 839 *end = '\0'; 840 GNUNET_assert (0 == 841 json_object_set_new (cf, 842 uuid, 843 serialize_feedback (fb))); 844 } 845 set_opt (obj, 846 "challenge_feedback", 847 cf); 848 } 849 if (rr->have_selected_challenge) 850 set_opt (obj, 851 "selected_challenge_uuid", 852 GNUNET_JSON_from_data_auto (&rr->selected_challenge)); 853 if (NULL != rr->core_secret) 854 set_opt (obj, 855 "core_secret", 856 json_incref (rr->core_secret)); 857 } 858 859 860 json_t * 861 ANASTASIS_REDUX_state_serialize_ (const struct ANASTASIS_ReduxState *rs) 862 { 863 json_t *obj; 864 865 switch (rs->type) 866 { 867 case ANASTASIS_RT_BACKUP: 868 obj = GNUNET_JSON_PACK ( 869 GNUNET_JSON_pack_string ("reducer_type", 870 "backup"), 871 GNUNET_JSON_pack_string ("backup_state", 872 ANASTASIS_backup_state_to_string_ ( 873 rs->details.backup.state))); 874 serialize_common (obj, 875 &rs->common); 876 serialize_backup (obj, 877 &rs->details.backup); 878 return obj; 879 case ANASTASIS_RT_RECOVERY: 880 obj = GNUNET_JSON_PACK ( 881 GNUNET_JSON_pack_string ("reducer_type", 882 "recovery"), 883 GNUNET_JSON_pack_string ("recovery_state", 884 ANASTASIS_recovery_state_to_string_ ( 885 rs->details.recovery.state))); 886 serialize_common (obj, 887 &rs->common); 888 serialize_recovery (obj, 889 &rs->details.recovery); 890 return obj; 891 case ANASTASIS_RT_ERROR: 892 return GNUNET_JSON_PACK ( 893 GNUNET_JSON_pack_string ("reducer_type", 894 "error"), 895 GNUNET_JSON_pack_uint64 ("code", 896 rs->details.error.code), 897 GNUNET_JSON_pack_allow_null ( 898 GNUNET_JSON_pack_string ("hint", 899 rs->details.error.hint)), 900 GNUNET_JSON_pack_allow_null ( 901 GNUNET_JSON_pack_string ("detail", 902 rs->details.error.detail))); 903 } 904 GNUNET_assert (0); 905 return NULL; 906 } 907 908 909 /* end of anastasis_api_redux_serialize.c */