From df7d7dddb27cb9527d4de66de8954451ab1dfa2b Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 25 Nov 2019 01:45:34 +0100 Subject: finish upload API --- src/lib/Makefile.am | 4 +- src/lib/sync_api_curl_defaults.c | 50 +++++++++++++++ src/lib/sync_api_curl_defaults.h | 39 ++++++++++++ src/lib/sync_api_upload.c | 132 +++++++++++++++++++++++++++++++++++++-- 4 files changed, 219 insertions(+), 6 deletions(-) create mode 100644 src/lib/sync_api_curl_defaults.c create mode 100644 src/lib/sync_api_curl_defaults.h (limited to 'src/lib') diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index 20ceab4..ed0a61e 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -12,15 +12,15 @@ lib_LTLIBRARIES = \ libsync_la_LDFLAGS = \ -version-info 0:0:0 \ -no-undefined - libsync_la_SOURCES = \ sync_api_curl_defaults.c sync_api_curl_defaults.h \ sync_api_download.c \ sync_api_upload.c - libsync_la_LIBADD = \ -lgnunetcurl \ -lgnunetjson \ + -ltalerjson \ + -ltalerutil \ -lgnunetutil \ -ljansson \ $(XLIB) diff --git a/src/lib/sync_api_curl_defaults.c b/src/lib/sync_api_curl_defaults.c new file mode 100644 index 0000000..5a114ed --- /dev/null +++ b/src/lib/sync_api_curl_defaults.c @@ -0,0 +1,50 @@ +/* + This file is part of TALER + Copyright (C) 2014-2019 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + +*/ +/** + * @file lib/sync_api_curl_defaults.c + * @brief curl easy handle defaults + * @author Florian Dold + */ + +#include "sync_api_curl_defaults.h" + +/** + * Get a curl handle with the right defaults + * for the sync lib. + * + * @param url URL to query + */ +CURL * +SYNC_curl_easy_get_ (const char *url) +{ + CURL *eh; + + eh = curl_easy_init (); + GNUNET_assert (CURLE_OK == + curl_easy_setopt (eh, + CURLOPT_URL, + url)); + GNUNET_assert (CURLE_OK == + curl_easy_setopt (eh, + CURLOPT_FOLLOWLOCATION, + 1L)); + GNUNET_assert (CURLE_OK == + curl_easy_setopt (eh, + CURLOPT_TCP_FASTOPEN, + 1L)); + return eh; +} diff --git a/src/lib/sync_api_curl_defaults.h b/src/lib/sync_api_curl_defaults.h new file mode 100644 index 0000000..afc6e47 --- /dev/null +++ b/src/lib/sync_api_curl_defaults.h @@ -0,0 +1,39 @@ +/* + This file is part of TALER + Copyright (C) 2014-2019 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see + +*/ +/** + * @file lib/sync_api_curl_defaults.h + * @brief curl easy handle defaults + * @author Florian Dold + */ + +#ifndef _SYNC_CURL_DEFAULTS_H +#define _SYNC_CURL_DEFAULTS_H + +#include "platform.h" +#include + + +/** + * Get a curl handle with the right defaults + * for the exchange lib. In the future, we might manage a pool of connections here. + * + * @param url URL to query + */ +CURL * +SYNC_curl_easy_get_ (const char *url); + +#endif /* _TALER_CURL_DEFAULTS_H */ diff --git a/src/lib/sync_api_upload.c b/src/lib/sync_api_upload.c index 47bc3f5..f3e3cf3 100644 --- a/src/lib/sync_api_upload.c +++ b/src/lib/sync_api_upload.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "sync_service.h" #include "sync_api_curl_defaults.h" @@ -64,6 +65,15 @@ struct SYNC_UploadOperation */ void *cb_cls; + /** + * Payment URI we received from the service, or NULL. + */ + char *pay_uri; + + /** + * Hash of the data we are uploading. + */ + struct GNUNET_HashCode new_upload_hash; }; @@ -83,29 +93,133 @@ handle_upload_finished (void *cls, { struct SYNC_UploadOperation *uo = cls; enum TALER_ErrorCode ec = TALER_EC_INVALID; + struct SYNC_UploadDetails ud; + struct SYNC_UploadDetails *udp; uo->job = NULL; + udp = NULL; + memset (&ud, 0, sizeof (ud)); switch (response_code) { case 0: break; - case MHD_HTTP_OK: + case MHD_HTTP_NO_CONTENT: + ud.us = SYNC_US_SUCCESS; + ud.details.curr_backup_hash = &uo->new_upload_hash; + udp = &ud; + ec = TALER_EC_NONE; + break; + case MHD_HTTP_NOT_MODIFIED: + ud.us = SYNC_US_SUCCESS; + ud.details.curr_backup_hash = &uo->new_upload_hash; + udp = &ud; + ec = TALER_EC_NONE; + break; + case MHD_HTTP_BAD_REQUEST: + GNUNET_break (0); + ec = TALER_JSON_get_error_code2 (data, + data_size); + break; + case MHD_HTTP_PAYMENT_REQUIRED: + ud.us = SYNC_US_PAYMENT_REQUIRED; + ud.details.payment_request = uo->pay_uri; + udp = &ud; + ec = TALER_EC_NONE; + break; + case MHD_HTTP_FORBIDDEN: + GNUNET_break (0); + ec = TALER_JSON_get_error_code2 (data, + data_size); + break; + case MHD_HTTP_CONFLICT: + ud.us = SYNC_US_CONFLICTING_BACKUP; + GNUNET_CRYPTO_hash (data, + data_size, + &ud.details.recovered_backup.existing_backup_hash); + ud.details.recovered_backup.existing_backup_size + = data_size; + ud.details.recovered_backup.existing_backup + = data; + udp = &ud; + ec = TALER_EC_NONE; + break; + case MHD_HTTP_GONE: + ec = TALER_JSON_get_error_code2 (data, + data_size); + break; + case MHD_HTTP_LENGTH_REQUIRED: + GNUNET_break (0); + break; + case MHD_HTTP_REQUEST_ENTITY_TOO_LARGE: + ec = TALER_JSON_get_error_code2 (data, + data_size); + break; + case MHD_HTTP_TOO_MANY_REQUESTS: + ec = TALER_JSON_get_error_code2 (data, + data_size); break; - // FIXME: handle all cases... } - if (NULL != uo->cb) { uo->cb (uo->cb_cls, ec, response_code, - NULL); + udp); uo->cb = NULL; } SYNC_upload_cancel (uo); } +/** + * Handle HTTP header received by curl. + * + * @param buffer one line of HTTP header data + * @param size size of an item + * @param nitems number of items passed + * @param userdata our `struct SYNC_DownloadOperation *` + * @return `size * nitems` + */ +static size_t +handle_header (char *buffer, + size_t size, + size_t nitems, + void *userdata) +{ + struct SYNC_UploadOperation *uo = userdata; + size_t total = size * nitems; + char *ndup; + const char *hdr_type; + char *hdr_val; + + ndup = GNUNET_strndup (buffer, + total); + hdr_type = strtok (ndup, + ":"); + if (NULL == hdr_type) + { + GNUNET_free (ndup); + return total; + } + hdr_val = strtok (NULL, + ""); + if (NULL == hdr_val) + { + GNUNET_free (ndup); + return total; + } + if (' ' == *hdr_val) + hdr_val++; + if (0 == strcasecmp (hdr_type, + "Taler")) + { + /* found payment URI we care about! */ + uo->pay_uri = GNUNET_strdup (hdr_val); + } + GNUNET_free (ndup); + return total; +} + /** * Upload a @a backup to a Sync server. Note that @a backup must @@ -239,6 +353,7 @@ SYNC_upload (struct GNUNET_CURL_Context *ctx, /* Finished setting up headers */ uo = GNUNET_new (struct SYNC_UploadOperation); + uo->new_upload_hash = usp.new_backup_hash; { char *path; char *account_s; @@ -283,6 +398,14 @@ SYNC_upload (struct GNUNET_CURL_Context *ctx, curl_easy_setopt (eh, CURLOPT_POSTFIELDSIZE, (long) backup_size)); + GNUNET_assert (CURLE_OK == + curl_easy_setopt (eh, + CURLOPT_HEADERFUNCTION, + &handle_header)); + GNUNET_assert (CURLE_OK == + curl_easy_setopt (eh, + CURLOPT_HEADERDATA, + uo)); uo->job = GNUNET_CURL_job_add_raw (ctx, eh, job_headers, @@ -308,6 +431,7 @@ SYNC_upload_cancel (struct SYNC_UploadOperation *uo) GNUNET_CURL_job_cancel (uo->job); uo->job = NULL; } + GNUNET_free (uo->pay_uri); GNUNET_free (uo->url); GNUNET_free (uo); } -- cgit v1.2.3