aboutsummaryrefslogtreecommitdiff
path: root/src/restclient/anastasis_api_policy_meta_lookup.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/restclient/anastasis_api_policy_meta_lookup.c')
-rw-r--r--src/restclient/anastasis_api_policy_meta_lookup.c267
1 files changed, 267 insertions, 0 deletions
diff --git a/src/restclient/anastasis_api_policy_meta_lookup.c b/src/restclient/anastasis_api_policy_meta_lookup.c
new file mode 100644
index 0000000..9be49ca
--- /dev/null
+++ b/src/restclient/anastasis_api_policy_meta_lookup.c
@@ -0,0 +1,267 @@
1/*
2 This file is part of ANASTASIS
3 Copyright (C) 2022 Anastasis SARL
4
5 ANASTASIS is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as
7 published by the Free Software Foundation; either version 2.1,
8 or (at your option) any later version.
9
10 ANASTASIS is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public
16 License along with ANASTASIS; see the file COPYING.LGPL. If not,
17 see <http://www.gnu.org/licenses/>
18*/
19
20/**
21 * @file restclient/anastasis_api_policy_meta_lookup.c
22 * @brief Implementation of the /policy/$POL/meta GET request
23 * @author Christian Grothoff
24 */
25#include "platform.h"
26#include <curl/curl.h>
27#include <jansson.h>
28#include <microhttpd.h> /* just for HTTP status codes */
29#include "anastasis_service.h"
30#include "anastasis_api_curl_defaults.h"
31#include <taler/taler_signatures.h>
32
33
34/**
35 * @brief A Meta Operation Handle
36 */
37struct ANASTASIS_PolicyMetaLookupOperation
38{
39
40 /**
41 * The url for this request, including parameters.
42 */
43 char *url;
44
45 /**
46 * Handle for the request.
47 */
48 struct GNUNET_CURL_Job *job;
49
50 /**
51 * Function to call with the result.
52 */
53 ANASTASIS_PolicyMetaLookupCallback cb;
54
55 /**
56 * Closure for @a cb.
57 */
58 void *cb_cls;
59
60 /**
61 * Reference to the execution context.
62 */
63 struct GNUNET_CURL_Context *ctx;
64
65 /**
66 * Public key of the account we are downloading from.
67 */
68 struct ANASTASIS_CRYPTO_AccountPublicKeyP account_pub;
69
70 /**
71 * Maximum version to fetch.
72 */
73 uint32_t max_version;
74
75};
76
77
78/**
79 * Process GET /policy/$POL/meta response
80 *
81 * @param cls our `struct ANASTASIS_PolicyMetaLookupOperation *`
82 * @param response_code HTTP status
83 * @param data response body, a `json_t *`, NULL on error
84 */
85static void
86handle_policy_meta_lookup_finished (void *cls,
87 long response_code,
88 const void *response)
89{
90 struct ANASTASIS_PolicyMetaLookupOperation *plo = cls;
91 const json_t *json = response;
92
93 plo->job = NULL;
94 switch (response_code)
95 {
96 case 0:
97 /* Hard error */
98 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
99 "Backend didn't even return from GET /policy\n");
100 break;
101 case MHD_HTTP_OK:
102 {
103 size_t mlen = json_object_size (json);
104
105 /* put a cap, as we will stack-allocate below and the
106 current service LIMITs the result to 1000 anyway;
107 could theoretically be increased in the future, but
108 then we should not put this onto the stack anymore... */
109 if (mlen > 10000)
110 {
111 GNUNET_break (0);
112 response_code = 0;
113 break;
114 }
115 {
116 struct ANASTASIS_MetaDataEntry metas[GNUNET_NZL (mlen)];
117 void *md[GNUNET_NZL (mlen)];
118 struct ANASTASIS_MetaDownloadDetails mdd = {
119 .metas = metas,
120 .metas_length = mlen
121 };
122 size_t off = 0;
123 const char *label;
124 const json_t *val;
125
126 memset (md,
127 0,
128 sizeof (md));
129 json_object_foreach ((json_t *) json,
130 label,
131 val)
132 {
133 unsigned int ver;
134 char dummy;
135 const char *vals;
136
137 if (1 != sscanf (label,
138 "%u%c",
139 &ver,
140 &dummy))
141 {
142 GNUNET_break (0);
143 break;
144 }
145 metas[off].version = (uint32_t) ver;
146 if (json_is_null (val))
147 {
148 metas[off].meta_data = NULL;
149 metas[off].meta_data_size = 0;
150 off++;
151 continue;
152 }
153 vals = json_string_value (val);
154 if ( (NULL == vals) ||
155 (GNUNET_OK !=
156 GNUNET_STRINGS_string_to_data_alloc (vals,
157 strlen (vals),
158 &md[off],
159 &metas[off].meta_data_size)) )
160 {
161 GNUNET_break (0);
162 break;
163 }
164 metas[off].version = (uint32_t) ver;
165 metas[off].meta_data = md[off];
166 off++;
167 }
168 if (off < mlen)
169 {
170 GNUNET_break (0);
171 response_code = 0;
172 for (size_t i = 0; i<off; i++)
173 GNUNET_free (md[i]);
174 break;
175 }
176 plo->cb (plo->cb_cls,
177 response_code,
178 &mdd);
179 for (size_t i = 0; i<off; i++)
180 GNUNET_free (md[i]);
181 plo->cb = NULL;
182 }
183 ANASTASIS_policy_meta_lookup_cancel (plo);
184 return;
185 }
186 case MHD_HTTP_BAD_REQUEST:
187 /* This should never happen, either us or the anastasis server is buggy
188 (or API version conflict); just pass JSON reply to the application */
189 break;
190 case MHD_HTTP_NOT_FOUND:
191 /* Nothing really to verify */
192 break;
193 case MHD_HTTP_INTERNAL_SERVER_ERROR:
194 /* Server had an internal issue; we should retry, but this API
195 leaves this to the application */
196 break;
197 default:
198 /* unexpected response code */
199 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
200 "Unexpected response code %u\n",
201 (unsigned int) response_code);
202 GNUNET_break (0);
203 response_code = 0;
204 break;
205 }
206 plo->cb (plo->cb_cls,
207 response_code,
208 NULL);
209 plo->cb = NULL;
210 ANASTASIS_policy_meta_lookup_cancel (plo);
211}
212
213
214struct ANASTASIS_PolicyMetaLookupOperation *
215ANASTASIS_policy_meta_lookup (
216 struct GNUNET_CURL_Context *ctx,
217 const char *backend_url,
218 const struct ANASTASIS_CRYPTO_AccountPublicKeyP *anastasis_pub,
219 uint32_t max_version,
220 ANASTASIS_PolicyMetaLookupCallback cb,
221 void *cb_cls)
222{
223 struct ANASTASIS_PolicyMetaLookupOperation *plo;
224 CURL *eh;
225 char *path;
226
227 GNUNET_assert (NULL != cb);
228 plo = GNUNET_new (struct ANASTASIS_PolicyMetaLookupOperation);
229 plo->account_pub = *anastasis_pub;
230 {
231 char *acc_pub_str;
232
233 acc_pub_str = GNUNET_STRINGS_data_to_string_alloc (anastasis_pub,
234 sizeof (*anastasis_pub));
235 GNUNET_asprintf (&path,
236 "policy/%s/meta",
237 acc_pub_str);
238 GNUNET_free (acc_pub_str);
239 }
240 plo->url = TALER_url_join (backend_url,
241 path,
242 NULL);
243 GNUNET_free (path);
244 eh = ANASTASIS_curl_easy_get_ (plo->url);
245 GNUNET_assert (NULL != eh);
246 plo->cb = cb;
247 plo->cb_cls = cb_cls;
248 plo->job = GNUNET_CURL_job_add (ctx,
249 eh,
250 &handle_policy_meta_lookup_finished,
251 plo);
252 return plo;
253}
254
255
256void
257ANASTASIS_policy_meta_lookup_cancel (struct
258 ANASTASIS_PolicyMetaLookupOperation *plo)
259{
260 if (NULL != plo->job)
261 {
262 GNUNET_CURL_job_cancel (plo->job);
263 plo->job = NULL;
264 }
265 GNUNET_free (plo->url);
266 GNUNET_free (plo);
267}