diff options
Diffstat (limited to 'src/curl/curl.c')
-rw-r--r-- | src/curl/curl.c | 529 |
1 files changed, 263 insertions, 266 deletions
diff --git a/src/curl/curl.c b/src/curl/curl.c index 38a1f5fcd..8e66ba4cb 100644 --- a/src/curl/curl.c +++ b/src/curl/curl.c | |||
@@ -1,22 +1,22 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet | 2 | This file is part of GNUnet |
3 | Copyright (C) 2014, 2015, 2016, 2018 GNUnet e.V. | 3 | Copyright (C) 2014, 2015, 2016, 2018 GNUnet e.V. |
4 | 4 | ||
5 | GNUnet is free software: you can redistribute it and/or modify it | 5 | GNUnet is free software: you can redistribute it and/or modify it |
6 | under the terms of the GNU Affero General Public License as published | 6 | under the terms of the GNU Affero General Public License as published |
7 | by the Free Software Foundation, either version 3 of the License, | 7 | by the Free Software Foundation, either version 3 of the License, |
8 | or (at your option) any later version. | 8 | or (at your option) any later version. |
9 | 9 | ||
10 | GNUnet is distributed in the hope that it will be useful, but | 10 | GNUnet is distributed in the hope that it will be useful, but |
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | 11 | WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | Affero General Public License for more details. | 13 | Affero General Public License for more details. |
14 | 14 | ||
15 | You should have received a copy of the GNU Affero General Public License | 15 | You should have received a copy of the GNU Affero General Public License |
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | 16 | along with this program. If not, see <http://www.gnu.org/licenses/>. |
17 | 17 | ||
18 | SPDX-License-Identifier: AGPL3.0-or-later | 18 | SPDX-License-Identifier: AGPL3.0-or-later |
19 | */ | 19 | */ |
20 | /** | 20 | /** |
21 | * @file curl/curl.c | 21 | * @file curl/curl.c |
22 | * @brief API for downloading JSON via CURL | 22 | * @brief API for downloading JSON via CURL |
@@ -40,23 +40,23 @@ | |||
40 | * @param code what was the curl error code | 40 | * @param code what was the curl error code |
41 | */ | 41 | */ |
42 | #define CURL_STRERROR(type, function, code) \ | 42 | #define CURL_STRERROR(type, function, code) \ |
43 | GNUNET_log (type, \ | 43 | GNUNET_log(type, \ |
44 | "Curl function `%s' has failed at `%s:%d' with error: %s\n", \ | 44 | "Curl function `%s' has failed at `%s:%d' with error: %s\n", \ |
45 | function, \ | 45 | function, \ |
46 | __FILE__, \ | 46 | __FILE__, \ |
47 | __LINE__, \ | 47 | __LINE__, \ |
48 | curl_easy_strerror (code)); | 48 | curl_easy_strerror(code)); |
49 | 49 | ||
50 | /** | 50 | /** |
51 | * Print JSON parsing related error information | 51 | * Print JSON parsing related error information |
52 | */ | 52 | */ |
53 | #define JSON_WARN(error) \ | 53 | #define JSON_WARN(error) \ |
54 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, \ | 54 | GNUNET_log(GNUNET_ERROR_TYPE_WARNING, \ |
55 | "JSON parsing failed at %s:%u: %s (%s)\n", \ | 55 | "JSON parsing failed at %s:%u: %s (%s)\n", \ |
56 | __FILE__, \ | 56 | __FILE__, \ |
57 | __LINE__, \ | 57 | __LINE__, \ |
58 | error.text, \ | 58 | error.text, \ |
59 | error.source) | 59 | error.source) |
60 | 60 | ||
61 | 61 | ||
62 | /** | 62 | /** |
@@ -68,9 +68,7 @@ static int curl_fail; | |||
68 | /** | 68 | /** |
69 | * Jobs are CURL requests running within a `struct GNUNET_CURL_Context`. | 69 | * Jobs are CURL requests running within a `struct GNUNET_CURL_Context`. |
70 | */ | 70 | */ |
71 | struct GNUNET_CURL_Job | 71 | struct GNUNET_CURL_Job { |
72 | { | ||
73 | |||
74 | /** | 72 | /** |
75 | * We keep jobs in a DLL. | 73 | * We keep jobs in a DLL. |
76 | */ | 74 | */ |
@@ -117,8 +115,7 @@ struct GNUNET_CURL_Job | |||
117 | /** | 115 | /** |
118 | * Context | 116 | * Context |
119 | */ | 117 | */ |
120 | struct GNUNET_CURL_Context | 118 | struct GNUNET_CURL_Context { |
121 | { | ||
122 | /** | 119 | /** |
123 | * Curl multi handle | 120 | * Curl multi handle |
124 | */ | 121 | */ |
@@ -172,30 +169,30 @@ struct GNUNET_CURL_Context | |||
172 | * @return library context | 169 | * @return library context |
173 | */ | 170 | */ |
174 | struct GNUNET_CURL_Context * | 171 | struct GNUNET_CURL_Context * |
175 | GNUNET_CURL_init (GNUNET_CURL_RescheduleCallback cb, void *cb_cls) | 172 | GNUNET_CURL_init(GNUNET_CURL_RescheduleCallback cb, void *cb_cls) |
176 | { | 173 | { |
177 | struct GNUNET_CURL_Context *ctx; | 174 | struct GNUNET_CURL_Context *ctx; |
178 | CURLM *multi; | 175 | CURLM *multi; |
179 | CURLSH *share; | 176 | CURLSH *share; |
180 | 177 | ||
181 | if (curl_fail) | 178 | if (curl_fail) |
182 | { | 179 | { |
183 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Curl was not initialised properly\n"); | 180 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Curl was not initialised properly\n"); |
184 | return NULL; | 181 | return NULL; |
185 | } | 182 | } |
186 | if (NULL == (multi = curl_multi_init ())) | 183 | if (NULL == (multi = curl_multi_init())) |
187 | { | 184 | { |
188 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 185 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, |
189 | "Failed to create a Curl multi handle\n"); | 186 | "Failed to create a Curl multi handle\n"); |
190 | return NULL; | 187 | return NULL; |
191 | } | 188 | } |
192 | if (NULL == (share = curl_share_init ())) | 189 | if (NULL == (share = curl_share_init())) |
193 | { | 190 | { |
194 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 191 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, |
195 | "Failed to create a Curl share handle\n"); | 192 | "Failed to create a Curl share handle\n"); |
196 | return NULL; | 193 | return NULL; |
197 | } | 194 | } |
198 | ctx = GNUNET_new (struct GNUNET_CURL_Context); | 195 | ctx = GNUNET_new(struct GNUNET_CURL_Context); |
199 | ctx->cb = cb; | 196 | ctx->cb = cb; |
200 | ctx->cb_cls = cb_cls; | 197 | ctx->cb_cls = cb_cls; |
201 | ctx->multi = multi; | 198 | ctx->multi = multi; |
@@ -211,8 +208,8 @@ GNUNET_CURL_init (GNUNET_CURL_RescheduleCallback cb, void *cb_cls) | |||
211 | * @param header_name name of the header to send. | 208 | * @param header_name name of the header to send. |
212 | */ | 209 | */ |
213 | void | 210 | void |
214 | GNUNET_CURL_enable_async_scope_header (struct GNUNET_CURL_Context *ctx, | 211 | GNUNET_CURL_enable_async_scope_header(struct GNUNET_CURL_Context *ctx, |
215 | const char *header_name) | 212 | const char *header_name) |
216 | { | 213 | { |
217 | ctx->async_scope_id_header = header_name; | 214 | ctx->async_scope_id_header = header_name; |
218 | } | 215 | } |
@@ -232,26 +229,26 @@ GNUNET_CURL_enable_async_scope_header (struct GNUNET_CURL_Context *ctx, | |||
232 | * @return number of bytes processed from @a bufptr | 229 | * @return number of bytes processed from @a bufptr |
233 | */ | 230 | */ |
234 | static size_t | 231 | static size_t |
235 | download_cb (char *bufptr, size_t size, size_t nitems, void *cls) | 232 | download_cb(char *bufptr, size_t size, size_t nitems, void *cls) |
236 | { | 233 | { |
237 | struct GNUNET_CURL_DownloadBuffer *db = cls; | 234 | struct GNUNET_CURL_DownloadBuffer *db = cls; |
238 | size_t msize; | 235 | size_t msize; |
239 | void *buf; | 236 | void *buf; |
240 | 237 | ||
241 | if (0 == size * nitems) | 238 | if (0 == size * nitems) |
242 | { | 239 | { |
243 | /* Nothing (left) to do */ | 240 | /* Nothing (left) to do */ |
244 | return 0; | 241 | return 0; |
245 | } | 242 | } |
246 | msize = size * nitems; | 243 | msize = size * nitems; |
247 | if ((msize + db->buf_size) >= GNUNET_MAX_MALLOC_CHECKED) | 244 | if ((msize + db->buf_size) >= GNUNET_MAX_MALLOC_CHECKED) |
248 | { | 245 | { |
249 | db->eno = ENOMEM; | 246 | db->eno = ENOMEM; |
250 | return 0; /* signals an error to curl */ | 247 | return 0; /* signals an error to curl */ |
251 | } | 248 | } |
252 | db->buf = GNUNET_realloc (db->buf, db->buf_size + msize); | 249 | db->buf = GNUNET_realloc(db->buf, db->buf_size + msize); |
253 | buf = db->buf + db->buf_size; | 250 | buf = db->buf + db->buf_size; |
254 | GNUNET_memcpy (buf, bufptr, msize); | 251 | GNUNET_memcpy(buf, bufptr, msize); |
255 | db->buf_size += msize; | 252 | db->buf_size += msize; |
256 | return msize; | 253 | return msize; |
257 | } | 254 | } |
@@ -277,77 +274,77 @@ download_cb (char *bufptr, size_t size, size_t nitems, void *cls) | |||
277 | * @return NULL on error (in this case, @eh is still released!) | 274 | * @return NULL on error (in this case, @eh is still released!) |
278 | */ | 275 | */ |
279 | struct GNUNET_CURL_Job * | 276 | struct GNUNET_CURL_Job * |
280 | GNUNET_CURL_job_add2 (struct GNUNET_CURL_Context *ctx, | 277 | GNUNET_CURL_job_add2(struct GNUNET_CURL_Context *ctx, |
281 | CURL *eh, | 278 | CURL *eh, |
282 | const struct curl_slist *job_headers, | 279 | const struct curl_slist *job_headers, |
283 | GNUNET_CURL_JobCompletionCallback jcc, | 280 | GNUNET_CURL_JobCompletionCallback jcc, |
284 | void *jcc_cls) | 281 | void *jcc_cls) |
285 | { | 282 | { |
286 | struct GNUNET_CURL_Job *job; | 283 | struct GNUNET_CURL_Job *job; |
287 | struct curl_slist *all_headers = NULL; | 284 | struct curl_slist *all_headers = NULL; |
288 | 285 | ||
289 | for (const struct curl_slist *curr = job_headers; curr != NULL; | 286 | for (const struct curl_slist *curr = job_headers; curr != NULL; |
290 | curr = curr->next) | 287 | curr = curr->next) |
291 | { | 288 | { |
292 | GNUNET_assert (NULL != | 289 | GNUNET_assert(NULL != |
293 | (all_headers = curl_slist_append (all_headers, curr->data))); | 290 | (all_headers = curl_slist_append(all_headers, curr->data))); |
294 | } | 291 | } |
295 | 292 | ||
296 | for (const struct curl_slist *curr = ctx->common_headers; curr != NULL; | 293 | for (const struct curl_slist *curr = ctx->common_headers; curr != NULL; |
297 | curr = curr->next) | 294 | curr = curr->next) |
298 | { | 295 | { |
299 | GNUNET_assert (NULL != | 296 | GNUNET_assert(NULL != |
300 | (all_headers = curl_slist_append (all_headers, curr->data))); | 297 | (all_headers = curl_slist_append(all_headers, curr->data))); |
301 | } | 298 | } |
302 | 299 | ||
303 | if (NULL != ctx->async_scope_id_header) | 300 | if (NULL != ctx->async_scope_id_header) |
304 | { | ||
305 | struct GNUNET_AsyncScopeSave scope; | ||
306 | |||
307 | GNUNET_async_scope_get (&scope); | ||
308 | if (GNUNET_YES == scope.have_scope) | ||
309 | { | 301 | { |
310 | char *aid_header = NULL; | 302 | struct GNUNET_AsyncScopeSave scope; |
311 | aid_header = | 303 | |
312 | GNUNET_STRINGS_data_to_string_alloc (&scope.scope_id, | 304 | GNUNET_async_scope_get(&scope); |
313 | sizeof ( | 305 | if (GNUNET_YES == scope.have_scope) |
314 | struct GNUNET_AsyncScopeId)); | 306 | { |
315 | GNUNET_assert (NULL != aid_header); | 307 | char *aid_header = NULL; |
316 | GNUNET_assert (NULL != curl_slist_append (all_headers, aid_header)); | 308 | aid_header = |
317 | GNUNET_free (aid_header); | 309 | GNUNET_STRINGS_data_to_string_alloc(&scope.scope_id, |
310 | sizeof( | ||
311 | struct GNUNET_AsyncScopeId)); | ||
312 | GNUNET_assert(NULL != aid_header); | ||
313 | GNUNET_assert(NULL != curl_slist_append(all_headers, aid_header)); | ||
314 | GNUNET_free(aid_header); | ||
315 | } | ||
318 | } | 316 | } |
319 | } | ||
320 | 317 | ||
321 | if (CURLE_OK != curl_easy_setopt (eh, CURLOPT_HTTPHEADER, all_headers)) | 318 | if (CURLE_OK != curl_easy_setopt(eh, CURLOPT_HTTPHEADER, all_headers)) |
322 | { | 319 | { |
323 | GNUNET_break (0); | 320 | GNUNET_break(0); |
324 | curl_slist_free_all (all_headers); | 321 | curl_slist_free_all(all_headers); |
325 | curl_easy_cleanup (eh); | 322 | curl_easy_cleanup(eh); |
326 | return NULL; | 323 | return NULL; |
327 | } | 324 | } |
328 | 325 | ||
329 | job = GNUNET_new (struct GNUNET_CURL_Job); | 326 | job = GNUNET_new(struct GNUNET_CURL_Job); |
330 | job->job_headers = all_headers; | 327 | job->job_headers = all_headers; |
331 | 328 | ||
332 | if ((CURLE_OK != curl_easy_setopt (eh, CURLOPT_PRIVATE, job)) || | 329 | if ((CURLE_OK != curl_easy_setopt(eh, CURLOPT_PRIVATE, job)) || |
333 | (CURLE_OK != | 330 | (CURLE_OK != |
334 | curl_easy_setopt (eh, CURLOPT_WRITEFUNCTION, &download_cb)) || | 331 | curl_easy_setopt(eh, CURLOPT_WRITEFUNCTION, &download_cb)) || |
335 | (CURLE_OK != curl_easy_setopt (eh, CURLOPT_WRITEDATA, &job->db)) || | 332 | (CURLE_OK != curl_easy_setopt(eh, CURLOPT_WRITEDATA, &job->db)) || |
336 | (CURLE_OK != curl_easy_setopt (eh, CURLOPT_SHARE, ctx->share)) || | 333 | (CURLE_OK != curl_easy_setopt(eh, CURLOPT_SHARE, ctx->share)) || |
337 | (CURLM_OK != curl_multi_add_handle (ctx->multi, eh))) | 334 | (CURLM_OK != curl_multi_add_handle(ctx->multi, eh))) |
338 | { | 335 | { |
339 | GNUNET_break (0); | 336 | GNUNET_break(0); |
340 | GNUNET_free (job); | 337 | GNUNET_free(job); |
341 | curl_easy_cleanup (eh); | 338 | curl_easy_cleanup(eh); |
342 | return NULL; | 339 | return NULL; |
343 | } | 340 | } |
344 | 341 | ||
345 | job->easy_handle = eh; | 342 | job->easy_handle = eh; |
346 | job->ctx = ctx; | 343 | job->ctx = ctx; |
347 | job->jcc = jcc; | 344 | job->jcc = jcc; |
348 | job->jcc_cls = jcc_cls; | 345 | job->jcc_cls = jcc_cls; |
349 | GNUNET_CONTAINER_DLL_insert (ctx->jobs_head, ctx->jobs_tail, job); | 346 | GNUNET_CONTAINER_DLL_insert(ctx->jobs_head, ctx->jobs_tail, job); |
350 | ctx->cb (ctx->cb_cls); | 347 | ctx->cb(ctx->cb_cls); |
351 | return job; | 348 | return job; |
352 | } | 349 | } |
353 | 350 | ||
@@ -369,24 +366,24 @@ GNUNET_CURL_job_add2 (struct GNUNET_CURL_Context *ctx, | |||
369 | * @return NULL on error (in this case, @eh is still released!) | 366 | * @return NULL on error (in this case, @eh is still released!) |
370 | */ | 367 | */ |
371 | struct GNUNET_CURL_Job * | 368 | struct GNUNET_CURL_Job * |
372 | GNUNET_CURL_job_add (struct GNUNET_CURL_Context *ctx, | 369 | GNUNET_CURL_job_add(struct GNUNET_CURL_Context *ctx, |
373 | CURL *eh, | 370 | CURL *eh, |
374 | int add_json, | 371 | int add_json, |
375 | GNUNET_CURL_JobCompletionCallback jcc, | 372 | GNUNET_CURL_JobCompletionCallback jcc, |
376 | void *jcc_cls) | 373 | void *jcc_cls) |
377 | { | 374 | { |
378 | struct GNUNET_CURL_Job *job; | 375 | struct GNUNET_CURL_Job *job; |
379 | struct curl_slist *job_headers = NULL; | 376 | struct curl_slist *job_headers = NULL; |
380 | 377 | ||
381 | if (GNUNET_YES == add_json) | 378 | if (GNUNET_YES == add_json) |
382 | { | 379 | { |
383 | GNUNET_assert ( | 380 | GNUNET_assert( |
384 | NULL != (job_headers = | 381 | NULL != (job_headers = |
385 | curl_slist_append (NULL, "Content-Type: application/json"))); | 382 | curl_slist_append(NULL, "Content-Type: application/json"))); |
386 | } | 383 | } |
387 | 384 | ||
388 | job = GNUNET_CURL_job_add2 (ctx, eh, job_headers, jcc, jcc_cls); | 385 | job = GNUNET_CURL_job_add2(ctx, eh, job_headers, jcc, jcc_cls); |
389 | curl_slist_free_all (job_headers); | 386 | curl_slist_free_all(job_headers); |
390 | return job; | 387 | return job; |
391 | } | 388 | } |
392 | 389 | ||
@@ -398,17 +395,17 @@ GNUNET_CURL_job_add (struct GNUNET_CURL_Context *ctx, | |||
398 | * @param job job to cancel | 395 | * @param job job to cancel |
399 | */ | 396 | */ |
400 | void | 397 | void |
401 | GNUNET_CURL_job_cancel (struct GNUNET_CURL_Job *job) | 398 | GNUNET_CURL_job_cancel(struct GNUNET_CURL_Job *job) |
402 | { | 399 | { |
403 | struct GNUNET_CURL_Context *ctx = job->ctx; | 400 | struct GNUNET_CURL_Context *ctx = job->ctx; |
404 | 401 | ||
405 | GNUNET_CONTAINER_DLL_remove (ctx->jobs_head, ctx->jobs_tail, job); | 402 | GNUNET_CONTAINER_DLL_remove(ctx->jobs_head, ctx->jobs_tail, job); |
406 | GNUNET_break (CURLM_OK == | 403 | GNUNET_break(CURLM_OK == |
407 | curl_multi_remove_handle (ctx->multi, job->easy_handle)); | 404 | curl_multi_remove_handle(ctx->multi, job->easy_handle)); |
408 | curl_easy_cleanup (job->easy_handle); | 405 | curl_easy_cleanup(job->easy_handle); |
409 | GNUNET_free_non_null (job->db.buf); | 406 | GNUNET_free_non_null(job->db.buf); |
410 | curl_slist_free_all (job->job_headers); | 407 | curl_slist_free_all(job->job_headers); |
411 | GNUNET_free (job); | 408 | GNUNET_free(job); |
412 | } | 409 | } |
413 | 410 | ||
414 | 411 | ||
@@ -431,62 +428,62 @@ GNUNET_CURL_job_cancel (struct GNUNET_CURL_Job *job) | |||
431 | * @return NULL if downloading a JSON reply failed. | 428 | * @return NULL if downloading a JSON reply failed. |
432 | */ | 429 | */ |
433 | void * | 430 | void * |
434 | GNUNET_CURL_download_get_result_ (struct GNUNET_CURL_DownloadBuffer *db, | 431 | GNUNET_CURL_download_get_result_(struct GNUNET_CURL_DownloadBuffer *db, |
435 | CURL *eh, | 432 | CURL *eh, |
436 | long *response_code) | 433 | long *response_code) |
437 | { | 434 | { |
438 | json_t *json; | 435 | json_t *json; |
439 | json_error_t error; | 436 | json_error_t error; |
440 | char *ct; | 437 | char *ct; |
441 | 438 | ||
442 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 439 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, |
443 | "Downloaded body: %.*s\n", | 440 | "Downloaded body: %.*s\n", |
444 | (int) db->buf_size, | 441 | (int)db->buf_size, |
445 | (char *) db->buf); | 442 | (char *)db->buf); |
446 | 443 | ||
447 | if ((CURLE_OK != curl_easy_getinfo (eh, CURLINFO_CONTENT_TYPE, &ct)) || | 444 | if ((CURLE_OK != curl_easy_getinfo(eh, CURLINFO_CONTENT_TYPE, &ct)) || |
448 | (NULL == ct) || (0 != strcasecmp (ct, "application/json"))) | 445 | (NULL == ct) || (0 != strcasecmp(ct, "application/json"))) |
449 | { | ||
450 | /* No content type or explicitly not JSON, refuse to parse | ||
451 | (but keep response code) */ | ||
452 | if (CURLE_OK != | ||
453 | curl_easy_getinfo (eh, CURLINFO_RESPONSE_CODE, response_code)) | ||
454 | { | 446 | { |
455 | /* unexpected error... */ | 447 | /* No content type or explicitly not JSON, refuse to parse |
456 | GNUNET_break (0); | 448 | (but keep response code) */ |
457 | *response_code = 0; | 449 | if (CURLE_OK != |
450 | curl_easy_getinfo(eh, CURLINFO_RESPONSE_CODE, response_code)) | ||
451 | { | ||
452 | /* unexpected error... */ | ||
453 | GNUNET_break(0); | ||
454 | *response_code = 0; | ||
455 | } | ||
456 | if (0 != db->buf_size) | ||
457 | GNUNET_log(GNUNET_ERROR_TYPE_WARNING, | ||
458 | "Did NOT detect response as JSON\n"); | ||
459 | return NULL; | ||
458 | } | 460 | } |
459 | if (0 != db->buf_size) | ||
460 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
461 | "Did NOT detect response as JSON\n"); | ||
462 | return NULL; | ||
463 | } | ||
464 | json = NULL; | 461 | json = NULL; |
465 | if (0 == db->eno) | 462 | if (0 == db->eno) |
466 | { | ||
467 | json = json_loadb (db->buf, | ||
468 | db->buf_size, | ||
469 | JSON_REJECT_DUPLICATES | JSON_DISABLE_EOF_CHECK, | ||
470 | &error); | ||
471 | if (NULL == json) | ||
472 | { | 463 | { |
473 | JSON_WARN (error); | 464 | json = json_loadb(db->buf, |
474 | *response_code = 0; | 465 | db->buf_size, |
466 | JSON_REJECT_DUPLICATES | JSON_DISABLE_EOF_CHECK, | ||
467 | &error); | ||
468 | if (NULL == json) | ||
469 | { | ||
470 | JSON_WARN(error); | ||
471 | *response_code = 0; | ||
472 | } | ||
475 | } | 473 | } |
476 | } | 474 | GNUNET_free_non_null(db->buf); |
477 | GNUNET_free_non_null (db->buf); | ||
478 | db->buf = NULL; | 475 | db->buf = NULL; |
479 | db->buf_size = 0; | 476 | db->buf_size = 0; |
480 | if (NULL != json) | 477 | if (NULL != json) |
481 | { | ||
482 | if (CURLE_OK != | ||
483 | curl_easy_getinfo (eh, CURLINFO_RESPONSE_CODE, response_code)) | ||
484 | { | 478 | { |
485 | /* unexpected error... */ | 479 | if (CURLE_OK != |
486 | GNUNET_break (0); | 480 | curl_easy_getinfo(eh, CURLINFO_RESPONSE_CODE, response_code)) |
487 | *response_code = 0; | 481 | { |
482 | /* unexpected error... */ | ||
483 | GNUNET_break(0); | ||
484 | *response_code = 0; | ||
485 | } | ||
488 | } | 486 | } |
489 | } | ||
490 | return json; | 487 | return json; |
491 | } | 488 | } |
492 | 489 | ||
@@ -499,9 +496,9 @@ GNUNET_CURL_download_get_result_ (struct GNUNET_CURL_DownloadBuffer *db, | |||
499 | * @return #GNUNET_OK if no errors occurred, #GNUNET_SYSERR otherwise. | 496 | * @return #GNUNET_OK if no errors occurred, #GNUNET_SYSERR otherwise. |
500 | */ | 497 | */ |
501 | int | 498 | int |
502 | GNUNET_CURL_append_header (struct GNUNET_CURL_Context *ctx, const char *header) | 499 | GNUNET_CURL_append_header(struct GNUNET_CURL_Context *ctx, const char *header) |
503 | { | 500 | { |
504 | ctx->common_headers = curl_slist_append (ctx->common_headers, header); | 501 | ctx->common_headers = curl_slist_append(ctx->common_headers, header); |
505 | if (NULL == ctx->common_headers) | 502 | if (NULL == ctx->common_headers) |
506 | return GNUNET_SYSERR; | 503 | return GNUNET_SYSERR; |
507 | 504 | ||
@@ -518,98 +515,98 @@ GNUNET_CURL_append_header (struct GNUNET_CURL_Context *ctx, const char *header) | |||
518 | * @param rc cleans/frees the response | 515 | * @param rc cleans/frees the response |
519 | */ | 516 | */ |
520 | void | 517 | void |
521 | GNUNET_CURL_perform2 (struct GNUNET_CURL_Context *ctx, | 518 | GNUNET_CURL_perform2(struct GNUNET_CURL_Context *ctx, |
522 | GNUNET_CURL_RawParser rp, | 519 | GNUNET_CURL_RawParser rp, |
523 | GNUNET_CURL_ResponseCleaner rc) | 520 | GNUNET_CURL_ResponseCleaner rc) |
524 | { | 521 | { |
525 | CURLMsg *cmsg; | 522 | CURLMsg *cmsg; |
526 | int n_running; | 523 | int n_running; |
527 | int n_completed; | 524 | int n_completed; |
528 | 525 | ||
529 | (void) curl_multi_perform (ctx->multi, &n_running); | 526 | (void)curl_multi_perform(ctx->multi, &n_running); |
530 | while (NULL != (cmsg = curl_multi_info_read (ctx->multi, &n_completed))) | 527 | while (NULL != (cmsg = curl_multi_info_read(ctx->multi, &n_completed))) |
531 | { | 528 | { |
532 | struct GNUNET_CURL_Job *job; | 529 | struct GNUNET_CURL_Job *job; |
533 | long response_code; | 530 | long response_code; |
534 | void *response; | 531 | void *response; |
535 | 532 | ||
536 | /* Only documented return value is CURLMSG_DONE */ | 533 | /* Only documented return value is CURLMSG_DONE */ |
537 | GNUNET_break (CURLMSG_DONE == cmsg->msg); | 534 | GNUNET_break(CURLMSG_DONE == cmsg->msg); |
538 | GNUNET_assert (CURLE_OK == curl_easy_getinfo (cmsg->easy_handle, | 535 | GNUNET_assert(CURLE_OK == curl_easy_getinfo(cmsg->easy_handle, |
539 | CURLINFO_PRIVATE, | 536 | CURLINFO_PRIVATE, |
540 | (char **) &job)); | 537 | (char **)&job)); |
541 | GNUNET_assert (job->ctx == ctx); | 538 | GNUNET_assert(job->ctx == ctx); |
542 | response_code = 0; | 539 | response_code = 0; |
543 | response = rp (&job->db, job->easy_handle, &response_code); | 540 | response = rp(&job->db, job->easy_handle, &response_code); |
544 | #if ENABLE_BENCHMARK | 541 | #if ENABLE_BENCHMARK |
545 | { | 542 | { |
546 | char *url = NULL; | 543 | char *url = NULL; |
547 | double total_as_double = 0; | 544 | double total_as_double = 0; |
548 | struct GNUNET_TIME_Relative total; | 545 | struct GNUNET_TIME_Relative total; |
549 | struct UrlRequestData *urd; | 546 | struct UrlRequestData *urd; |
550 | /* Some care required, as curl is using data types (long vs curl_off_t vs | 547 | /* Some care required, as curl is using data types (long vs curl_off_t vs |
551 | * double) inconsistently to store byte count. */ | 548 | * double) inconsistently to store byte count. */ |
552 | curl_off_t size_curl = 0; | 549 | curl_off_t size_curl = 0; |
553 | long size_long = 0; | 550 | long size_long = 0; |
554 | uint64_t bytes_sent = 0; | 551 | uint64_t bytes_sent = 0; |
555 | uint64_t bytes_received = 0; | 552 | uint64_t bytes_received = 0; |
556 | 553 | ||
557 | GNUNET_break (CURLE_OK == curl_easy_getinfo (cmsg->easy_handle, | 554 | GNUNET_break(CURLE_OK == curl_easy_getinfo(cmsg->easy_handle, |
558 | CURLINFO_TOTAL_TIME, | 555 | CURLINFO_TOTAL_TIME, |
559 | &total_as_double)); | 556 | &total_as_double)); |
560 | total.rel_value_us = total_as_double * 1000 * 1000; | 557 | total.rel_value_us = total_as_double * 1000 * 1000; |
561 | 558 | ||
562 | GNUNET_break (CURLE_OK == curl_easy_getinfo (cmsg->easy_handle, | 559 | GNUNET_break(CURLE_OK == curl_easy_getinfo(cmsg->easy_handle, |
563 | CURLINFO_EFFECTIVE_URL, | 560 | CURLINFO_EFFECTIVE_URL, |
564 | &url)); | 561 | &url)); |
565 | 562 | ||
566 | /* HEADER_SIZE + SIZE_DOWNLOAD_T is hopefully the total | 563 | /* HEADER_SIZE + SIZE_DOWNLOAD_T is hopefully the total |
567 | number of bytes received, not clear from curl docs. */ | 564 | number of bytes received, not clear from curl docs. */ |
568 | 565 | ||
569 | GNUNET_break (CURLE_OK == curl_easy_getinfo (cmsg->easy_handle, | 566 | GNUNET_break(CURLE_OK == curl_easy_getinfo(cmsg->easy_handle, |
570 | CURLINFO_HEADER_SIZE, | 567 | CURLINFO_HEADER_SIZE, |
571 | &size_long)); | 568 | &size_long)); |
572 | bytes_received += size_long; | 569 | bytes_received += size_long; |
573 | 570 | ||
574 | GNUNET_break (CURLE_OK == curl_easy_getinfo (cmsg->easy_handle, | 571 | GNUNET_break(CURLE_OK == curl_easy_getinfo(cmsg->easy_handle, |
575 | CURLINFO_SIZE_DOWNLOAD_T, | 572 | CURLINFO_SIZE_DOWNLOAD_T, |
576 | &size_curl)); | 573 | &size_curl)); |
577 | bytes_received += size_curl; | 574 | bytes_received += size_curl; |
578 | 575 | ||
579 | /* REQUEST_SIZE + SIZE_UPLOAD_T is hopefully the total number of bytes | 576 | /* REQUEST_SIZE + SIZE_UPLOAD_T is hopefully the total number of bytes |
580 | sent, again docs are not completely clear. */ | 577 | sent, again docs are not completely clear. */ |
581 | 578 | ||
582 | GNUNET_break (CURLE_OK == curl_easy_getinfo (cmsg->easy_handle, | 579 | GNUNET_break(CURLE_OK == curl_easy_getinfo(cmsg->easy_handle, |
583 | CURLINFO_REQUEST_SIZE, | 580 | CURLINFO_REQUEST_SIZE, |
584 | &size_long)); | 581 | &size_long)); |
585 | bytes_sent += size_long; | 582 | bytes_sent += size_long; |
586 | 583 | ||
587 | /* We obtain this value to check an invariant, but never use it otherwise. */ | 584 | /* We obtain this value to check an invariant, but never use it otherwise. */ |
588 | GNUNET_break (CURLE_OK == curl_easy_getinfo (cmsg->easy_handle, | 585 | GNUNET_break(CURLE_OK == curl_easy_getinfo(cmsg->easy_handle, |
589 | CURLINFO_SIZE_UPLOAD_T, | 586 | CURLINFO_SIZE_UPLOAD_T, |
590 | &size_curl)); | 587 | &size_curl)); |
591 | 588 | ||
592 | /* CURLINFO_SIZE_UPLOAD_T <= CURLINFO_REQUEST_SIZE should | 589 | /* CURLINFO_SIZE_UPLOAD_T <= CURLINFO_REQUEST_SIZE should |
593 | be an invariant. | 590 | be an invariant. |
594 | As verified with | 591 | As verified with |
595 | curl -w "foo%{size_request} -XPOST --data "ABC" $URL | 592 | curl -w "foo%{size_request} -XPOST --data "ABC" $URL |
596 | the CURLINFO_REQUEST_SIZE should be the whole size of the request | 593 | the CURLINFO_REQUEST_SIZE should be the whole size of the request |
597 | including headers and body. | 594 | including headers and body. |
598 | */ | 595 | */ |
599 | GNUNET_break (size_curl <= size_long); | 596 | GNUNET_break(size_curl <= size_long); |
600 | 597 | ||
601 | urd = get_url_benchmark_data (url, (unsigned int) response_code); | 598 | urd = get_url_benchmark_data(url, (unsigned int)response_code); |
602 | urd->count++; | 599 | urd->count++; |
603 | urd->time = GNUNET_TIME_relative_add (urd->time, total); | 600 | urd->time = GNUNET_TIME_relative_add(urd->time, total); |
604 | urd->time_max = GNUNET_TIME_relative_max (total, urd->time_max); | 601 | urd->time_max = GNUNET_TIME_relative_max(total, urd->time_max); |
605 | urd->bytes_sent += bytes_sent; | 602 | urd->bytes_sent += bytes_sent; |
606 | urd->bytes_received += bytes_received; | 603 | urd->bytes_received += bytes_received; |
607 | } | 604 | } |
608 | #endif | 605 | #endif |
609 | job->jcc (job->jcc_cls, response_code, response); | 606 | job->jcc(job->jcc_cls, response_code, response); |
610 | rc (response); | 607 | rc(response); |
611 | GNUNET_CURL_job_cancel (job); | 608 | GNUNET_CURL_job_cancel(job); |
612 | } | 609 | } |
613 | } | 610 | } |
614 | 611 | ||
615 | 612 | ||
@@ -619,11 +616,11 @@ GNUNET_CURL_perform2 (struct GNUNET_CURL_Context *ctx, | |||
619 | * @param ctx the library context | 616 | * @param ctx the library context |
620 | */ | 617 | */ |
621 | void | 618 | void |
622 | GNUNET_CURL_perform (struct GNUNET_CURL_Context *ctx) | 619 | GNUNET_CURL_perform(struct GNUNET_CURL_Context *ctx) |
623 | { | 620 | { |
624 | GNUNET_CURL_perform2 (ctx, | 621 | GNUNET_CURL_perform2(ctx, |
625 | &GNUNET_CURL_download_get_result_, | 622 | &GNUNET_CURL_download_get_result_, |
626 | (GNUNET_CURL_ResponseCleaner) &json_decref); | 623 | (GNUNET_CURL_ResponseCleaner) & json_decref); |
627 | } | 624 | } |
628 | 625 | ||
629 | 626 | ||
@@ -656,25 +653,25 @@ GNUNET_CURL_perform (struct GNUNET_CURL_Context *ctx) | |||
656 | * proceed immediately with #GNUNET_CURL_perform(). | 653 | * proceed immediately with #GNUNET_CURL_perform(). |
657 | */ | 654 | */ |
658 | void | 655 | void |
659 | GNUNET_CURL_get_select_info (struct GNUNET_CURL_Context *ctx, | 656 | GNUNET_CURL_get_select_info(struct GNUNET_CURL_Context *ctx, |
660 | fd_set *read_fd_set, | 657 | fd_set *read_fd_set, |
661 | fd_set *write_fd_set, | 658 | fd_set *write_fd_set, |
662 | fd_set *except_fd_set, | 659 | fd_set *except_fd_set, |
663 | int *max_fd, | 660 | int *max_fd, |
664 | long *timeout) | 661 | long *timeout) |
665 | { | 662 | { |
666 | long to; | 663 | long to; |
667 | int m; | 664 | int m; |
668 | 665 | ||
669 | m = -1; | 666 | m = -1; |
670 | GNUNET_assert (CURLM_OK == curl_multi_fdset (ctx->multi, | 667 | GNUNET_assert(CURLM_OK == curl_multi_fdset(ctx->multi, |
671 | read_fd_set, | 668 | read_fd_set, |
672 | write_fd_set, | 669 | write_fd_set, |
673 | except_fd_set, | 670 | except_fd_set, |
674 | &m)); | 671 | &m)); |
675 | to = *timeout; | 672 | to = *timeout; |
676 | *max_fd = GNUNET_MAX (m, *max_fd); | 673 | *max_fd = GNUNET_MAX(m, *max_fd); |
677 | GNUNET_assert (CURLM_OK == curl_multi_timeout (ctx->multi, &to)); | 674 | GNUNET_assert(CURLM_OK == curl_multi_timeout(ctx->multi, &to)); |
678 | 675 | ||
679 | /* Only if what we got back from curl is smaller than what we | 676 | /* Only if what we got back from curl is smaller than what we |
680 | already had (-1 == infinity!), then update timeout */ | 677 | already had (-1 == infinity!), then update timeout */ |
@@ -693,14 +690,14 @@ GNUNET_CURL_get_select_info (struct GNUNET_CURL_Context *ctx, | |||
693 | * @param ctx the library context | 690 | * @param ctx the library context |
694 | */ | 691 | */ |
695 | void | 692 | void |
696 | GNUNET_CURL_fini (struct GNUNET_CURL_Context *ctx) | 693 | GNUNET_CURL_fini(struct GNUNET_CURL_Context *ctx) |
697 | { | 694 | { |
698 | /* all jobs must have been cancelled at this time, assert this */ | 695 | /* all jobs must have been cancelled at this time, assert this */ |
699 | GNUNET_assert (NULL == ctx->jobs_head); | 696 | GNUNET_assert(NULL == ctx->jobs_head); |
700 | curl_share_cleanup (ctx->share); | 697 | curl_share_cleanup(ctx->share); |
701 | curl_multi_cleanup (ctx->multi); | 698 | curl_multi_cleanup(ctx->multi); |
702 | curl_slist_free_all (ctx->common_headers); | 699 | curl_slist_free_all(ctx->common_headers); |
703 | GNUNET_free (ctx); | 700 | GNUNET_free(ctx); |
704 | } | 701 | } |
705 | 702 | ||
706 | 703 | ||
@@ -708,15 +705,15 @@ GNUNET_CURL_fini (struct GNUNET_CURL_Context *ctx) | |||
708 | * Initial global setup logic, specifically runs the Curl setup. | 705 | * Initial global setup logic, specifically runs the Curl setup. |
709 | */ | 706 | */ |
710 | __attribute__ ((constructor)) void | 707 | __attribute__ ((constructor)) void |
711 | GNUNET_CURL_constructor__ (void) | 708 | GNUNET_CURL_constructor__(void) |
712 | { | 709 | { |
713 | CURLcode ret; | 710 | CURLcode ret; |
714 | 711 | ||
715 | if (CURLE_OK != (ret = curl_global_init (CURL_GLOBAL_DEFAULT))) | 712 | if (CURLE_OK != (ret = curl_global_init(CURL_GLOBAL_DEFAULT))) |
716 | { | 713 | { |
717 | CURL_STRERROR (GNUNET_ERROR_TYPE_ERROR, "curl_global_init", ret); | 714 | CURL_STRERROR(GNUNET_ERROR_TYPE_ERROR, "curl_global_init", ret); |
718 | curl_fail = 1; | 715 | curl_fail = 1; |
719 | } | 716 | } |
720 | } | 717 | } |
721 | 718 | ||
722 | 719 | ||
@@ -724,11 +721,11 @@ GNUNET_CURL_constructor__ (void) | |||
724 | * Cleans up after us, specifically runs the Curl cleanup. | 721 | * Cleans up after us, specifically runs the Curl cleanup. |
725 | */ | 722 | */ |
726 | __attribute__ ((destructor)) void | 723 | __attribute__ ((destructor)) void |
727 | GNUNET_CURL_destructor__ (void) | 724 | GNUNET_CURL_destructor__(void) |
728 | { | 725 | { |
729 | if (curl_fail) | 726 | if (curl_fail) |
730 | return; | 727 | return; |
731 | curl_global_cleanup (); | 728 | curl_global_cleanup(); |
732 | } | 729 | } |
733 | 730 | ||
734 | /* end of curl.c */ | 731 | /* end of curl.c */ |