summaryrefslogtreecommitdiff
path: root/src/backend/anastasis-httpd_truth_upload.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/anastasis-httpd_truth_upload.c')
-rw-r--r--src/backend/anastasis-httpd_truth_upload.c856
1 files changed, 0 insertions, 856 deletions
diff --git a/src/backend/anastasis-httpd_truth_upload.c b/src/backend/anastasis-httpd_truth_upload.c
deleted file mode 100644
index d9e63c3..0000000
--- a/src/backend/anastasis-httpd_truth_upload.c
+++ /dev/null
@@ -1,856 +0,0 @@
-/*
- This file is part of Anastasis
- Copyright (C) 2019, 2021 Anastasis SARL
-
- Anastasis 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, or (at your option) any later version.
-
- Anastasis 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
- Anastasis; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
-*/
-/**
- * @file anastasis-httpd_truth_upload.c
- * @brief functions to handle incoming POST request on /truth
- * @author Dennis Neufeld
- * @author Dominik Meister
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include "anastasis-httpd.h"
-#include "anastasis_service.h"
-#include "anastasis-httpd_truth.h"
-#include <gnunet/gnunet_util_lib.h>
-#include <gnunet/gnunet_rest_lib.h>
-#include <taler/taler_json_lib.h>
-#include <taler/taler_merchant_service.h>
-#include <taler/taler_signatures.h>
-#include "anastasis_authorization_lib.h"
-
-
-/**
- * Information we track per truth upload.
- */
-struct TruthUploadContext
-{
-
- /**
- * UUID of the truth object we are processing.
- */
- struct ANASTASIS_CRYPTO_TruthUUIDP truth_uuid;
-
- /**
- * Kept in DLL for shutdown handling while suspended.
- */
- struct TruthUploadContext *next;
-
- /**
- * Kept in DLL for shutdown handling while suspended.
- */
- struct TruthUploadContext *prev;
-
- /**
- * Used while we are awaiting proposal creation.
- */
- struct TALER_MERCHANT_PostOrdersHandle *po;
-
- /**
- * Used while we are waiting payment.
- */
- struct TALER_MERCHANT_OrderMerchantGetHandle *cpo;
-
- /**
- * Post parser context.
- */
- void *post_ctx;
-
- /**
- * Handle to the client request.
- */
- struct MHD_Connection *connection;
-
- /**
- * Incoming JSON, NULL if not yet available.
- */
- json_t *json;
-
- /**
- * HTTP response code to use on resume, if non-NULL.
- */
- struct MHD_Response *resp;
-
- /**
- * When should this request time out?
- */
- struct GNUNET_TIME_Absolute timeout;
-
- /**
- * Fee that is to be paid for this upload.
- */
- struct TALER_Amount upload_fee;
-
- /**
- * HTTP response code to use on resume, if resp is set.
- */
- unsigned int response_code;
-
- /**
- * For how many years must the customer still pay?
- */
- unsigned int years_to_pay;
-
-};
-
-
-/**
- * Head of linked list over all truth upload processes
- */
-static struct TruthUploadContext *tuc_head;
-
-/**
- * Tail of linked list over all truth upload processes
- */
-static struct TruthUploadContext *tuc_tail;
-
-
-void
-AH_truth_upload_shutdown (void)
-{
- struct TruthUploadContext *tuc;
-
- while (NULL != (tuc = tuc_head))
- {
- GNUNET_CONTAINER_DLL_remove (tuc_head,
- tuc_tail,
- tuc);
- if (NULL != tuc->cpo)
- {
- TALER_MERCHANT_merchant_order_get_cancel (tuc->cpo);
- tuc->cpo = NULL;
- }
- if (NULL != tuc->po)
- {
- TALER_MERCHANT_orders_post_cancel (tuc->po);
- tuc->po = NULL;
- }
- MHD_resume_connection (tuc->connection);
- }
-}
-
-
-/**
- * Function called to clean up a `struct TruthUploadContext`.
- *
- * @param hc general handler context
- */
-static void
-cleanup_truth_post (struct TM_HandlerContext *hc)
-{
- struct TruthUploadContext *tuc = hc->ctx;
-
- TALER_MHD_parse_post_cleanup_callback (tuc->post_ctx);
- if (NULL != tuc->po)
- TALER_MERCHANT_orders_post_cancel (tuc->po);
- if (NULL != tuc->cpo)
- TALER_MERCHANT_merchant_order_get_cancel (tuc->cpo);
- if (NULL != tuc->resp)
- MHD_destroy_response (tuc->resp);
- if (NULL != tuc->json)
- json_decref (tuc->json);
- GNUNET_free (tuc);
-}
-
-
-/**
- * Transmit a payment request for @a tuc.
- *
- * @param tuc upload context to generate payment request for
- */
-static void
-make_payment_request (struct TruthUploadContext *tuc)
-{
- struct MHD_Response *resp;
-
- /* request payment via Taler */
- resp = MHD_create_response_from_buffer (0,
- NULL,
- MHD_RESPMEM_PERSISTENT);
- GNUNET_assert (NULL != resp);
- TALER_MHD_add_global_headers (resp);
- {
- char *hdr;
- const char *pfx;
- const char *hn;
-
- if (0 == strncasecmp ("https://",
- AH_backend_url,
- strlen ("https://")))
- {
- pfx = "taler://";
- hn = &AH_backend_url[strlen ("https://")];
- }
- else if (0 == strncasecmp ("http://",
- AH_backend_url,
- strlen ("http://")))
- {
- pfx = "taler+http://";
- hn = &AH_backend_url[strlen ("http://")];
- }
- else
- {
- /* This invariant holds as per check in anastasis-httpd.c */
- GNUNET_assert (0);
- }
- /* This invariant holds as per check in anastasis-httpd.c */
- GNUNET_assert (0 != strlen (hn));
- {
- char *order_id;
-
- order_id = GNUNET_STRINGS_data_to_string_alloc (
- &tuc->truth_uuid,
- sizeof (tuc->truth_uuid));
- GNUNET_asprintf (&hdr,
- "%spay/%s%s/",
- pfx,
- hn,
- order_id);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Returning %u %s\n",
- MHD_HTTP_PAYMENT_REQUIRED,
- order_id);
- GNUNET_free (order_id);
- }
- GNUNET_break (MHD_YES ==
- MHD_add_response_header (resp,
- ANASTASIS_HTTP_HEADER_TALER,
- hdr));
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "TRUTH payment request made: %s\n",
- hdr);
- GNUNET_free (hdr);
- }
- tuc->resp = resp;
- tuc->response_code = MHD_HTTP_PAYMENT_REQUIRED;
-}
-
-
-/**
- * Callbacks of this type are used to serve the result of submitting a
- * POST /private/orders request to a merchant.
- *
- * @param cls our `struct TruthUploadContext`
- * @param por response details
- */
-static void
-proposal_cb (void *cls,
- const struct TALER_MERCHANT_PostOrdersReply *por)
-{
- struct TruthUploadContext *tuc = cls;
-
- tuc->po = NULL;
- GNUNET_CONTAINER_DLL_remove (tuc_head,
- tuc_tail,
- tuc);
- MHD_resume_connection (tuc->connection);
- AH_trigger_daemon (NULL);
- if (MHD_HTTP_OK != por->hr.http_status)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Backend returned status %u/%d\n",
- por->hr.http_status,
- (int) por->hr.ec);
- GNUNET_break (0);
- tuc->resp = TALER_MHD_MAKE_JSON_PACK (
- GNUNET_JSON_pack_uint64 ("code",
- TALER_EC_ANASTASIS_GENERIC_ORDER_CREATE_BACKEND_ERROR),
- GNUNET_JSON_pack_string ("hint",
- "Failed to setup order with merchant backend"),
- GNUNET_JSON_pack_uint64 ("backend-ec",
- por->hr.ec),
- GNUNET_JSON_pack_uint64 ("backend-http-status",
- por->hr.http_status),
- GNUNET_JSON_pack_allow_null (
- GNUNET_JSON_pack_object_incref ("backend-reply",
- (json_t *) por->hr.reply)));
- tuc->response_code = MHD_HTTP_BAD_GATEWAY;
- return;
- }
- make_payment_request (tuc);
-}
-
-
-/**
- * Callback to process a GET /check-payment request
- *
- * @param cls our `struct PolicyUploadContext`
- * @param hr HTTP response details
- * @param osr order status
- */
-static void
-check_payment_cb (void *cls,
- const struct TALER_MERCHANT_HttpResponse *hr,
- const struct TALER_MERCHANT_OrderStatusResponse *osr)
-{
- struct TruthUploadContext *tuc = cls;
-
- tuc->cpo = NULL;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Checking backend order status returned %u\n",
- hr->http_status);
- switch (hr->http_status)
- {
- case 0:
- /* Likely timeout, complain! */
- tuc->response_code = MHD_HTTP_GATEWAY_TIMEOUT;
- tuc->resp = TALER_MHD_make_error (
- TALER_EC_ANASTASIS_GENERIC_BACKEND_TIMEOUT,
- NULL);
- break;
- case MHD_HTTP_OK:
- switch (osr->status)
- {
- case TALER_MERCHANT_OSC_PAID:
- {
- enum GNUNET_DB_QueryStatus qs;
- unsigned int years;
- struct GNUNET_TIME_Relative paid_until;
- const json_t *contract;
- struct TALER_Amount amount;
- struct GNUNET_JSON_Specification cspec[] = {
- TALER_JSON_spec_amount ("amount",
- AH_currency,
- &amount),
- GNUNET_JSON_spec_end ()
- };
-
- contract = osr->details.paid.contract_terms;
- if (GNUNET_OK !=
- GNUNET_JSON_parse (contract,
- cspec,
- NULL, NULL))
- {
- GNUNET_break (0);
- tuc->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
- tuc->resp = TALER_MHD_make_error (
- TALER_EC_MERCHANT_GENERIC_DB_CONTRACT_CONTENT_INVALID,
- "contract terms in database are malformed");
- break;
- }
- years = TALER_amount_divide2 (&amount,
- &AH_truth_upload_fee);
- paid_until = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_YEARS,
- years);
- /* add 1 week grace period, otherwise if a user
- wants to pay for 1 year, the first seconds
- would have passed between making the payment
- and our subsequent check if +1 year was
- paid... So we actually say 1 year = 52 weeks
- on the server, while the client calculates
- with 365 days. */
- paid_until = GNUNET_TIME_relative_add (paid_until,
- GNUNET_TIME_UNIT_WEEKS);
- qs = db->record_truth_upload_payment (
- db->cls,
- &tuc->truth_uuid,
- &osr->details.paid.deposit_total,
- paid_until);
- if (qs <= 0)
- {
- GNUNET_break (0);
- tuc->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
- tuc->resp = TALER_MHD_make_error (
- TALER_EC_GENERIC_DB_STORE_FAILED,
- "record_truth_upload_payment");
- break;
- }
- }
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Payment confirmed, resuming upload\n");
- break;
- case TALER_MERCHANT_OSC_UNPAID:
- case TALER_MERCHANT_OSC_CLAIMED:
- make_payment_request (tuc);
- break;
- }
- break;
- case MHD_HTTP_UNAUTHORIZED:
- /* Configuration issue, complain! */
- tuc->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
- tuc->resp = TALER_MHD_MAKE_JSON_PACK (
- GNUNET_JSON_pack_uint64 ("code",
- TALER_EC_ANASTASIS_GENERIC_PAYMENT_CHECK_UNAUTHORIZED),
- GNUNET_JSON_pack_string ("hint",
- TALER_ErrorCode_get_hint (
- TALER_EC_ANASTASIS_GENERIC_PAYMENT_CHECK_UNAUTHORIZED)),
- GNUNET_JSON_pack_uint64 ("backend-ec",
- hr->ec),
- GNUNET_JSON_pack_uint64 ("backend-http-status",
- hr->http_status),
- GNUNET_JSON_pack_allow_null (
- GNUNET_JSON_pack_object_incref ("backend-reply",
- (json_t *) hr->reply)));
- GNUNET_assert (NULL != tuc->resp);
- break;
- case MHD_HTTP_NOT_FOUND:
- /* Setup fresh order */
- {
- char *order_id;
- json_t *order;
-
- order_id = GNUNET_STRINGS_data_to_string_alloc (
- &tuc->truth_uuid,
- sizeof(tuc->truth_uuid));
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "%u, setting up fresh order %s\n",
- MHD_HTTP_NOT_FOUND,
- order_id);
- order = json_pack ("{s:o, s:s, s:[{s:s,s:I,s:s}], s:s}",
- "amount",
- TALER_JSON_from_amount (&tuc->upload_fee),
- "summary",
- "Anastasis challenge storage fee",
- "products",
- "description", "challenge storage fee",
- "quantity", (json_int_t) tuc->years_to_pay,
- "unit", "years",
-
- "order_id",
- order_id);
- GNUNET_free (order_id);
- tuc->po = TALER_MERCHANT_orders_post2 (AH_ctx,
- AH_backend_url,
- order,
- GNUNET_TIME_UNIT_ZERO,
- NULL, /* no payment target */
- 0,
- NULL, /* no inventory products */
- 0,
- NULL, /* no uuids */
- false, /* do NOT require claim token */
- &proposal_cb,
- tuc);
- AH_trigger_curl ();
- json_decref (order);
- return;
- }
- default:
- /* Unexpected backend response */
- tuc->response_code = MHD_HTTP_BAD_GATEWAY;
- tuc->resp = TALER_MHD_MAKE_JSON_PACK (
- GNUNET_JSON_pack_uint64 ("code",
- TALER_EC_ANASTASIS_GENERIC_BACKEND_ERROR),
- GNUNET_JSON_pack_string ("hint",
- TALER_ErrorCode_get_hint (
- TALER_EC_ANASTASIS_GENERIC_BACKEND_ERROR)),
- GNUNET_JSON_pack_uint64 ("backend-ec",
- (json_int_t) hr->ec),
- GNUNET_JSON_pack_uint64 ("backend-http-status",
- (json_int_t) hr->http_status),
- GNUNET_JSON_pack_allow_null (
- GNUNET_JSON_pack_object_incref ("backend-reply",
- (json_t *) hr->reply)));
- break;
- }
- GNUNET_CONTAINER_DLL_remove (tuc_head,
- tuc_tail,
- tuc);
- MHD_resume_connection (tuc->connection);
- AH_trigger_daemon (NULL);
-}
-
-
-/**
- * Helper function used to ask our backend to begin processing a
- * payment for the truth upload. May perform asynchronous operations
- * by suspending the connection if required.
- *
- * @param tuc context to begin payment for.
- * @return MHD status code
- */
-static MHD_RESULT
-begin_payment (struct TruthUploadContext *tuc)
-{
- char *order_id;
- struct GNUNET_TIME_Relative timeout;
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Checking backend order status...\n");
- timeout = GNUNET_TIME_absolute_get_remaining (tuc->timeout);
- order_id = GNUNET_STRINGS_data_to_string_alloc (
- &tuc->truth_uuid,
- sizeof (tuc->truth_uuid));
- tuc->cpo = TALER_MERCHANT_merchant_order_get (AH_ctx,
- AH_backend_url,
- order_id,
- NULL /* our payments are NOT session-bound */,
- false,
- timeout,
- &check_payment_cb,
- tuc);
- GNUNET_free (order_id);
- if (NULL == tuc->cpo)
- {
- GNUNET_break (0);
- return TALER_MHD_reply_with_error (tuc->connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_ANASTASIS_GENERIC_PAYMENT_CHECK_START_FAILED,
- "Could not check order status");
- }
- GNUNET_CONTAINER_DLL_insert (tuc_head,
- tuc_tail,
- tuc);
- MHD_suspend_connection (tuc->connection);
- return MHD_YES;
-}
-
-
-MHD_RESULT
-AH_handler_truth_post (
- struct MHD_Connection *connection,
- struct TM_HandlerContext *hc,
- const struct ANASTASIS_CRYPTO_TruthUUIDP *truth_uuid,
- const char *truth_data,
- size_t *truth_data_size)
-{
- struct TruthUploadContext *tuc = hc->ctx;
- MHD_RESULT ret;
- int res;
- struct ANASTASIS_CRYPTO_EncryptedKeyShareP keyshare_data;
- void *encrypted_truth;
- size_t encrypted_truth_size;
- const char *truth_mime = NULL;
- const char *type;
- enum GNUNET_DB_QueryStatus qs;
- uint32_t storage_years;
- struct GNUNET_TIME_Absolute paid_until;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_fixed_auto ("keyshare_data",
- &keyshare_data),
- GNUNET_JSON_spec_string ("type",
- &type),
- GNUNET_JSON_spec_varsize ("encrypted_truth",
- &encrypted_truth,
- &encrypted_truth_size),
- GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_string ("truth_mime",
- &truth_mime)),
- GNUNET_JSON_spec_uint32 ("storage_duration_years",
- &storage_years),
- GNUNET_JSON_spec_end ()
- };
-
- if (NULL == tuc)
- {
- tuc = GNUNET_new (struct TruthUploadContext);
- tuc->connection = connection;
- tuc->truth_uuid = *truth_uuid;
- hc->ctx = tuc;
- hc->cc = &cleanup_truth_post;
-
- /* check for excessive upload */
- {
- const char *lens;
- unsigned long len;
- char dummy;
-
- lens = MHD_lookup_connection_value (connection,
- MHD_HEADER_KIND,
- MHD_HTTP_HEADER_CONTENT_LENGTH);
- if ( (NULL == lens) ||
- (1 != sscanf (lens,
- "%lu%c",
- &len,
- &dummy)) )
- {
- GNUNET_break_op (0);
- return TALER_MHD_reply_with_error (
- connection,
- MHD_HTTP_BAD_REQUEST,
- (NULL == lens)
- ? TALER_EC_ANASTASIS_GENERIC_MISSING_CONTENT_LENGTH
- : TALER_EC_ANASTASIS_GENERIC_MALFORMED_CONTENT_LENGTH,
- NULL);
- }
- if (len / 1024 / 1024 >= AH_upload_limit_mb)
- {
- GNUNET_break_op (0);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_PAYLOAD_TOO_LARGE,
- TALER_EC_SYNC_MALFORMED_CONTENT_LENGTH,
- "Content-length value not acceptable");
- }
- }
-
- {
- const char *long_poll_timeout_ms;
-
- long_poll_timeout_ms = MHD_lookup_connection_value (connection,
- MHD_GET_ARGUMENT_KIND,
- "timeout_ms");
- if (NULL != long_poll_timeout_ms)
- {
- unsigned int timeout;
- char dummy;
-
- if (1 != sscanf (long_poll_timeout_ms,
- "%u%c",
- &timeout,
- &dummy))
- {
- GNUNET_break_op (0);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_GENERIC_PARAMETER_MALFORMED,
- "timeout_ms (must be non-negative number)");
- }
- tuc->timeout
- = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_relative_multiply (
- GNUNET_TIME_UNIT_MILLISECONDS,
- timeout));
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Long polling for %u ms enabled\n",
- timeout);
- }
- else
- {
- tuc->timeout = GNUNET_TIME_relative_to_absolute (
- GNUNET_TIME_UNIT_SECONDS);
- }
- }
-
- } /* end 'if (NULL == tuc)' */
-
- if (NULL != tuc->resp)
- {
- /* We generated a response asynchronously, queue that */
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Returning asynchronously generated response with HTTP status %u\n",
- tuc->response_code);
- ret = MHD_queue_response (connection,
- tuc->response_code,
- tuc->resp);
- GNUNET_break (MHD_YES == ret);
- MHD_destroy_response (tuc->resp);
- tuc->resp = NULL;
- return ret;
- }
-
- if (NULL == tuc->json)
- {
- res = TALER_MHD_parse_post_json (connection,
- &tuc->post_ctx,
- truth_data,
- truth_data_size,
- &tuc->json);
- if (GNUNET_SYSERR == res)
- {
- GNUNET_break (0);
- return MHD_NO;
- }
- if ( (GNUNET_NO == res) ||
- (NULL == tuc->json) )
- return MHD_YES;
- }
- res = TALER_MHD_parse_json_data (connection,
- tuc->json,
- spec);
- if (GNUNET_SYSERR == res)
- {
- GNUNET_break (0);
- return MHD_NO; /* hard failure */
- }
- if (GNUNET_NO == res)
- {
- GNUNET_break_op (0);
- return MHD_YES; /* failure */
- }
-
- /* check method is supported */
- if ( (0 != strcmp ("question",
- type)) &&
- (NULL ==
- ANASTASIS_authorization_plugin_load (type,
- db,
- AH_cfg)) )
- {
- GNUNET_JSON_parse_free (spec);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_ANASTASIS_TRUTH_UPLOAD_METHOD_NOT_SUPPORTED,
- type);
- }
-
- if (storage_years > ANASTASIS_MAX_YEARS_STORAGE)
- {
- GNUNET_break_op (0);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_GENERIC_PARAMETER_MALFORMED,
- "storage_duration_years");
- }
- if (0 == storage_years)
- storage_years = 1;
-
- {
- struct TALER_Amount zero_amount;
-
- TALER_amount_set_zero (AH_currency,
- &zero_amount);
- if (0 != TALER_amount_cmp (&AH_truth_upload_fee,
- &zero_amount))
- {
- struct GNUNET_TIME_Absolute desired_until;
- enum GNUNET_DB_QueryStatus qs;
-
- desired_until
- = GNUNET_TIME_relative_to_absolute (
- GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_YEARS,
- storage_years));
- qs = db->check_truth_upload_paid (db->cls,
- truth_uuid,
- &paid_until);
- if (qs < 0)
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_FETCH_FAILED,
- NULL);
- if ( (0 == qs) ||
- (paid_until.abs_value_us < desired_until.abs_value_us) )
- {
- struct GNUNET_TIME_Absolute now;
- struct GNUNET_TIME_Relative rem;
-
- now = GNUNET_TIME_absolute_get ();
- if (paid_until.abs_value_us < now.abs_value_us)
- paid_until = now;
- rem = GNUNET_TIME_absolute_get_difference (paid_until,
- desired_until);
- tuc->years_to_pay = rem.rel_value_us
- / GNUNET_TIME_UNIT_YEARS.rel_value_us;
- if (0 != (rem.rel_value_us % GNUNET_TIME_UNIT_YEARS.rel_value_us))
- tuc->years_to_pay++;
- if (0 >
- TALER_amount_multiply (&tuc->upload_fee,
- &AH_truth_upload_fee,
- tuc->years_to_pay))
- {
- GNUNET_break_op (0);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_GENERIC_PARAMETER_MALFORMED,
- "storage_duration_years");
- }
- if ( (0 != tuc->upload_fee.fraction) ||
- (0 != tuc->upload_fee.value) )
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Truth upload payment required (%d)!\n",
- qs);
- return begin_payment (tuc);
- }
- }
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "TRUTH paid until %s (%d)!\n",
- GNUNET_STRINGS_relative_time_to_string (
- GNUNET_TIME_absolute_get_remaining (
- paid_until),
- GNUNET_YES),
- qs);
- }
- else
- {
- paid_until
- = GNUNET_TIME_relative_to_absolute (
- GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_YEARS,
- ANASTASIS_MAX_YEARS_STORAGE));
- }
- }
-
-
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Storing truth until %s!\n",
- GNUNET_STRINGS_absolute_time_to_string (paid_until));
- qs = db->store_truth (db->cls,
- truth_uuid,
- &keyshare_data,
- (NULL == truth_mime)
- ? ""
- : truth_mime,
- encrypted_truth,
- encrypted_truth_size,
- type,
- GNUNET_TIME_absolute_get_remaining (paid_until));
- switch (qs)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- case GNUNET_DB_STATUS_SOFT_ERROR:
- GNUNET_break (0);
- GNUNET_JSON_parse_free (spec);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_INVARIANT_FAILURE,
- "store_truth");
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- {
- void *xtruth;
- size_t xtruth_size;
- char *xtruth_mime;
- char *xmethod;
- bool ok = false;
-
- if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT ==
- db->get_escrow_challenge (db->cls,
- truth_uuid,
- &xtruth,
- &xtruth_size,
- &xtruth_mime,
- &xmethod))
- {
- ok = ( (xtruth_size == encrypted_truth_size) &&
- (0 == strcmp (xmethod,
- type)) &&
- (0 == strcmp (truth_mime,
- xtruth_mime)) &&
- (0 == memcmp (xtruth,
- encrypted_truth,
- xtruth_size)) );
- GNUNET_free (encrypted_truth);
- GNUNET_free (xtruth_mime);
- GNUNET_free (xmethod);
- }
- if (! ok)
- {
- GNUNET_JSON_parse_free (spec);
-
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_CONFLICT,
- TALER_EC_ANASTASIS_TRUTH_UPLOAD_UUID_EXISTS,
- NULL);
- }
- /* idempotency detected, intentional fall through! */
- }
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- {
- struct MHD_Response *resp;
-
- GNUNET_JSON_parse_free (spec);
- resp = MHD_create_response_from_buffer (0,
- NULL,
- MHD_RESPMEM_PERSISTENT);
- TALER_MHD_add_global_headers (resp);
- ret = MHD_queue_response (connection,
- MHD_HTTP_NO_CONTENT,
- resp);
- MHD_destroy_response (resp);
- GNUNET_break (MHD_YES == ret);
- return ret;
- }
- }
- GNUNET_JSON_parse_free (spec);
- GNUNET_break (0);
- return MHD_NO;
-}