summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2019-11-25 01:45:34 +0100
committerChristian Grothoff <christian@grothoff.org>2019-11-25 01:45:34 +0100
commitdf7d7dddb27cb9527d4de66de8954451ab1dfa2b (patch)
treebda17eb98581294bc9a03bf2ce29e727b7db630b
parent40c71cb44bdb6f097a2d45fb57406c50b87be849 (diff)
downloadsync-df7d7dddb27cb9527d4de66de8954451ab1dfa2b.tar.gz
sync-df7d7dddb27cb9527d4de66de8954451ab1dfa2b.tar.bz2
sync-df7d7dddb27cb9527d4de66de8954451ab1dfa2b.zip
finish upload API
-rw-r--r--src/include/sync_service.h2
-rw-r--r--src/lib/Makefile.am4
-rw-r--r--src/lib/sync_api_curl_defaults.c50
-rw-r--r--src/lib/sync_api_curl_defaults.h39
-rw-r--r--src/lib/sync_api_upload.c132
-rw-r--r--src/sync/sync-httpd_backup_post.c2
6 files changed, 221 insertions, 8 deletions
diff --git a/src/include/sync_service.h b/src/include/sync_service.h
index bb67481..08c2dcc 100644
--- a/src/include/sync_service.h
+++ b/src/include/sync_service.h
@@ -161,7 +161,7 @@ struct SYNC_UploadDetails
/**
* Hash over @e existing_backup.
*/
- const struct GNUNET_HashCode *existing_backup_hash;
+ struct GNUNET_HashCode existing_backup_hash;
/**
* Number of bytes in @e existing_backup.
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
+ <http://www.gnu.org/licenses/>
+*/
+/**
+ * @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
+ <http://www.gnu.org/licenses/>
+*/
+/**
+ * @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 <gnunet/gnunet_curl_lib.h>
+
+
+/**
+ * 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 <gnunet/gnunet_util_lib.h>
#include <gnunet/gnunet_curl_lib.h>
#include <taler/taler_signatures.h>
+#include <taler/taler_json_lib.h>
#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);
}
diff --git a/src/sync/sync-httpd_backup_post.c b/src/sync/sync-httpd_backup_post.c
index 8b8ea35..ed6e35d 100644
--- a/src/sync/sync-httpd_backup_post.c
+++ b/src/sync/sync-httpd_backup_post.c
@@ -667,7 +667,7 @@ sync_handler_backup_post (struct MHD_Connection *connection,
{
GNUNET_break_op (0);
return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_UNAUTHORIZED,
+ MHD_HTTP_FORBIDDEN,
TALER_EC_SYNC_INVALID_SIGNATURE,
"Account signature does not match upload");
}