aboutsummaryrefslogtreecommitdiff
path: root/src/backend/taler-merchant-httpd_private-post-orders.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/taler-merchant-httpd_private-post-orders.c')
-rw-r--r--src/backend/taler-merchant-httpd_private-post-orders.c212
1 files changed, 137 insertions, 75 deletions
diff --git a/src/backend/taler-merchant-httpd_private-post-orders.c b/src/backend/taler-merchant-httpd_private-post-orders.c
index 6974e367..4ac997ae 100644
--- a/src/backend/taler-merchant-httpd_private-post-orders.c
+++ b/src/backend/taler-merchant-httpd_private-post-orders.c
@@ -35,6 +35,7 @@
#include <taler/taler_error_codes.h>
#include <taler/taler_signatures.h>
#include <taler/taler_json_lib.h>
+#include <time.h>
#include "taler-merchant-httpd.h"
#include "taler-merchant-httpd_private-post-orders.h"
#include "taler-merchant-httpd_exchanges.h"
@@ -690,6 +691,7 @@ clean_order (void *cls)
oc->parse_choices.choices[i].outputs_len,
0);
}
+ // TODO: Free token family public keys
GNUNET_array_grow (oc->parse_request.inventory_products,
oc->parse_request.inventory_products_length,
0);
@@ -1319,6 +1321,96 @@ get_exchange_keys (void *cls,
}
/**
+ * Get rounded time interval. @a start is calculated by rounding
+ * @a ts down to the nearest multiple of @a precision. @a end is
+ * the next higher multiple of @a precision.
+ *
+ * @param precision rounding precision.
+ * year, month, day, hour, minute are supported.
+ * @param ts timestamp to round
+ * @param[out] start start of the interval
+ * @param[out] end end of the interval
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
+ */
+static enum GNUNET_GenericReturnValue
+get_rounded_time_interval (struct GNUNET_TIME_Relative precision,
+ struct GNUNET_TIME_Timestamp ts,
+ struct GNUNET_TIME_Timestamp *start,
+ struct GNUNET_TIME_Timestamp *end)
+{
+ struct tm* timeinfo;
+ time_t seconds;
+
+ seconds = GNUNET_TIME_timestamp_to_s (ts);
+ timeinfo = localtime (&seconds);
+
+ if (GNUNET_TIME_relative_cmp (GNUNET_TIME_UNIT_YEARS, ==, precision))
+ {
+ timeinfo->tm_mon = 0;
+ timeinfo->tm_mday = 1;
+ timeinfo->tm_hour = 0;
+ timeinfo->tm_min = 0;
+ timeinfo->tm_sec = 0;
+ }
+ else if (GNUNET_TIME_relative_cmp (GNUNET_TIME_UNIT_MONTHS, ==, precision))
+ {
+ timeinfo->tm_mday = 1;
+ timeinfo->tm_hour = 0;
+ timeinfo->tm_min = 0;
+ timeinfo->tm_sec = 0;
+ }
+ else if (GNUNET_TIME_relative_cmp (GNUNET_TIME_UNIT_DAYS, ==, precision))
+ {
+ timeinfo->tm_hour = 0;
+ timeinfo->tm_min = 0;
+ timeinfo->tm_sec = 0;
+ }
+ else if (GNUNET_TIME_relative_cmp (GNUNET_TIME_UNIT_HOURS, ==, precision))
+ {
+ timeinfo->tm_min = 0;
+ timeinfo->tm_sec = 0;
+ }
+ else if (GNUNET_TIME_relative_cmp (GNUNET_TIME_UNIT_MINUTES, ==, precision))
+ {
+ timeinfo->tm_sec = 0;
+ }
+ else
+ {
+ return GNUNET_SYSERR;
+ }
+
+ *start = GNUNET_TIME_timestamp_from_s (mktime (timeinfo));
+
+ if (GNUNET_TIME_relative_cmp (GNUNET_TIME_UNIT_YEARS, ==, precision))
+ {
+ timeinfo->tm_year++;
+ }
+ else if (GNUNET_TIME_relative_cmp (GNUNET_TIME_UNIT_MONTHS, ==, precision))
+ {
+ timeinfo->tm_mon = (timeinfo->tm_mon + 1) % 12;
+ }
+ else if (GNUNET_TIME_relative_cmp (GNUNET_TIME_UNIT_DAYS, ==, precision))
+ {
+ timeinfo->tm_mday++;
+ }
+ else if (GNUNET_TIME_relative_cmp (GNUNET_TIME_UNIT_HOURS, ==, precision))
+ {
+ timeinfo->tm_hour++;
+ }
+ else if (GNUNET_TIME_relative_cmp (GNUNET_TIME_UNIT_MINUTES, ==, precision))
+ {
+ timeinfo->tm_min++;
+ }
+ else
+ {
+ return GNUNET_SYSERR;
+ }
+
+ *end = GNUNET_TIME_timestamp_from_s (mktime (timeinfo));
+ return GNUNET_OK;
+}
+
+/**
* Check if the token family with the given @a slug is already present in
* the list of token families for this order. If not, fetch its details and
* add it to the list. Then check if there is a public key with a matching
@@ -1328,8 +1420,9 @@ get_exchange_keys (void *cls,
* @param[in,out] oc order context
* @param slug slug of the token family
* @param valid_after validity start date of the token, subject to rounding
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
*/
-static MHD_RESULT
+static enum GNUNET_GenericReturnValue
set_token_family (struct OrderContext *oc,
const char *slug,
struct GNUNET_TIME_Timestamp valid_after)
@@ -1339,16 +1432,22 @@ set_token_family (struct OrderContext *oc,
enum GNUNET_DB_QueryStatus qs;
// TODO: make this configurable. This is the granularity of token
// expiration dates.
- struct GNUNET_TIME_Relative rounding = GNUNET_TIME_UNIT_YEARS;
+ struct GNUNET_TIME_Relative precision = GNUNET_TIME_UNIT_MONTHS;
+ struct GNUNET_TIME_Timestamp min_valid_after;
+ struct GNUNET_TIME_Timestamp max_valid_after;
- struct GNUNET_TIME_Timestamp min_valid_after = GNUNET_TIME_absolute_to_timestamp (
- GNUNET_TIME_absolute_round_down (
- valid_after.abs_time,
- rounding));
- struct GNUNET_TIME_Timestamp max_valid_after = GNUNET_TIME_absolute_to_timestamp (
- GNUNET_TIME_absolute_add(
- min_valid_after.abs_time,
- rounding));
+ if ( GNUNET_OK != get_rounded_time_interval (precision,
+ valid_after,
+ &min_valid_after,
+ &max_valid_after))
+ {
+ GNUNET_break (0);
+ reply_with_error (oc,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
+ "valid_after");
+ return GNUNET_SYSERR;
+ }
for (unsigned int i = 0; i<oc->parse_choices.token_families_len; i++)
{
@@ -1364,13 +1463,15 @@ set_token_family (struct OrderContext *oc,
{
for (unsigned int i = 0; i<family->keys_len; i++)
{
- if (family->keys[i].valid_after.abs_time.abs_value_us >=
- min_valid_after.abs_time.abs_value_us
- && family->keys[i].valid_after.abs_time.abs_value_us <
- max_valid_after.abs_time.abs_value_us)
+ if (GNUNET_TIME_timestamp_cmp (family->keys[i].valid_after,
+ >=,
+ min_valid_after)
+ && GNUNET_TIME_timestamp_cmp (family->keys[i].valid_after,
+ <,
+ max_valid_after))
{
/* The token family and a matching key is already added. */
- return MHD_YES;
+ return GNUNET_OK;
}
}
}
@@ -1414,15 +1515,15 @@ set_token_family (struct OrderContext *oc,
http_status,
ec,
"token_family_slug");
- return MHD_NO;
+ return GNUNET_SYSERR;
}
- if (NULL == key_details.pub)
+ if (GNUNET_CRYPTO_BSA_INVALID == key_details.pub.public_key.cipher)
{
/* There is no matching key for this token family yet. */
/* We have to generate one. */
- /* If public key is NULL, private key must also be NULL */
- GNUNET_assert (NULL == key_details.priv);
+ /* If public key is invalid, private key must also be invalid */
+ GNUNET_assert (GNUNET_CRYPTO_BSA_INVALID == key_details.priv.private_key.cipher);
enum GNUNET_DB_QueryStatus iqs;
struct GNUNET_CRYPTO_BlindSignPrivateKey *priv;
@@ -1446,6 +1547,7 @@ set_token_family (struct OrderContext *oc,
};
// TODO: Check if I have to decref pub and priv here.
+ // GNUNET_CRYPTO_blind_sign_pub_decref (pub);
iqs = TMH_db->insert_token_family_key (TMH_db->cls,
slug,
@@ -1454,10 +1556,9 @@ set_token_family (struct OrderContext *oc,
min_valid_after,
valid_before);
- /* private key is no longer needed */
- // GNUNET_CRYPTO_blind_sign_priv_decref (&token_priv.private_key);
+ GNUNET_CRYPTO_blind_sign_priv_decref (priv);
- if (iqs < 0)
+ if (iqs <= 0)
{
enum TALER_ErrorCode ec = TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
unsigned int http_status = 0;
@@ -1469,23 +1570,21 @@ set_token_family (struct OrderContext *oc,
ec = TALER_EC_GENERIC_DB_STORE_FAILED;
break;
case GNUNET_DB_STATUS_SOFT_ERROR:
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
http_status = MHD_HTTP_INTERNAL_SERVER_ERROR;
ec = TALER_EC_GENERIC_DB_SOFT_FAILURE;
break;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
/* case listed to make compilers happy */
GNUNET_assert (0);
}
- // GNUNET_CRYPTO_blind_sign_pub_decref (&token_pub.public_key);
-
GNUNET_break (0);
reply_with_error (oc,
http_status,
ec,
"token_family_slug");
- return MHD_NO;
+ return GNUNET_SYSERR;
}
{
@@ -1501,7 +1600,7 @@ set_token_family (struct OrderContext *oc,
}
} else {
struct TALER_MerchantContractTokenFamilyKey key = {
- .pub = *key_details.pub,
+ .pub = key_details.pub,
.valid_after = key_details.valid_before,
.valid_before = key_details.valid_before,
};
@@ -1517,9 +1616,6 @@ set_token_family (struct OrderContext *oc,
GNUNET_free (key_details.token_family.slug);
GNUNET_free (key_details.token_family.name);
- if (NULL != key_details.priv) {
- GNUNET_CRYPTO_blind_sign_priv_decref (&key_details.priv->private_key);
- }
switch (key_details.token_family.kind) {
case TALER_MERCHANTDB_TFK_Subscription:
@@ -1538,7 +1634,7 @@ set_token_family (struct OrderContext *oc,
oc->parse_choices.token_families_len,
*family);
- return MHD_YES;
+ return GNUNET_OK;
}
/**
@@ -2496,29 +2592,12 @@ parse_choices (struct OrderContext *oc)
continue;
}
- bool found = false;
-
- for (unsigned int i = 0; i<oc->parse_choices.token_families_len; i++)
- {
- if (0 == strcmp (oc->parse_choices.token_families[i].slug,
- input.details.token.token_family_slug))
- {
- found = true;
- break;
- }
- }
-
- if (! found)
+ if (GNUNET_OK != set_token_family (oc,
+ input.details.token.token_family_slug,
+ input.details.token.valid_after))
{
- MHD_RESULT res;
- res = set_token_family (oc,
- input.details.token.token_family_slug,
- input.details.token.valid_after);
-
- if (MHD_NO == res)
- {
- return;
- }
+ /* error is already scheduled, return. */
+ return;
}
GNUNET_array_append (oc->parse_choices.choices[i].inputs,
@@ -2592,29 +2671,12 @@ parse_choices (struct OrderContext *oc)
continue;
}
- bool found = false;
-
- for (unsigned int i = 0; i<oc->parse_choices.token_families_len; i++)
+ if (GNUNET_OK != set_token_family (oc,
+ output.details.token.token_family_slug,
+ output.details.token.valid_after))
{
- if (0 == strcmp (oc->parse_choices.token_families[i].slug,
- output.details.token.token_family_slug))
- {
- found = true;
- break;
- }
- }
-
- if (! found)
- {
- MHD_RESULT res;
- res = set_token_family (oc,
- output.details.token.token_family_slug,
- output.details.token.valid_after);
-
- if (MHD_NO == res)
- {
- return;
- }
+ /* error is already scheduled, return. */
+ return;
}
GNUNET_array_append (oc->parse_choices.choices[i].outputs,