Line data Source code
1 : /*
2 : This file is part of TALER
3 : Copyright (C) 2014-2018 Taler Systems SA
4 :
5 : TALER 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 : 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 General Public License for more details.
12 :
13 : You should have received a copy of the GNU General Public License along with
14 : TALER; see the file COPYING. If not, see
15 : <http://www.gnu.org/licenses/>
16 : */
17 : /**
18 : * @file lib/auditor_api_exchanges.c
19 : * @brief Implementation of the /exchanges request of the auditor's HTTP API
20 : * @author Christian Grothoff
21 : */
22 : #include "platform.h"
23 : #include <jansson.h>
24 : #include <microhttpd.h> /* just for HTTP status codes */
25 : #include <gnunet/gnunet_util_lib.h>
26 : #include <gnunet/gnunet_json_lib.h>
27 : #include <gnunet/gnunet_curl_lib.h>
28 : #include "taler_json_lib.h"
29 : #include "taler_auditor_service.h"
30 : #include "auditor_api_handle.h"
31 : #include "taler_signatures.h"
32 : #include "auditor_api_curl_defaults.h"
33 :
34 : /**
35 : * How many exchanges do we allow a single auditor to
36 : * audit at most?
37 : */
38 : #define MAX_EXCHANGES 1024
39 :
40 :
41 : /**
42 : * @brief A ListExchanges Handle
43 : */
44 : struct TALER_AUDITOR_ListExchangesHandle
45 : {
46 :
47 : /**
48 : * The connection to auditor this request handle will use
49 : */
50 : struct TALER_AUDITOR_Handle *auditor;
51 :
52 : /**
53 : * The url for this request.
54 : */
55 : char *url;
56 :
57 : /**
58 : * Handle for the request.
59 : */
60 : struct GNUNET_CURL_Job *job;
61 :
62 : /**
63 : * Function to call with the result.
64 : */
65 : TALER_AUDITOR_ListExchangesResultCallback cb;
66 :
67 : /**
68 : * Closure for @a cb.
69 : */
70 : void *cb_cls;
71 :
72 : };
73 :
74 :
75 : /**
76 : * Function called when we're done processing the
77 : * HTTP /exchanges request.
78 : *
79 : * @param cls the `struct TALER_AUDITOR_ListExchangesHandle`
80 : * @param response_code HTTP response code, 0 on error
81 : * @param djson parsed JSON result, NULL on error
82 : */
83 : static void
84 0 : handle_exchanges_finished (void *cls,
85 : long response_code,
86 : const void *djson)
87 : {
88 0 : const json_t *json = djson;
89 : const json_t *ja;
90 : unsigned int ja_len;
91 0 : struct TALER_AUDITOR_ListExchangesHandle *leh = cls;
92 0 : struct TALER_AUDITOR_HttpResponse hr = {
93 : .reply = json,
94 0 : .http_status = (unsigned int) response_code
95 : };
96 :
97 0 : leh->job = NULL;
98 0 : switch (response_code)
99 : {
100 0 : case 0:
101 0 : hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
102 0 : break;
103 0 : case MHD_HTTP_OK:
104 0 : ja = json_object_get (json,
105 : "exchanges");
106 0 : if ( (NULL == ja) ||
107 0 : (! json_is_array (ja)) )
108 : {
109 0 : GNUNET_break (0);
110 0 : hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
111 0 : hr.http_status = 0;
112 0 : break;
113 : }
114 :
115 0 : ja_len = json_array_size (ja);
116 0 : if (ja_len > MAX_EXCHANGES)
117 : {
118 0 : GNUNET_break (0);
119 0 : hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
120 0 : hr.http_status = 0;
121 0 : break;
122 : }
123 0 : {
124 0 : struct TALER_AUDITOR_ExchangeInfo ei[ja_len];
125 : bool ok;
126 :
127 0 : ok = true;
128 0 : for (unsigned int i = 0; i<ja_len; i++)
129 : {
130 : struct GNUNET_JSON_Specification spec[] = {
131 0 : GNUNET_JSON_spec_fixed_auto ("master_pub", &ei[i].master_pub),
132 0 : GNUNET_JSON_spec_string ("exchange_url", &ei[i].exchange_url),
133 0 : GNUNET_JSON_spec_end ()
134 : };
135 :
136 0 : if (GNUNET_OK !=
137 0 : GNUNET_JSON_parse (json_array_get (ja,
138 : i),
139 : spec,
140 : NULL, NULL))
141 : {
142 0 : GNUNET_break_op (0);
143 0 : ok = false;
144 0 : hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
145 0 : hr.http_status = 0;
146 0 : break;
147 : }
148 : }
149 0 : if (! ok)
150 0 : break;
151 0 : leh->cb (leh->cb_cls,
152 : &hr,
153 : ja_len,
154 : ei);
155 0 : TALER_AUDITOR_list_exchanges_cancel (leh);
156 0 : return;
157 : }
158 0 : case MHD_HTTP_BAD_REQUEST:
159 : /* This should never happen, either us or the auditor is buggy
160 : (or API version conflict); just pass JSON reply to the application */
161 0 : hr.ec = TALER_JSON_get_error_code (json);
162 0 : hr.hint = TALER_JSON_get_error_hint (json);
163 0 : break;
164 0 : case MHD_HTTP_NOT_FOUND:
165 : /* Nothing really to verify, this should never
166 : happen, we should pass the JSON reply to the application */
167 0 : hr.ec = TALER_JSON_get_error_code (json);
168 0 : hr.hint = TALER_JSON_get_error_hint (json);
169 0 : break;
170 0 : case MHD_HTTP_INTERNAL_SERVER_ERROR:
171 : /* Server had an internal issue; we should retry, but this API
172 : leaves this to the application */
173 0 : hr.ec = TALER_JSON_get_error_code (json);
174 0 : hr.hint = TALER_JSON_get_error_hint (json);
175 0 : break;
176 0 : default:
177 : /* unexpected response code */
178 0 : hr.ec = TALER_JSON_get_error_code (json);
179 0 : hr.hint = TALER_JSON_get_error_hint (json);
180 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
181 : "Unexpected response code %u/%d for auditor list-exchanges request\n",
182 : (unsigned int) response_code,
183 : (int) hr.ec);
184 0 : GNUNET_break_op (0);
185 0 : break;
186 : }
187 0 : if (NULL != leh->cb)
188 0 : leh->cb (leh->cb_cls,
189 : &hr,
190 : 0,
191 : NULL);
192 0 : TALER_AUDITOR_list_exchanges_cancel (leh);
193 : }
194 :
195 :
196 : struct TALER_AUDITOR_ListExchangesHandle *
197 0 : TALER_AUDITOR_list_exchanges (struct TALER_AUDITOR_Handle *auditor,
198 : TALER_AUDITOR_ListExchangesResultCallback cb,
199 : void *cb_cls)
200 : {
201 : struct TALER_AUDITOR_ListExchangesHandle *leh;
202 : struct GNUNET_CURL_Context *ctx;
203 : CURL *eh;
204 :
205 0 : GNUNET_assert (GNUNET_YES ==
206 : TALER_AUDITOR_handle_is_ready_ (auditor));
207 :
208 0 : leh = GNUNET_new (struct TALER_AUDITOR_ListExchangesHandle);
209 0 : leh->auditor = auditor;
210 0 : leh->cb = cb;
211 0 : leh->cb_cls = cb_cls;
212 0 : leh->url = TALER_AUDITOR_path_to_url_ (auditor,
213 : "/exchanges");
214 0 : if (NULL == leh->url)
215 : {
216 0 : GNUNET_free (leh);
217 0 : return NULL;
218 : }
219 0 : GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
220 : "URL for list-exchanges: `%s'\n",
221 : leh->url);
222 0 : eh = TALER_AUDITOR_curl_easy_get_ (leh->url);
223 0 : if (NULL == eh)
224 : {
225 0 : GNUNET_break (0);
226 0 : GNUNET_free (leh->url);
227 0 : GNUNET_free (leh);
228 0 : return NULL;
229 : }
230 0 : ctx = TALER_AUDITOR_handle_to_context_ (auditor);
231 0 : leh->job = GNUNET_CURL_job_add (ctx,
232 : eh,
233 : &handle_exchanges_finished,
234 : leh);
235 0 : return leh;
236 : }
237 :
238 :
239 : void
240 0 : TALER_AUDITOR_list_exchanges_cancel (
241 : struct TALER_AUDITOR_ListExchangesHandle *leh)
242 : {
243 0 : if (NULL != leh->job)
244 : {
245 0 : GNUNET_CURL_job_cancel (leh->job);
246 0 : leh->job = NULL;
247 : }
248 0 : GNUNET_free (leh->url);
249 0 : GNUNET_free (leh);
250 0 : }
251 :
252 :
253 : /* end of auditor_api_exchanges.c */
|