From 8468a39c0aeb8e569c7084a42d73580bbd48dec1 Mon Sep 17 00:00:00 2001 From: josch Date: Sat, 6 Dec 2014 11:04:04 +0100 Subject: [PATCH] if apicall failed - retry --- fuse/main.c | 2 +- fuse/operations.c | 1 + mfapi/apicalls.c | 1 - mfapi/apicalls.h | 2 +- mfapi/apicalls/device_get_changes.c | 44 +++++++++--- mfapi/apicalls/device_get_patch.c | 43 +++++++---- mfapi/apicalls/device_get_status.c | 39 +++++++--- mfapi/apicalls/device_get_updates.c | 71 ++++++++++++------ mfapi/apicalls/file_delete.c | 36 +++++++--- mfapi/apicalls/file_get_info.c | 35 ++++++--- mfapi/apicalls/file_get_links.c | 35 ++++++--- mfapi/apicalls/folder_create.c | 56 ++++++++++----- mfapi/apicalls/folder_delete.c | 38 +++++++--- mfapi/apicalls/folder_get_content.c | 95 +++++++++++++++++-------- mfapi/apicalls/folder_get_info.c | 49 +++++++++---- mfapi/apicalls/upload_poll_upload.c | 39 +++++++--- mfapi/apicalls/upload_simple.c | 65 +++++++++++------ mfapi/apicalls/user_get_session_token.c | 75 ++++++++++++------- mfapi/mfconn.c | 57 +++++++++++++-- mfapi/mfconn.h | 7 +- 20 files changed, 579 insertions(+), 211 deletions(-) diff --git a/fuse/main.c b/fuse/main.c index e1fb44c..8674f9c 100644 --- a/fuse/main.c +++ b/fuse/main.c @@ -280,7 +280,7 @@ static void connect_mf(struct mediafirefs_user_options *options, ctx->conn = mfconn_create(options->server, options->username, options->password, options->app_id, - options->api_key); + options->api_key, 3); if (ctx->conn == NULL) { fprintf(stderr, "Cannot establish connection\n"); diff --git a/fuse/operations.c b/fuse/operations.c index a433ee7..fe78627 100644 --- a/fuse/operations.c +++ b/fuse/operations.c @@ -426,6 +426,7 @@ int mediafirefs_release(const char *path, struct fuse_file_info *file_info) folder_key = folder_tree_path_get_key(ctx->tree, ctx->conn, dir_name); + upload_key = NULL; retval = mfconn_api_upload_simple(ctx->conn, folder_key, fh, file_name, &upload_key); diff --git a/mfapi/apicalls.c b/mfapi/apicalls.c index 1196988..1b3735d 100644 --- a/mfapi/apicalls.c +++ b/mfapi/apicalls.c @@ -19,7 +19,6 @@ #include #include #include -#include #include "../utils/http.h" diff --git a/mfapi/apicalls.h b/mfapi/apicalls.h index 8aa7bf9..1b5734e 100644 --- a/mfapi/apicalls.h +++ b/mfapi/apicalls.h @@ -61,7 +61,7 @@ int mfconn_api_file_get_links(mfconn * conn, mffile * file, int mfconn_api_folder_create(mfconn * conn, const char *parent, const char *name); -long mfconn_api_folder_get_content(mfconn * conn, int mode, +long mfconn_api_folder_get_content(mfconn * conn, const int mode, const char *folderkey, mffolder *** folder_result, mffile *** file_result); diff --git a/mfapi/apicalls/device_get_changes.c b/mfapi/apicalls/device_get_changes.c index 06784f6..f59918d 100644 --- a/mfapi/apicalls/device_get_changes.c +++ b/mfapi/apicalls/device_get_changes.c @@ -43,22 +43,46 @@ int mfconn_api_device_get_changes(mfconn * conn, uint64_t revision, const char *api_call; int retval; mfhttp *http; + int i; if (conn == NULL) return -1; - api_call = mfconn_create_signed_get(conn, 0, "device/get_changes.php", - "?revision=%" PRIu64 - "&response_format=json", revision); + for (i = 0; i < mfconn_get_max_num_retries(conn); i++) { + if (*changes != NULL) { + free(*changes); + *changes = NULL; + } - http = http_create(); - retval = - http_get_buf(http, api_call, _decode_device_get_changes, - (void *)changes); - http_destroy(http); - mfconn_update_secret_key(conn); + api_call = mfconn_create_signed_get(conn, 0, "device/get_changes.php", + "?revision=%" PRIu64 + "&response_format=json", revision); - free((void *)api_call); + http = http_create(); + retval = + http_get_buf(http, api_call, _decode_device_get_changes, + (void *)changes); + http_destroy(http); + mfconn_update_secret_key(conn); + + free((void *)api_call); + + if (retval != 127 && retval != 28) + break; + + // if there was either a curl timeout or a token error, get a new + // token and try again + // + // on a curl timeout we get a new token because it is likely that we + // lost signature synchronization (we don't know whether the server + // accepted or rejected the last call) + fprintf(stderr, "got error %d - negotiate a new token\n", retval); + retval = mfconn_refresh_token(conn); + if (retval != 0) { + fprintf(stderr, "failed to get a new token\n"); + break; + } + } return retval; } diff --git a/mfapi/apicalls/device_get_patch.c b/mfapi/apicalls/device_get_patch.c index ffe4e95..681fdf6 100644 --- a/mfapi/apicalls/device_get_patch.c +++ b/mfapi/apicalls/device_get_patch.c @@ -38,6 +38,7 @@ int mfconn_api_device_get_patch(mfconn * conn, mfpatch * patch, int len; mfhttp *http; int retval; + int i; if (conn == NULL) return -1; @@ -53,20 +54,38 @@ int mfconn_api_device_get_patch(mfconn * conn, mfpatch * patch, if (len != 15) return -1; - api_call = mfconn_create_signed_get(conn, 0, "device/get_patch.php", - "?quick_key=%s" - "&source_revision=%" PRIu64 - "&target_revision=%" PRIu64 - "&response_format=json", quickkey, - source_revision, target_revision); + for (i = 0; i < mfconn_get_max_num_retries(conn); i++) { + api_call = mfconn_create_signed_get(conn, 0, "device/get_patch.php", + "?quick_key=%s" + "&source_revision=%" PRIu64 + "&target_revision=%" PRIu64 + "&response_format=json", quickkey, + source_revision, target_revision); - http = http_create(); - retval = http_get_buf(http, api_call, _decode_device_get_patch, - (void *)patch); - http_destroy(http); - mfconn_update_secret_key(conn); + http = http_create(); + retval = http_get_buf(http, api_call, _decode_device_get_patch, + (void *)patch); + http_destroy(http); + mfconn_update_secret_key(conn); - free((void *)api_call); + free((void *)api_call); + + if (retval != 127 && retval != 28) + break; + + // if there was either a curl timeout or a token error, get a new + // token and try again + // + // on a curl timeout we get a new token because it is likely that we + // lost signature synchronization (we don't know whether the server + // accepted or rejected the last call) + fprintf(stderr, "got error %d - negotiate a new token\n", retval); + retval = mfconn_refresh_token(conn); + if (retval != 0) { + fprintf(stderr, "failed to get a new token\n"); + break; + } + } return retval; } diff --git a/mfapi/apicalls/device_get_status.c b/mfapi/apicalls/device_get_status.c index 0719cb5..931e6a6 100644 --- a/mfapi/apicalls/device_get_status.c +++ b/mfapi/apicalls/device_get_status.c @@ -33,23 +33,40 @@ int mfconn_api_device_get_status(mfconn * conn, uint64_t * revision) const char *api_call; int retval; mfhttp *http; - - // char *rx_buffer; + int i; if (conn == NULL) return -1; - api_call = mfconn_create_signed_get(conn, 0, "device/get_status.php", - "?response_format=json"); + for (i = 0; i < mfconn_get_max_num_retries(conn); i++) { + api_call = mfconn_create_signed_get(conn, 0, "device/get_status.php", + "?response_format=json"); - http = http_create(); - retval = - http_get_buf(http, api_call, _decode_device_get_status, - (void *)revision); - http_destroy(http); - mfconn_update_secret_key(conn); + http = http_create(); + retval = + http_get_buf(http, api_call, _decode_device_get_status, + (void *)revision); + http_destroy(http); + mfconn_update_secret_key(conn); - free((void *)api_call); + free((void *)api_call); + + if (retval != 127 && retval != 28) + break; + + // if there was either a curl timeout or a token error, get a new + // token and try again + // + // on a curl timeout we get a new token because it is likely that we + // lost signature synchronization (we don't know whether the server + // accepted or rejected the last call) + fprintf(stderr, "got error %d - negotiate a new token\n", retval); + retval = mfconn_refresh_token(conn); + if (retval != 0) { + fprintf(stderr, "failed to get a new token\n"); + break; + } + } return retval; } diff --git a/mfapi/apicalls/device_get_updates.c b/mfapi/apicalls/device_get_updates.c index fbb9998..664cadf 100644 --- a/mfapi/apicalls/device_get_updates.c +++ b/mfapi/apicalls/device_get_updates.c @@ -39,6 +39,8 @@ int mfconn_api_device_get_updates(mfconn * conn, const char *quickkey, int len; mfhttp *http; int retval; + int i, + j; if (conn == NULL) return -1; @@ -54,27 +56,56 @@ int mfconn_api_device_get_updates(mfconn * conn, const char *quickkey, if (len != 15) return -1; - if (target_revision == 0) { - api_call = mfconn_create_signed_get(conn, 0, "device/get_updates.php", - "?quick_key=%s" - "&revision=%" PRIu64 - "&response_format=json", quickkey, - revision); - } else { - api_call = mfconn_create_signed_get(conn, 0, "device/get_updates.php", - "?quick_key=%s" - "&revision=%" PRIu64 - "&target_revision=%" PRIu64 - "&response_format=json", quickkey, - revision, target_revision); - } - http = http_create(); - retval = http_get_buf(http, api_call, _decode_device_get_updates, - (void *)patches); - http_destroy(http); - mfconn_update_secret_key(conn); + for (i = 0; i < mfconn_get_max_num_retries(conn); i++) { + if (*patches != NULL) { + for (j = 0; (*patches)[j] != NULL; j++) { + patch_free((*patches)[j]); + } + free(*patches); + *patches = NULL; + } - free((void *)api_call); + if (target_revision == 0) { + api_call = mfconn_create_signed_get(conn, 0, + "device/get_updates.php", + "?quick_key=%s" + "&revision=%" PRIu64 + "&response_format=json", + quickkey, revision); + } else { + api_call = mfconn_create_signed_get(conn, 0, + "device/get_updates.php", + "?quick_key=%s" + "&revision=%" PRIu64 + "&target_revision=%" PRIu64 + "&response_format=json", + quickkey, revision, + target_revision); + } + http = http_create(); + retval = http_get_buf(http, api_call, _decode_device_get_updates, + (void *)patches); + http_destroy(http); + mfconn_update_secret_key(conn); + + free((void *)api_call); + + if (retval != 127 && retval != 28) + break; + + // if there was either a curl timeout or a token error, get a new + // token and try again + // + // on a curl timeout we get a new token because it is likely that we + // lost signature synchronization (we don't know whether the server + // accepted or rejected the last call) + fprintf(stderr, "got error %d - negotiate a new token\n", retval); + retval = mfconn_refresh_token(conn); + if (retval != 0) { + fprintf(stderr, "failed to get a new token\n"); + break; + } + } return retval; } diff --git a/mfapi/apicalls/file_delete.c b/mfapi/apicalls/file_delete.c index d3aa607..f413c19 100644 --- a/mfapi/apicalls/file_delete.c +++ b/mfapi/apicalls/file_delete.c @@ -30,6 +30,7 @@ int mfconn_api_file_delete(mfconn * conn, const char *quickkey) const char *api_call; int retval; mfhttp *http; + int i; if (conn == NULL) return -1; @@ -40,16 +41,35 @@ int mfconn_api_file_delete(mfconn * conn, const char *quickkey) if (strlen(quickkey) != 15) return -1; - api_call = mfconn_create_signed_get(conn, 0, "file/delete.php", - "?quick_key=%s&response_format=json", - quickkey); + for (i = 0; i < mfconn_get_max_num_retries(conn); i++) { + api_call = mfconn_create_signed_get(conn, 0, "file/delete.php", + "?quick_key=%s" + "&response_format=json", quickkey); - http = http_create(); - retval = http_get_buf(http, api_call, mfapi_decode_common, "file/delete"); - http_destroy(http); - mfconn_update_secret_key(conn); + http = http_create(); + retval = + http_get_buf(http, api_call, mfapi_decode_common, "file/delete"); + http_destroy(http); + mfconn_update_secret_key(conn); - free((void *)api_call); + free((void *)api_call); + + if (retval != 127 && retval != 28) + break; + + // if there was either a curl timeout or a token error, get a new + // token and try again + // + // on a curl timeout we get a new token because it is likely that we + // lost signature synchronization (we don't know whether the server + // accepted or rejected the last call) + fprintf(stderr, "got error %d - negotiate a new token\n", retval); + retval = mfconn_refresh_token(conn); + if (retval != 0) { + fprintf(stderr, "failed to get a new token\n"); + break; + } + } return retval; } diff --git a/mfapi/apicalls/file_get_info.c b/mfapi/apicalls/file_get_info.c index 264edee..03868fe 100644 --- a/mfapi/apicalls/file_get_info.c +++ b/mfapi/apicalls/file_get_info.c @@ -38,6 +38,7 @@ int mfconn_api_file_get_info(mfconn * conn, mffile * file, int retval; int len; mfhttp *http; + int i; if (conn == NULL) return -1; @@ -53,16 +54,34 @@ int mfconn_api_file_get_info(mfconn * conn, mffile * file, if (len != 11 && len != 15) return -1; - api_call = mfconn_create_signed_get(conn, 0, "file/get_info.php", - "?quick_key=%s&response_format=json", - quickkey); + for (i = 0; i < mfconn_get_max_num_retries(conn); i++) { + api_call = mfconn_create_signed_get(conn, 0, "file/get_info.php", + "?quick_key=%s" + "&response_format=json", quickkey); - http = http_create(); - retval = http_get_buf(http, api_call, _decode_file_get_info, file); - http_destroy(http); - mfconn_update_secret_key(conn); + http = http_create(); + retval = http_get_buf(http, api_call, _decode_file_get_info, file); + http_destroy(http); + mfconn_update_secret_key(conn); - free((void *)api_call); + free((void *)api_call); + + if (retval != 127 && retval != 28) + break; + + // if there was either a curl timeout or a token error, get a new + // token and try again + // + // on a curl timeout we get a new token because it is likely that we + // lost signature synchronization (we don't know whether the server + // accepted or rejected the last call) + fprintf(stderr, "got error %d - negotiate a new token\n", retval); + retval = mfconn_refresh_token(conn); + if (retval != 0) { + fprintf(stderr, "failed to get a new token\n"); + break; + } + } return retval; } diff --git a/mfapi/apicalls/file_get_links.c b/mfapi/apicalls/file_get_links.c index 79e58d1..1f03851 100644 --- a/mfapi/apicalls/file_get_links.c +++ b/mfapi/apicalls/file_get_links.c @@ -36,6 +36,7 @@ int mfconn_api_file_get_links(mfconn * conn, mffile * file, int retval; int len; mfhttp *http; + int i; if (conn == NULL) return -1; @@ -51,16 +52,34 @@ int mfconn_api_file_get_links(mfconn * conn, mffile * file, if (len != 11 && len != 15) return -1; - api_call = mfconn_create_signed_get(conn, 0, "file/get_links.php", - "?quick_key=%s&response_format=json", - quickkey); + for (i = 0; i < mfconn_get_max_num_retries(conn); i++) { + api_call = mfconn_create_signed_get(conn, 0, "file/get_links.php", + "?quick_key=%s" + "&response_format=json", quickkey); - http = http_create(); - retval = http_get_buf(http, api_call, _decode_file_get_links, file); - http_destroy(http); - mfconn_update_secret_key(conn); + http = http_create(); + retval = http_get_buf(http, api_call, _decode_file_get_links, file); + http_destroy(http); + mfconn_update_secret_key(conn); - free((void *)api_call); + free((void *)api_call); + + if (retval != 127 && retval != 28) + break; + + // if there was either a curl timeout or a token error, get a new + // token and try again + // + // on a curl timeout we get a new token because it is likely that we + // lost signature synchronization (we don't know whether the server + // accepted or rejected the last call) + fprintf(stderr, "got error %d - negotiate a new token\n", retval); + retval = mfconn_refresh_token(conn); + if (retval != 0) { + fprintf(stderr, "failed to get a new token\n"); + break; + } + } return retval; } diff --git a/mfapi/apicalls/folder_create.c b/mfapi/apicalls/folder_create.c index 5674840..48ccf0d 100644 --- a/mfapi/apicalls/folder_create.c +++ b/mfapi/apicalls/folder_create.c @@ -31,6 +31,7 @@ int mfconn_api_folder_create(mfconn * conn, const char *parent, const char *api_call; int retval; mfhttp *http; + int i; if (conn == NULL) return -1; @@ -45,25 +46,44 @@ int mfconn_api_folder_create(mfconn * conn, const char *parent, return -1; } - if (parent != NULL) { - api_call = - mfconn_create_signed_get(conn, 0, "folder/create.php", - "?parent_key=%s&foldername=%s" - "&response_format=json", parent, name); - } else { - api_call = - mfconn_create_signed_get(conn, 0, "folder/create.php", - "?foldername=%s&response_format=json", - name); + for (i = 0; i < mfconn_get_max_num_retries(conn); i++) { + if (parent != NULL) { + api_call = + mfconn_create_signed_get(conn, 0, "folder/create.php", + "?parent_key=%s&foldername=%s" + "&response_format=json", parent, + name); + } else { + api_call = + mfconn_create_signed_get(conn, 0, "folder/create.php", + "?foldername=%s&response_format=json", + name); + } + + http = http_create(); + retval = http_get_buf(http, api_call, mfapi_decode_common, + "folder/create"); + http_destroy(http); + mfconn_update_secret_key(conn); + + free((void *)api_call); + + if (retval != 127 && retval != 28) + break; + + // if there was either a curl timeout or a token error, get a new + // token and try again + // + // on a curl timeout we get a new token because it is likely that we + // lost signature synchronization (we don't know whether the server + // accepted or rejected the last call) + fprintf(stderr, "got error %d - negotiate a new token\n", retval); + retval = mfconn_refresh_token(conn); + if (retval != 0) { + fprintf(stderr, "failed to get a new token\n"); + break; + } } - http = http_create(); - retval = http_get_buf(http, api_call, mfapi_decode_common, - "folder/create"); - http_destroy(http); - mfconn_update_secret_key(conn); - - free((void *)api_call); - return retval; } diff --git a/mfapi/apicalls/folder_delete.c b/mfapi/apicalls/folder_delete.c index 2210f4a..f5b63d5 100644 --- a/mfapi/apicalls/folder_delete.c +++ b/mfapi/apicalls/folder_delete.c @@ -30,6 +30,7 @@ int mfconn_api_folder_delete(mfconn * conn, const char *folderkey) const char *api_call; int retval; mfhttp *http; + int i; if (conn == NULL) return -1; @@ -40,17 +41,36 @@ int mfconn_api_folder_delete(mfconn * conn, const char *folderkey) if (strlen(folderkey) != 13) return -1; - api_call = mfconn_create_signed_get(conn, 0, "folder/delete.php", - "?folder_key=%s&response_format=json", - folderkey); + for (i = 0; i < mfconn_get_max_num_retries(conn); i++) { + api_call = mfconn_create_signed_get(conn, 0, "folder/delete.php", + "?folder_key=%s" + "&response_format=json", + folderkey); - http = http_create(); - retval = http_get_buf(http, api_call, mfapi_decode_common, - "folder/delete"); - http_destroy(http); - mfconn_update_secret_key(conn); + http = http_create(); + retval = http_get_buf(http, api_call, mfapi_decode_common, + "folder/delete"); + http_destroy(http); + mfconn_update_secret_key(conn); - free((void *)api_call); + free((void *)api_call); + + if (retval != 127 && retval != 28) + break; + + // if there was either a curl timeout or a token error, get a new + // token and try again + // + // on a curl timeout we get a new token because it is likely that we + // lost signature synchronization (we don't know whether the server + // accepted or rejected the last call) + fprintf(stderr, "got error %d - negotiate a new token\n", retval); + retval = mfconn_refresh_token(conn); + if (retval != 0) { + fprintf(stderr, "failed to get a new token\n"); + break; + } + } return retval; } diff --git a/mfapi/apicalls/folder_get_content.c b/mfapi/apicalls/folder_get_content.c index 4fb4a6b..de007be 100644 --- a/mfapi/apicalls/folder_get_content.c +++ b/mfapi/apicalls/folder_get_content.c @@ -46,7 +46,8 @@ static int _decode_folder_get_content_files(mfhttp * conn, void *data); * pointers to them. */ long -mfconn_api_folder_get_content(mfconn * conn, int mode, const char *folderkey, +mfconn_api_folder_get_content(mfconn * conn, const int mode, + const char *folderkey, mffolder *** mffolder_result, mffile *** mffile_result) { @@ -54,6 +55,8 @@ mfconn_api_folder_get_content(mfconn * conn, int mode, const char *folderkey, int retval; char *content_type; mfhttp *http; + int i, + j; if (conn == NULL) return -1; @@ -63,35 +66,71 @@ mfconn_api_folder_get_content(mfconn * conn, int mode, const char *folderkey, else content_type = "files"; - if (folderkey == NULL) { - api_call = mfconn_create_signed_get(conn, 0, "folder/get_content.php", - "?content_type=%s" - "&response_format=json", - content_type); - } else { - api_call = mfconn_create_signed_get(conn, 0, "folder/get_content.php", - "?folder_key=%s" - "&content_type=%s" - "&response_format=json", - folderkey, content_type); + for (i = 0; i < mfconn_get_max_num_retries(conn); i++) { + if (mode == 0) { + if (*mffolder_result != NULL) { + for (j = 0; (*mffolder_result)[j] != NULL; j++) { + folder_free((*mffolder_result)[j]); + } + free(*mffolder_result); + *mffolder_result = NULL; + } + } else { + if (*mffile_result != NULL) { + for (j = 0; (*mffile_result)[j] != NULL; j++) { + file_free((*mffile_result)[j]); + } + free(*mffile_result); + *mffile_result = NULL; + } + } + + if (folderkey == NULL) { + api_call = mfconn_create_signed_get(conn, 0, + "folder/get_content.php", + "?content_type=%s" + "&response_format=json", + content_type); + } else { + api_call = mfconn_create_signed_get(conn, 0, + "folder/get_content.php", + "?folder_key=%s" + "&content_type=%s" + "&response_format=json", + folderkey, content_type); + } + + http = http_create(); + if (mode == 0) + retval = http_get_buf(http, api_call, + _decode_folder_get_content_folders, + (void *)mffolder_result); + else + retval = http_get_buf(http, api_call, + _decode_folder_get_content_files, + (void *)mffile_result); + http_destroy(http); + mfconn_update_secret_key(conn); + + free((void *)api_call); + + if (retval != 127 && retval != 28) + break; + + // if there was either a curl timeout or a token error, get a new + // token and try again + // + // on a curl timeout we get a new token because it is likely that we + // lost signature synchronization (we don't know whether the server + // accepted or rejected the last call) + fprintf(stderr, "got error %d - negotiate a new token\n", retval); + retval = mfconn_refresh_token(conn); + if (retval != 0) { + fprintf(stderr, "failed to get a new token\n"); + break; + } } - http = http_create(); - if (mode == 0) - retval = - http_get_buf(http, api_call, - _decode_folder_get_content_folders, - (void *)mffolder_result); - else - retval = - http_get_buf(http, api_call, - _decode_folder_get_content_files, - (void *)mffile_result); - http_destroy(http); - mfconn_update_secret_key(conn); - - free((void *)api_call); - return retval; } diff --git a/mfapi/apicalls/folder_get_info.c b/mfapi/apicalls/folder_get_info.c index a12c600..c674015 100644 --- a/mfapi/apicalls/folder_get_info.c +++ b/mfapi/apicalls/folder_get_info.c @@ -38,6 +38,7 @@ mfconn_api_folder_get_info(mfconn * conn, mffolder * folder, const char *api_call; int retval; mfhttp *http; + int i; if (conn == NULL) return -1; @@ -50,23 +51,41 @@ mfconn_api_folder_get_info(mfconn * conn, mffolder * folder, return -1; } - if (folderkey == NULL) { - api_call = mfconn_create_signed_get(conn, 0, "folder/get_info.php", - "?response_format=json"); - } else { - api_call = mfconn_create_signed_get(conn, 0, "folder/get_info.php", - "?folder_key=%s" - "&response_format=json", - folderkey); + for (i = 0; i < mfconn_get_max_num_retries(conn); i++) { + if (folderkey == NULL) { + api_call = mfconn_create_signed_get(conn, 0, "folder/get_info.php", + "?response_format=json"); + } else { + api_call = mfconn_create_signed_get(conn, 0, "folder/get_info.php", + "?folder_key=%s" + "&response_format=json", + folderkey); + } + + http = http_create(); + retval = http_get_buf(http, api_call, _decode_folder_get_info, folder); + http_destroy(http); + mfconn_update_secret_key(conn); + + free((void *)api_call); + + if (retval != 127 && retval != 28) + break; + + // if there was either a curl timeout or a token error, get a new + // token and try again + // + // on a curl timeout we get a new token because it is likely that we + // lost signature synchronization (we don't know whether the server + // accepted or rejected the last call) + fprintf(stderr, "got error %d - negotiate a new token\n", retval); + retval = mfconn_refresh_token(conn); + if (retval != 0) { + fprintf(stderr, "failed to get a new token\n"); + break; + } } - http = http_create(); - retval = http_get_buf(http, api_call, _decode_folder_get_info, folder); - http_destroy(http); - mfconn_update_secret_key(conn); - - free((void *)api_call); - return retval; } diff --git a/mfapi/apicalls/upload_poll_upload.c b/mfapi/apicalls/upload_poll_upload.c index 7c5454f..bc0d1c4 100644 --- a/mfapi/apicalls/upload_poll_upload.c +++ b/mfapi/apicalls/upload_poll_upload.c @@ -42,6 +42,7 @@ mfconn_api_upload_poll_upload(mfconn * conn, const char *upload_key, int retval; mfhttp *http; struct upload_poll_upload_response response; + int i; if (conn == NULL) return -1; @@ -49,18 +50,36 @@ mfconn_api_upload_poll_upload(mfconn * conn, const char *upload_key, if (upload_key == NULL) return -1; - // make an UNSIGNED get - api_call = mfconn_create_unsigned_get(conn, 0, - "upload/poll_upload.php", - "?response_format=json" - "&key=%s", upload_key); + for (i = 0; i < mfconn_get_max_num_retries(conn); i++) { + // make an UNSIGNED get + api_call = mfconn_create_unsigned_get(conn, 0, + "upload/poll_upload.php", + "?response_format=json" + "&key=%s", upload_key); - http = http_create(); - retval = http_get_buf(http, api_call, _decode_upload_poll_upload, - &response); - http_destroy(http); + http = http_create(); + retval = http_get_buf(http, api_call, _decode_upload_poll_upload, + &response); + http_destroy(http); - free((void *)api_call); + free((void *)api_call); + + if (retval != 127 && retval != 28) + break; + + // if there was either a curl timeout or a token error, get a new + // token and try again + // + // on a curl timeout we get a new token because it is likely that we + // lost signature synchronization (we don't know whether the server + // accepted or rejected the last call) + fprintf(stderr, "got error %d - negotiate a new token\n", retval); + retval = mfconn_refresh_token(conn); + if (retval != 0) { + fprintf(stderr, "failed to get a new token\n"); + break; + } + } *status = response.status; *fileerror = response.fileerror; diff --git a/mfapi/apicalls/upload_simple.c b/mfapi/apicalls/upload_simple.c index fcf7169..7da69cf 100644 --- a/mfapi/apicalls/upload_simple.c +++ b/mfapi/apicalls/upload_simple.c @@ -44,6 +44,7 @@ mfconn_api_upload_simple(mfconn * conn, const char *folderkey, unsigned char hash[SHA256_DIGEST_LENGTH]; char *file_hash; uint64_t file_size; + int i; if (conn == NULL) return -1; @@ -64,29 +65,53 @@ mfconn_api_upload_simple(mfconn * conn, const char *folderkey, file_hash = binary2hex(hash, SHA256_DIGEST_LENGTH); - if (folderkey == NULL) { - api_call = mfconn_create_signed_get(conn, 0, - "upload/simple.php", - "?response_format=json"); - } else { - api_call = mfconn_create_signed_get(conn, 0, - "upload/simple.php", - "?response_format=json" - "&folder_key=%s", folderkey); + for (i = 0; i < mfconn_get_max_num_retries(conn); i++) { + if (*upload_key != NULL) { + free(*upload_key); + *upload_key = NULL; + } + + if (folderkey == NULL) { + api_call = mfconn_create_signed_get(conn, 0, + "upload/simple.php", + "?response_format=json"); + } else { + api_call = mfconn_create_signed_get(conn, 0, + "upload/simple.php", + "?response_format=json" + "&folder_key=%s", folderkey); + } + + // make sure that we are at the beginning of the file + rewind(fh); + + http = http_create(); + retval = http_post_file(http, api_call, fh, file_name, + file_size, file_hash, + _decode_upload_simple, upload_key); + http_destroy(http); + mfconn_update_secret_key(conn); + + free((void *)api_call); + + if (retval != 127 && retval != 28) + break; + + // if there was either a curl timeout or a token error, get a new + // token and try again + // + // on a curl timeout we get a new token because it is likely that we + // lost signature synchronization (we don't know whether the server + // accepted or rejected the last call) + fprintf(stderr, "got error %d - negotiate a new token\n", retval); + retval = mfconn_refresh_token(conn); + if (retval != 0) { + fprintf(stderr, "failed to get a new token\n"); + break; + } } - // make sure that we are at the beginning of the file - rewind(fh); - - http = http_create(); - retval = http_post_file(http, api_call, fh, file_name, - file_size, file_hash, - _decode_upload_simple, upload_key); - http_destroy(http); - mfconn_update_secret_key(conn); - free(file_hash); - free((void *)api_call); return retval; } diff --git a/mfapi/apicalls/user_get_session_token.c b/mfapi/apicalls/user_get_session_token.c index 6fcf248..0326457 100644 --- a/mfapi/apicalls/user_get_session_token.c +++ b/mfapi/apicalls/user_get_session_token.c @@ -51,38 +51,65 @@ mfconn_api_user_get_session_token(mfconn * conn, const char *server, int retval; struct user_get_session_token_response response; mfhttp *http; + int i; if (conn == NULL) return -1; - // configure url for operation - login_url = strdup_printf("https://%s/api/user/get_session_token.php", - server); + for (i = 0; i < mfconn_get_max_num_retries(conn); i++) { + if (*secret_time != NULL) { + free(*secret_time); + *secret_time = NULL; + } + if (*session_token != NULL) { + free(*session_token); + *session_token = NULL; + } + // configure url for operation + login_url = strdup_printf("https://%s/api/user/get_session_token.php", + server); - // create user signature - user_signature = - mfconn_create_user_signature(conn, username, password, app_id, - app_key); + // create user signature + user_signature = + mfconn_create_user_signature(conn, username, password, app_id, + app_key); - // FIXME: username and password have to be urlencoded (maybe using - // curl_easy_escape) - post_args = strdup_printf("email=%s" - "&password=%s" - "&application_id=%d" - "&signature=%s" - "&token_version=2" - "&response_format=json", - username, password, app_id, user_signature); - free((void *)user_signature); + // FIXME: username and password have to be urlencoded (maybe using + // curl_easy_escape) + post_args = strdup_printf("email=%s" + "&password=%s" + "&application_id=%d" + "&signature=%s" + "&token_version=2" + "&response_format=json", + username, password, app_id, user_signature); + free((void *)user_signature); - http = http_create(); - retval = - http_post_buf(http, login_url, post_args, - _decode_get_session_token, (void *)(&response)); - http_destroy(http); + http = http_create(); + retval = + http_post_buf(http, login_url, post_args, + _decode_get_session_token, (void *)(&response)); + http_destroy(http); - free(login_url); - free(post_args); + free(login_url); + free(post_args); + + if (retval != 127 && retval != 28) + break; + + // if there was either a curl timeout or a token error, get a new + // token and try again + // + // on a curl timeout we get a new token because it is likely that we + // lost signature synchronization (we don't know whether the server + // accepted or rejected the last call) + fprintf(stderr, "got error %d - negotiate a new token\n", retval); + retval = mfconn_refresh_token(conn); + if (retval != 0) { + fprintf(stderr, "failed to get a new token\n"); + break; + } + } *secret_key = response.secret_key; *secret_time = response.secret_time; diff --git a/mfapi/mfconn.c b/mfapi/mfconn.c index b388ac2..b81818b 100644 --- a/mfapi/mfconn.c +++ b/mfapi/mfconn.c @@ -35,11 +35,16 @@ struct mfconn { uint32_t secret_key; char *secret_time; char *session_token; + char *username; + char *password; + int app_id; + char *app_key; + int max_num_retries; }; mfconn *mfconn_create(const char *server, const char *username, const char *password, int app_id, - const char *app_key) + const char *app_key, int max_num_retries) { mfconn *conn; int retval; @@ -59,24 +64,59 @@ mfconn *mfconn_create(const char *server, const char *username, conn = (mfconn *) calloc(1, sizeof(mfconn)); conn->server = strdup(server); + conn->username = strdup(username); + conn->password = strdup(password); + conn->app_id = app_id; + if (app_key != NULL) + conn->app_key = strdup(app_key); + else + conn->app_key = NULL; + conn->max_num_retries = max_num_retries; + conn->secret_time = NULL; + conn->session_token = NULL; retval = mfconn_api_user_get_session_token(conn, conn->server, - username, password, app_id, - app_key, + conn->username, conn->password, + conn->app_id, conn->app_key, &(conn->secret_key), &(conn->secret_time), &(conn->session_token)); - if (retval == 0) - return conn; - else { + if (retval != 0) { fprintf(stderr, "error: mfconn_api_user_get_session_token\n"); return NULL; } + + return conn; +} + +int mfconn_refresh_token(mfconn * conn) +{ + int retval; + + free(conn->secret_time); + conn->secret_time = NULL; + free(conn->session_token); + conn->session_token = NULL; + retval = mfconn_api_user_get_session_token(conn, conn->server, + conn->username, conn->password, + conn->app_id, conn->app_key, + &(conn->secret_key), + &(conn->secret_time), + &(conn->session_token)); + if (retval != 0) { + fprintf(stderr, "user/get_session_token failed\n"); + return -1; + } + return 0; } void mfconn_destroy(mfconn * conn) { free(conn->server); + free(conn->username); + free(conn->password); + if (conn->app_key != NULL) + free(conn->app_key); free(conn->secret_time); free(conn->session_token); free(conn); @@ -334,3 +374,8 @@ uint32_t mfconn_get_secret_key(mfconn * conn) { return conn->secret_key; } + +int mfconn_get_max_num_retries(mfconn * conn) +{ + return conn->max_num_retries; +} diff --git a/mfapi/mfconn.h b/mfapi/mfconn.h index 1b43163..93788f1 100644 --- a/mfapi/mfconn.h +++ b/mfapi/mfconn.h @@ -28,7 +28,9 @@ typedef struct mfconn mfconn; mfconn *mfconn_create(const char *server, const char *username, const char *password, int app_id, - const char *app_key); + const char *app_key, int max_num_retries); + +int mfconn_refresh_token(mfconn * conn); void mfconn_destroy(mfconn * conn); @@ -54,4 +56,7 @@ const char *mfconn_get_session_token(mfconn * conn); const char *mfconn_get_secret_time(mfconn * conn); uint32_t mfconn_get_secret_key(mfconn * conn); + +int mfconn_get_max_num_retries(mfconn * conn); + #endif