LCOV - code coverage report
Current view: top level - lib - merchant_api_track_transfer.c (source / functions) Hit Total Coverage
Test: rcoverage.info Lines: 47 64 73.4 %
Date: 2018-09-21 06:18:36 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /*
       2             :   This file is part of TALER
       3             :   Copyright (C) 2014-2017 GNUnet e.V. and INRIA
       4             : 
       5             :   TALER is free software; you can redistribute it and/or modify it under the
       6             :   terms of the GNU Lesser General Public License as published by the Free Software
       7             :   Foundation; either version 2.1, or (at your option) any later version.
       8             : 
       9             :   TALER 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 Lesser General Public License for more details.
      12             : 
      13             :   You should have received a copy of the GNU Lesser General Public License along with
      14             :   TALER; see the file COPYING.LGPL.  If not, see
      15             :   <http://www.gnu.org/licenses/>
      16             : */
      17             : /**
      18             :  * @file lib/merchant_api_track_transfer.c
      19             :  * @brief Implementation of the /track/transfer request of the
      20             :  * merchant's HTTP API
      21             :  * @author Marcello Stanisci
      22             :  * @author Christian Grothoff
      23             :  */
      24             : #include "platform.h"
      25             : #include <curl/curl.h>
      26             : #include <jansson.h>
      27             : #include <microhttpd.h> /* just for HTTP status codes */
      28             : #include <gnunet/gnunet_util_lib.h>
      29             : #include <gnunet/gnunet_curl_lib.h>
      30             : #include "taler_merchant_service.h"
      31             : #include <taler/taler_json_lib.h>
      32             : #include <taler/taler_signatures.h>
      33             : 
      34             : 
      35             : /**
      36             :  * @brief A Handle for tracking wire transfers.
      37             :  */
      38             : struct TALER_MERCHANT_TrackTransferHandle
      39             : {
      40             : 
      41             :   /**
      42             :    * The url for this request.
      43             :    */
      44             :   char *url;
      45             : 
      46             :   /**
      47             :    * Handle for the request.
      48             :    */
      49             :   struct GNUNET_CURL_Job *job;
      50             : 
      51             :   /**
      52             :    * Function to call with the result.
      53             :    */
      54             :   TALER_MERCHANT_TrackTransferCallback cb;
      55             : 
      56             :   /**
      57             :    * Closure for @a cb.
      58             :    */
      59             :   void *cb_cls;
      60             : 
      61             :   /**
      62             :    * Reference to the execution context.
      63             :    */
      64             :   struct GNUNET_CURL_Context *ctx;
      65             : };
      66             : 
      67             : 
      68             : /**
      69             :  * We got a #MHD_HTTP_OK response for the /track/transfer request.
      70             :  * Check that the response is well-formed and if it is, call the
      71             :  * callback.  If not, return an error code.
      72             :  *
      73             :  * This code is very similar to
      74             :  * exchange_api_track_transfer.c::check_track_transfer_response_ok.
      75             :  * (Except we do not check the signature, as that was done by the
      76             :  * backend which we trust already.)
      77             :  * Any changes should likely be reflected there as well.
      78             :  *
      79             :  * @param wdh handle to the operation
      80             :  * @param json response we got
      81             :  * @return #GNUNET_OK if we are done and all is well,
      82             :  *         #GNUNET_SYSERR if the response was bogus
      83             :  */
      84             : static int
      85          12 : check_track_transfer_response_ok (struct TALER_MERCHANT_TrackTransferHandle *wdh,
      86             :                                   const json_t *json)
      87             : {
      88             :   json_t *deposits;
      89             :   struct GNUNET_HashCode h_wire;
      90             :   struct TALER_Amount total_amount;
      91             :   struct TALER_MerchantPublicKeyP merchant_pub;
      92             :   unsigned int num_details;
      93             :   struct TALER_ExchangePublicKeyP exchange_pub;
      94          12 :   struct GNUNET_JSON_Specification inner_spec[] = {
      95             :     TALER_JSON_spec_amount ("total", &total_amount),
      96             :     GNUNET_JSON_spec_fixed_auto ("merchant_pub", &merchant_pub),
      97             :     GNUNET_JSON_spec_fixed_auto ("H_wire", &h_wire),
      98             :     GNUNET_JSON_spec_json ("deposits_sums", &deposits),
      99             :     GNUNET_JSON_spec_fixed_auto ("exchange_pub", &exchange_pub),
     100             :     GNUNET_JSON_spec_end()
     101             :   };
     102             : 
     103          12 :   if (GNUNET_OK !=
     104          12 :       GNUNET_JSON_parse (json,
     105             :                          inner_spec,
     106             :                          NULL, NULL))
     107             :   {
     108           0 :     GNUNET_break_op (0);
     109           0 :     return GNUNET_SYSERR;
     110             :   }
     111          12 :   num_details = json_array_size (deposits);
     112          12 :   {
     113          12 :     struct TALER_MERCHANT_TrackTransferDetails details[num_details];
     114             : 
     115          24 :     for (unsigned int i=0;i<num_details;i++)
     116             :     {
     117          12 :       struct TALER_MERCHANT_TrackTransferDetails *detail = &details[i];
     118          12 :       json_t *deposit = json_array_get (deposits, i);
     119          36 :       struct GNUNET_JSON_Specification spec_detail[] = {
     120          12 :         GNUNET_JSON_spec_string ("order_id", &detail->order_id),
     121          12 :         TALER_JSON_spec_amount ("deposit_value", &detail->deposit_value),
     122          12 :         TALER_JSON_spec_amount ("deposit_fee", &detail->deposit_fee),
     123             :         GNUNET_JSON_spec_end()
     124             :       };
     125             : 
     126          12 :       if (GNUNET_OK !=
     127          12 :           GNUNET_JSON_parse (deposit,
     128             :                              spec_detail,
     129             :                              NULL, NULL))
     130             :       {
     131           0 :         GNUNET_break_op (0);
     132           0 :         GNUNET_JSON_parse_free (inner_spec);
     133           0 :         return GNUNET_SYSERR;
     134             :       }
     135             :     }
     136          12 :     wdh->cb (wdh->cb_cls,
     137             :              MHD_HTTP_OK,
     138             :              TALER_EC_NONE,
     139             :              &exchange_pub,
     140             :              json,
     141             :              &h_wire,
     142             :              &total_amount,
     143             :              num_details,
     144             :              details);
     145             :   }
     146          12 :   GNUNET_JSON_parse_free (inner_spec);
     147          12 :   return GNUNET_OK;
     148             : }
     149             : 
     150             : 
     151             : /**
     152             :  * Function called when we're done processing the
     153             :  * HTTP /track/transfer request.
     154             :  *
     155             :  * @param cls the `struct TALER_MERCHANT_TrackTransferHandle`
     156             :  * @param response_code HTTP response code, 0 on error
     157             :  * @param json response body, NULL if not in JSON
     158             :  */
     159             : static void
     160          13 : handle_track_transfer_finished (void *cls,
     161             :                                 long response_code,
     162             :                                 const json_t *json)
     163             : {
     164          13 :   struct TALER_MERCHANT_TrackTransferHandle *tdo = cls;
     165             : 
     166          13 :   tdo->job = NULL;
     167          13 :   switch (response_code)
     168             :   {
     169             :   case 0:
     170           0 :     break;
     171             :   case MHD_HTTP_OK:
     172          12 :     if (GNUNET_OK ==
     173          12 :         check_track_transfer_response_ok (tdo,
     174             :                                           json))
     175             :     {
     176          12 :       TALER_MERCHANT_track_transfer_cancel (tdo);
     177          12 :       return;
     178             :     }
     179           0 :     GNUNET_break_op (0);
     180           0 :     response_code = 0;
     181           0 :     break;
     182             :   case MHD_HTTP_FAILED_DEPENDENCY:
     183             :     /* Not a reason to break execution.  */ 
     184           1 :     break;
     185             :   case MHD_HTTP_NOT_FOUND:
     186             :     /* Nothing really to verify, this should never
     187             :        happen, we should pass the JSON reply to the application */
     188           0 :     break;
     189             :   case MHD_HTTP_INTERNAL_SERVER_ERROR:
     190             :     /* Server had an internal issue; we should retry, but this API
     191             :        leaves this to the application */
     192           0 :     break;
     193             :   default:
     194             :     /* unexpected response code */
     195           0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     196             :                 "Unexpected response code %u\n",
     197             :                 (unsigned int) response_code);
     198           0 :     GNUNET_break (0);
     199           0 :     response_code = 0;
     200           0 :     break;
     201             :   }
     202           1 :   tdo->cb (tdo->cb_cls,
     203             :            response_code,
     204             :            TALER_JSON_get_error_code (json),
     205             :            NULL,
     206             :            json,
     207             :            NULL,
     208             :            NULL,
     209             :            0,
     210             :            NULL);
     211           1 :   TALER_MERCHANT_track_transfer_cancel (tdo);
     212             : }
     213             : 
     214             : 
     215             : /**
     216             :  * Request backend to return transfers associated with a given wtid.
     217             :  *
     218             :  * @param ctx execution context
     219             :  * @param backend_url base URL of the backend
     220             :  * @param instance which merchant instance is going to be tracked
     221             :  * @param wire_method wire method used for the wire transfer
     222             :  * @param wtid base32 string indicating a wtid
     223             :  * @param exchange_url base URL of the exchange in charge of returning the wanted information
     224             :  * @param track_transfer_cb the callback to call when a reply for this request is available
     225             :  * @param track_transfer_cb_cls closure for @a contract_cb
     226             :  * @return a handle for this request
     227             :  */
     228             : struct TALER_MERCHANT_TrackTransferHandle *
     229          13 : TALER_MERCHANT_track_transfer (struct GNUNET_CURL_Context *ctx,
     230             :                                const char *backend_url,
     231             :                                const char *instance,
     232             :                                const char *wire_method,
     233             :                                const struct TALER_WireTransferIdentifierRawP *wtid,
     234             :                                const char *exchange_url,
     235             :                                TALER_MERCHANT_TrackTransferCallback track_transfer_cb,
     236             :                                void *track_transfer_cb_cls)
     237             : {
     238             :   struct TALER_MERCHANT_TrackTransferHandle *tdo;
     239             :   CURL *eh;
     240             :   char *wtid_str;
     241             : 
     242          13 :   wtid_str = GNUNET_STRINGS_data_to_string_alloc (wtid,
     243             :                                                   sizeof (struct TALER_WireTransferIdentifierRawP));
     244          13 :   tdo = GNUNET_new (struct TALER_MERCHANT_TrackTransferHandle);
     245          13 :   tdo->ctx = ctx;
     246          13 :   tdo->cb = track_transfer_cb; // very last to be called
     247          13 :   tdo->cb_cls = track_transfer_cb_cls;
     248          13 :   tdo->url = TALER_url_join (backend_url, "/track/transfer",
     249             :                              "wtid", wtid_str,
     250             :                              "exchange", exchange_url,
     251             :                              "instance", instance,
     252             :                              "wire_method", wire_method,
     253             :                              NULL);
     254          13 :   GNUNET_free (wtid_str);
     255          13 :   eh = curl_easy_init ();
     256          13 :   GNUNET_assert (CURLE_OK ==
     257             :                  curl_easy_setopt (eh,
     258             :                                    CURLOPT_URL,
     259             :                                    tdo->url));
     260          13 :   tdo->job = GNUNET_CURL_job_add (ctx,
     261             :                                   eh,
     262             :                                   GNUNET_YES,
     263             :                                   &handle_track_transfer_finished,
     264             :                                   tdo);
     265          13 :   return tdo;
     266             : }
     267             : 
     268             : 
     269             : /**
     270             :  * Cancel a /track/transfer request.  This function cannot be used
     271             :  * on a request handle if a response is already served for it.
     272             :  *
     273             :  * @param tdo handle to the tracking operation being cancelled
     274             :  */
     275             : void
     276          13 : TALER_MERCHANT_track_transfer_cancel (struct TALER_MERCHANT_TrackTransferHandle *tdo)
     277             : {
     278          13 :   if (NULL != tdo->job)
     279             :   {
     280           0 :     GNUNET_CURL_job_cancel (tdo->job);
     281           0 :     tdo->job = NULL;
     282             :   }
     283          13 :   GNUNET_free (tdo->url);
     284          13 :   GNUNET_free (tdo);
     285          13 : }
     286             : 
     287             : /* end of merchant_api_track_transfer.c */

Generated by: LCOV version 1.13