summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2020-02-28 14:19:11 +0100
committerChristian Grothoff <christian@grothoff.org>2020-02-28 14:19:11 +0100
commit821b2af393c41d6a22da17b529271fec375b31cc (patch)
tree01f896158ca1bbc780be913a92b907f4f5087ad3
parent79a682aebe685bd3eb472453267cf3cfafb39400 (diff)
downloadtaler-mdb-821b2af393c41d6a22da17b529271fec375b31cc.tar.gz
taler-mdb-821b2af393c41d6a22da17b529271fec375b31cc.tar.bz2
taler-mdb-821b2af393c41d6a22da17b529271fec375b31cc.zip
add multi-instance and preview support
-rw-r--r--src/main.c169
-rw-r--r--src/qr-show.c12
2 files changed, 159 insertions, 22 deletions
diff --git a/src/main.c b/src/main.c
index 0b2da81..8247d95 100644
--- a/src/main.c
+++ b/src/main.c
@@ -292,6 +292,20 @@ struct Product
char *description;
/**
+ * Which instance should be used for billing?
+ * Full URL, replaces the default base URL
+ * for orders involving this product. NULL if
+ * we should use the base_url.
+ */
+ char *instance;
+
+ /**
+ * Preview image to embed in the contract, NULL for
+ * no preview. Already base64 encoded.
+ */
+ char *preview;
+
+ /**
* Number of the product in the vending machine
*/
unsigned long long number;
@@ -883,7 +897,9 @@ show_qrcode (const char *uri)
/* turn on backlight if supported */
if (0 < qrDisplay.backlightfd)
- (void) write (qrDisplay.backlightfd, &backlight_on, 1);
+ (void) ! write (qrDisplay.backlightfd,
+ &backlight_on,
+ 1);
}
@@ -932,7 +948,9 @@ cleanup_payment (struct PaymentActivity *pa)
qrDisplay.var_info.xres * qrDisplay.var_info.yres
* sizeof (uint16_t));
if (0 < qrDisplay.backlightfd)
- (void) write (qrDisplay.backlightfd, &backlight_off, 1);
+ (void) ! write (qrDisplay.backlightfd,
+ &backlight_off,
+ 1);
#endif
GNUNET_free (pa->taler_pay_uri);
}
@@ -1069,14 +1087,20 @@ shutdown_task (void *cls)
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Unable to open /gpio/unexport for cancel button\n");
}
- (void) write (cancel_button.cancelbuttonfd, "23", 2);
+ (void) ! write (cancel_button.cancelbuttonfd,
+ "23",
+ 2);
close (cancel_button.cancelbuttonfd);
}
/* free the allocated productes read from config file */
if (NULL != products)
{
for (unsigned int i = 0; i < products_length; i++)
+ {
GNUNET_free (products[i].description);
+ GNUNET_free_non_null (products[i].instance);
+ GNUNET_free_non_null (products[i].preview);
+ }
GNUNET_array_grow (products,
products_length,
0);
@@ -1431,11 +1455,14 @@ static void
check_payment_again (void *cls)
{
struct PaymentActivity *pa = cls;
+ struct Product *p = pa->product;
pa->delay_pay_task = NULL;
GNUNET_assert (NULL == pa->cpo);
pa->cpo = TALER_MERCHANT_check_payment (ctx,
- backend_base_url,
+ (NULL == p->instance)
+ ? backend_base_url
+ : p->instance,
pa->order_id,
NULL /* snack machine, no Web crap */,
BACKEND_POLL_TIMEOUT,
@@ -1526,13 +1553,31 @@ launch_payment (struct Product *product)
uuid_s);
GNUNET_free (uuid_s);
/* create the json object for the order request */
- orderReq = json_pack ("{ s:s, s:o, s:s, s:o }",
- "summary", product->description,
- "amount", TALER_JSON_from_amount (&product->price),
- "fulfillment_url", fulflmntUrl
- ,"auto_refund", GNUNET_JSON_from_time_rel (
- MAX_REFUND_DELAY)
- );
+ if (NULL != product->preview)
+ {
+ orderReq = json_pack ("{ s:{s:s}, s:s, s:o, s:s, s:o }",
+ "summary",
+ "_",
+ product->description,
+ "preview", product->preview,
+ "amount", TALER_JSON_from_amount (&product->price),
+ "fulfillment_url", fulflmntUrl
+ ,"auto_refund", GNUNET_JSON_from_time_rel (
+ MAX_REFUND_DELAY)
+ );
+ }
+ else
+ {
+ orderReq = json_pack ("{ s:{s:s}, s:o, s:s, s:o }",
+ "summary",
+ "_",
+ product->description,
+ "amount", TALER_JSON_from_amount (&product->price),
+ "fulfillment_url", fulflmntUrl
+ ,"auto_refund", GNUNET_JSON_from_time_rel (
+ MAX_REFUND_DELAY)
+ );
+ }
GNUNET_free (fulflmntUrl);
if (NULL == orderReq)
{
@@ -1543,13 +1588,17 @@ launch_payment (struct Product *product)
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Creating order for `%s' at backend `%s'\n",
product->description,
- backend_base_url);
+ (NULL == product->instance)
+ ? backend_base_url
+ : product->instance);
pa = GNUNET_new (struct PaymentActivity);
pa->product = product;
pa->amount = product->price;
/* put the order on the merchant's backend */
pa->po = TALER_MERCHANT_order_put (ctx,
- backend_base_url,
+ (NULL == product->instance)
+ ? backend_base_url
+ : product->instance,
orderReq,
&proposal_cb,
pa);
@@ -1640,7 +1689,9 @@ vend_failure ()
mdb.session_running = GNUNET_NO;
r = GNUNET_new (struct Refund);
r->rio = TALER_MERCHANT_refund_increase (ctx,
- backend_base_url,
+ (NULL == p->instance)
+ ? backend_base_url
+ : p->instance,
payment_activity->order_id,
&payment_activity->amount,
"failed to dispense product",
@@ -1780,9 +1831,19 @@ cancel_button_pressed (void *cls)
{
(void) cls;
char value;
+
cancelbutton_task = NULL;
+ if (1 !=
+ read (cancel_button.cancelbuttonfd,
+ &value,
+ 1))
+ {
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
+ "read");
+ start_read_cancel_button ();
+ return;
+ }
- read (cancel_button.cancelbuttonfd, &value, 1);
lseek (cancel_button.cancelbuttonfd, 0, SEEK_SET);
/* This point should only be reached when a order is pending, because
* the scheduler read file gets added in the function "launch_payment".
@@ -1970,7 +2031,7 @@ write_mdb_command (void *cls)
chkSum += mdb.txBuffer[idx] = mdb.cmd->cmd.bin[idx];
for (size_t idx = 0; idx < mdb.cmd->data.bin_size; idx++)
chkSum += mdb.txBuffer[idx + mdb.cmd->cmd.bin_size] =
- mdb.cmd->data.bin[idx];
+ mdb.cmd->data.bin[idx];
mdb.txBuffer[mdb.cmd->cmd.bin_size + mdb.cmd->data.bin_size] =
(uint8_t) (chkSum & 0xFF);
}
@@ -2525,6 +2586,7 @@ read_products (void *cls,
{
struct Product tmpProduct;
char *tmpKey;
+ char *thumbnail_fn;
/* if the current section is not a product skip it */
if (0 != strncmp (section,
@@ -2592,6 +2654,73 @@ read_products (void *cls,
tmpProduct.key = '\0';
}
if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_string (cls,
+ section,
+ "instance",
+ &tmpProduct.instance))
+ tmpProduct.instance = NULL;
+ tmpProduct.preview = NULL;
+ if (GNUNET_OK ==
+ GNUNET_CONFIGURATION_get_value_string (cls,
+ section,
+ "thumbnail",
+ &thumbnail_fn))
+ {
+ struct GNUNET_DISK_FileHandle *fh;
+
+ fh = GNUNET_DISK_file_open (thumbnail_fn,
+ GNUNET_DISK_OPEN_READ,
+ GNUNET_DISK_PERM_NONE);
+ if (NULL == fh)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Could not open thumbnail `%s'\n",
+ thumbnail_fn);
+ }
+ else
+ {
+ off_t flen;
+
+ if (GNUNET_OK !=
+ GNUNET_DISK_file_handle_size (fh,
+ &flen))
+ {
+ GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
+ "stat",
+ thumbnail_fn);
+ }
+ else
+ {
+ void *thumb;
+ size_t len;
+ ssize_t ret;
+
+ len = (size_t) flen;
+ thumb = GNUNET_malloc (len);
+ ret = GNUNET_DISK_file_read (fh,
+ thumb,
+ len);
+ if ( (ret < 0) ||
+ (len != ((size_t) ret)) )
+ {
+ GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
+ "read",
+ thumbnail_fn);
+ }
+ else
+ {
+ tmpProduct.preview
+ = GNUNET_STRINGS_data_to_string_alloc (thumb,
+ len);
+ }
+ GNUNET_free (thumb);
+ }
+ GNUNET_break (GNUNET_OK ==
+ GNUNET_DISK_file_close (fh));
+ }
+ }
+ GNUNET_free (thumbnail_fn);
+ if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_number (cls,
section,
"number",
@@ -2601,6 +2730,8 @@ read_products (void *cls,
section,
"number");
GNUNET_free (tmpProduct.description);
+ GNUNET_free_non_null (tmpProduct.instance);
+ GNUNET_free_non_null (tmpProduct.preview);
return;
}
/* append the temporary product to the existing products */
@@ -2851,7 +2982,7 @@ run (void *cls,
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Unable to open /gpio/export for cancel button\n");
}
- (void) write (cancel_button.cancelbuttonfd, "23", 2);
+ (void) ! write (cancel_button.cancelbuttonfd, "23", 2);
close (cancel_button.cancelbuttonfd);
cancel_button.cancelbuttonfd = open ("/sys/class/gpio/gpio23/direction",
@@ -2861,7 +2992,7 @@ run (void *cls,
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Unable to open /gpio/gpio23/direction for cancel button\n");
}
- (void) write (cancel_button.cancelbuttonfd, "in", 2);
+ (void) ! write (cancel_button.cancelbuttonfd, "in", 2);
close (cancel_button.cancelbuttonfd);
cancel_button.cancelbuttonfd = open ("/sys/class/gpio/gpio23/value",
@@ -2948,7 +3079,7 @@ run (void *cls,
backlight_off = '1';
}
/* turn off the backlight */
- (void) write (qrDisplay.backlightfd, &backlight_off, 1);
+ (void) ! write (qrDisplay.backlightfd, &backlight_off, 1);
}
}
else
diff --git a/src/qr-show.c b/src/qr-show.c
index 0010a9a..728b9ca 100644
--- a/src/qr-show.c
+++ b/src/qr-show.c
@@ -214,7 +214,9 @@ show_qrcode (const char *uri)
QRinput_free (qri);
if (0 < qrDisplay.backlightfd)
- (void) write (qrDisplay.backlightfd, &backlight_on, 1);
+ (void) ! write (qrDisplay.backlightfd,
+ &backlight_on,
+ 1);
}
@@ -242,7 +244,9 @@ shutdown_task (void *cls)
qrDisplay.var_info.xres * qrDisplay.var_info.yres
* sizeof (uint16_t));
if (0 < qrDisplay.backlightfd)
- (void) write (qrDisplay.backlightfd, &backlight_off, 1);
+ (void) ! write (qrDisplay.backlightfd,
+ &backlight_off,
+ 1);
if (NULL != qrDisplay.memory)
{
/* free the display data */
@@ -382,7 +386,9 @@ run (void *cls,
backlight_on = '0';
backlight_off = '1';
}
- (void) write (qrDisplay.backlightfd, &backlight_off, 1);
+ (void) ! write (qrDisplay.backlightfd,
+ &backlight_off,
+ 1);
}
}
else