diff options
author | Christian Grothoff <christian@grothoff.org> | 2019-11-15 09:39:31 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2019-11-15 09:39:31 +0100 |
commit | 9badf80eb4228a9c009839a4856710127efe8601 (patch) | |
tree | ec62e28f2ab3b90ca374537a9b2730b1fecdbb93 /src/sync | |
parent | d0e22221b9fd3627d63e484b8957337d2638a871 (diff) | |
download | sync-9badf80eb4228a9c009839a4856710127efe8601.tar.gz sync-9badf80eb4228a9c009839a4856710127efe8601.tar.bz2 sync-9badf80eb4228a9c009839a4856710127efe8601.zip |
implement GET logic
Diffstat (limited to 'src/sync')
-rw-r--r-- | src/sync/sync-httpd.c | 27 | ||||
-rw-r--r-- | src/sync/sync-httpd_backup.c | 170 | ||||
-rw-r--r-- | src/sync/sync-httpd_backup.h | 10 |
3 files changed, 185 insertions, 22 deletions
diff --git a/src/sync/sync-httpd.c b/src/sync/sync-httpd.c index d7f6eb5..98a2b24 100644 --- a/src/sync/sync-httpd.c +++ b/src/sync/sync-httpd.c @@ -175,7 +175,10 @@ url_handler (void *cls, struct TM_HandlerContext *hc; struct GNUNET_AsyncScopeId aid; const char *correlation_id = NULL; + struct SYNC_AccountPublicKeyP account_pub; + (void) cls; + (void) version; hc = *con_cls; if (NULL == hc) @@ -197,7 +200,6 @@ url_handler (void *cls, { aid = hc->async_scope_id; } - GNUNET_SCHEDULER_begin_async_scope (&aid); if (NULL != correlation_id) @@ -211,22 +213,25 @@ url_handler (void *cls, "Handling request (%s) for URL '%s'\n", method, url); - if (0 == strncmp (url, - "/backup/", - strlen ("/backup/"))) + + if (GNUNET_OK == + GNUNET_CRYPTO_eddsa_public_key_from_string (url, + strlen (url), + &account_pub.eddsa_pub)) { - // return handle_policy (...); - if (0 == strcmp (method, MHD_HTTP_METHOD_GET)) + if (0 == strcasecmp (method, + MHD_HTTP_METHOD_GET)) { return sync_handler_backup_get (connection, - url, + &account_pub, con_cls); } - if (0 == strcmp (method, MHD_HTTP_METHOD_POST)) + if (0 == strcasecmp (method, + MHD_HTTP_METHOD_POST)) { return sync_handler_backup_post (connection, con_cls, - url, + &account_pub, upload_data, upload_data_size); } @@ -238,8 +243,8 @@ url_handler (void *cls, if ( (0 == strcmp (url, rh->url)) && ( (NULL == rh->method) || - (0 == strcmp (method, - rh->method)) ) ) + (0 == strcasecmp (method, + rh->method)) ) ) { int ret; diff --git a/src/sync/sync-httpd_backup.c b/src/sync/sync-httpd_backup.c index 86ba955..61d9151 100644 --- a/src/sync/sync-httpd_backup.c +++ b/src/sync/sync-httpd_backup.c @@ -21,26 +21,182 @@ #include "platform.h" #include "sync-httpd.h" #include <gnunet/gnunet_util_lib.h> +#include "sync-httpd_backup.h" +#include "sync-httpd_responses.h" /** * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[in,out] upload_data_size number of bytes (left) in @a upload_data + * @param account public key of the account the request is for + * @param[in,out] con_cls the connection's closure (can be updated) * @return MHD result code */ int sync_handler_backup_get (struct MHD_Connection *connection, - const char *url, + const struct SYNC_AccountPublicKeyP *account, void **con_cls) { - return MHD_NO; + struct SYNC_AccountSignatureP account_sig; + struct GNUNET_HashCode backup_hash; + struct GNUNET_HashCode prev_hash; + size_t backup_size; + void *backup; + enum SYNC_DB_QueryStatus qs; + struct MHD_Response *resp; + const char *inm; + struct GNUNET_HashCode inm_h; + int ret; + + inm = MHD_lookup_connection_value (connection, + MHD_HEADER_KIND, + MHD_HTTP_HEADER_IF_NONE_MATCH); + qs = db->lookup_account_TR (db->cls, + account, + &backup_hash); + switch (qs) + { + case SYNC_DB_OLD_BACKUP_MISSMATCH: + GNUNET_break (0); + return SH_RESPONSE_reply_internal_error (connection, + TALER_EC_INTERNAL_INVARIANT_FAILURE, + "unexpected return status (backup missmatch)"); + case SYNC_DB_PAYMENT_REQUIRED: + return SH_RESPONSE_reply_not_found (connection, + TALER_EC_SYNC_ACCOUNT_UNKNOWN, + "account"); + case SYNC_DB_HARD_ERROR: + GNUNET_break (0); + return SH_RESPONSE_reply_internal_error (connection, + TALER_EC_SYNC_DB_FETCH_ERROR, + "hard database failure"); + case SYNC_DB_SOFT_ERROR: + GNUNET_break (0); + return SH_RESPONSE_reply_internal_error (connection, + TALER_EC_SYNC_DB_FETCH_ERROR, + "soft database failure"); + case SYNC_DB_NO_RESULTS: + resp = MHD_create_response_from_buffer (0, + NULL, + MHD_RESPMEM_PERSISTENT); + ret = MHD_queue_response (connection, + MHD_HTTP_NO_CONTENT, + resp); + MHD_destroy_response (resp); + return ret; + case SYNC_DB_ONE_RESULT: + if (NULL != inm) + { + if (GNUNET_OK != + GNUNET_STRINGS_string_to_data (inm, + strlen (inm), + &inm_h, + sizeof (inm_h))) + { + GNUNET_break_op (0); + return SH_RESPONSE_reply_bad_request (connection, + TALER_EC_SYNC_BAD_ETAG, + "Etag is not a base32-encoded SHA-512 hash"); + } + if (0 == GNUNET_memcmp (&inm_h, + &backup_hash)) + { + resp = MHD_create_response_from_buffer (0, + NULL, + MHD_RESPMEM_PERSISTENT); + ret = MHD_queue_response (connection, + MHD_HTTP_NOT_MODIFIED, + resp); + MHD_destroy_response (resp); + return ret; + } + } + /* We have a result, should fetch and return it! */ + break; + } + + qs = db->lookup_backup_TR (db->cls, + account, + &account_sig, + &prev_hash, + &backup_hash, + &backup_size, + &backup); + switch (qs) + { + case SYNC_DB_OLD_BACKUP_MISSMATCH: + GNUNET_break (0); + return SH_RESPONSE_reply_internal_error (connection, + TALER_EC_INTERNAL_INVARIANT_FAILURE, + "unexpected return status (backup missmatch)"); + case SYNC_DB_PAYMENT_REQUIRED: + GNUNET_break (0); + return SH_RESPONSE_reply_internal_error (connection, + TALER_EC_INTERNAL_INVARIANT_FAILURE, + "unexpected return status (payment required)"); + case SYNC_DB_HARD_ERROR: + GNUNET_break (0); + return SH_RESPONSE_reply_internal_error (connection, + TALER_EC_SYNC_DB_FETCH_ERROR, + "hard database failure"); + case SYNC_DB_SOFT_ERROR: + GNUNET_break (0); + return SH_RESPONSE_reply_internal_error (connection, + TALER_EC_SYNC_DB_FETCH_ERROR, + "soft database failure"); + case SYNC_DB_NO_RESULTS: + GNUNET_break (0); + /* Note: can theoretically happen due to non-transactional nature if + the backup expired / was gc'ed JUST between the two SQL calls. + But too rare to handle properly, as doing a transaction would be + expensive. Just admit to failure ;-) */ + return SH_RESPONSE_reply_internal_error (connection, + TALER_EC_SYNC_DB_FETCH_ERROR, + "unexpected empty result set (try again?)"); + case SYNC_DB_ONE_RESULT: + /* interesting case below */ + break; + } + resp = MHD_create_response_from_buffer (backup_size, + backup, + MHD_RESPMEM_MUST_FREE); + { + char *sig_s; + char *prev_s; + char *etag; + + sig_s = GNUNET_STRINGS_data_to_string_alloc (&account_sig, + sizeof (account_sig)); + prev_s = GNUNET_STRINGS_data_to_string_alloc (&prev_hash, + sizeof (prev_hash)); + etag = GNUNET_STRINGS_data_to_string_alloc (&backup_hash, + sizeof (backup_hash)); + GNUNET_break (MHD_YES == + MHD_add_response_header (resp, + "X-Sync-Signature", + sig_s)); + GNUNET_break (MHD_YES == + MHD_add_response_header (resp, + "X-Sync-Previous", + prev_s)); + GNUNET_break (MHD_YES == + MHD_add_response_header (resp, + MHD_HTTP_HEADER_ETAG, + etag)); + GNUNET_free (etag); + GNUNET_free (prev_s); + GNUNET_free (sig_s); + } + ret = MHD_queue_response (connection, + MHD_HTTP_NOT_MODIFIED, + resp); + MHD_destroy_response (resp); + return ret; } /** * @param connection the MHD connection to handle * @param[in,out] connection_cls the connection's closure (can be updated) + * @param account public key of the account the request is for * @param upload_data upload data * @param[in,out] upload_data_size number of bytes (left) in @a upload_data * @return MHD result code @@ -48,9 +204,11 @@ sync_handler_backup_get (struct MHD_Connection *connection, int sync_handler_backup_post (struct MHD_Connection *connection, void **con_cls, - const char *url, + const struct SYNC_AccountPublicKeyP *account, const char *upload_data, size_t *upload_data_size) { + struct SYNC_AccountSignatureP account_sig; + return MHD_NO; } diff --git a/src/sync/sync-httpd_backup.h b/src/sync/sync-httpd_backup.h index 1ba7408..02f31be 100644 --- a/src/sync/sync-httpd_backup.h +++ b/src/sync/sync-httpd_backup.h @@ -24,20 +24,20 @@ /** * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[in,out] upload_data_size number of bytes (left) in @a upload_data + * @param account public key of the account the request is for + * @param[in,out] con_cls the connection's closure (can be updated) * @return MHD result code */ int sync_handler_backup_get (struct MHD_Connection *connection, - const char *url, + const struct SYNC_AccountPublicKeyP *account, void **con_cls); /** * @param connection the MHD connection to handle * @param[in,out] connection_cls the connection's closure (can be updated) + * @param account public key of the account the request is for * @param upload_data upload data * @param[in,out] upload_data_size number of bytes (left) in @a upload_data * @return MHD result code @@ -45,7 +45,7 @@ sync_handler_backup_get (struct MHD_Connection *connection, int sync_handler_backup_post (struct MHD_Connection *connection, void **con_cls, - const char *url, + const struct SYNC_AccountPublicKeyP *account, const char *upload_data, size_t *upload_data_size); |