Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cloud sync: clean up directory/filename mapping, log errors #15561

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 34 additions & 2 deletions network/cloud_sync/webdav.c
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,16 @@ static char *webdav_get_auth_header(const char *method, const char *url)
return webdav_st->digest_auth_header;
}

static void webdav_log_http_failure(const char *path, http_transfer_data_t *data)
{
int i;
RARCH_WARN("webdav failed: %s: HTTP %d\n", path, data->status);
for (i = 0; data->headers && i < data->headers->size; i++)
RARCH_WARN("%s\n", data->headers->elems[i].data);
if (data->data)
RARCH_WARN("%s\n", data->data);
}

static void webdav_stat_cb(retro_task_t *task, void *task_data, void *user_data, const char *err)
{
webdav_state_t *webdav_st = webdav_state_get_ptr();
Expand All @@ -465,9 +475,14 @@ static void webdav_stat_cb(retro_task_t *task, void *task_data, void *user_data,
webdav_stat_cb, webdav_cb_st);
return;
}
else
RARCH_WARN("failure creating WWW-Authenticate: Digest header\n");
}
}

if (!success && data)
webdav_log_http_failure(webdav_st->url, data);

webdav_cb_st->cb(webdav_cb_st->user_data, NULL, success, NULL);
free(webdav_cb_st);
}
Expand All @@ -477,14 +492,17 @@ static bool webdav_sync_begin(cloud_sync_complete_handler_t cb, void *user_data)
settings_t *settings = config_get_ptr();
const char *url = settings->arrays.webdav_url;
webdav_state_t *webdav_st = webdav_state_get_ptr();
size_t len = 0;
const char *auth_header;

if (string_is_empty(url))
return false;

// TODO: LOCK?

strlcpy(webdav_st->url, url, sizeof(webdav_st->url));
if (!strstr(url, "://"))
len += strlcpy(webdav_st->url, "http://", STRLEN_CONST("http://"));
strlcpy(webdav_st->url + len, url, sizeof(webdav_st->url) - len);
fill_pathname_slash(webdav_st->url, sizeof(webdav_st->url));

/* url/username/password may have changed, redo auth check */
Expand Down Expand Up @@ -529,8 +547,11 @@ static void webdav_read_cb(retro_task_t *task, void *task_data, void *user_data,
success = (data &&
((data->status >= 200 && data->status < 300) || data->status == 404));

if (!success && data)
webdav_log_http_failure(webdav_cb_st->path, data);

// TODO: it's possible we get a 401 here and need to redo the auth check with this request
if (data && data->data && webdav_cb_st)
if (success && data->data && webdav_cb_st)
{
// TODO: it would be better if writing to the file happened during the network reads
file = filestream_open(webdav_cb_st->file,
Expand Down Expand Up @@ -582,6 +603,8 @@ static void webdav_mkdir_cb(retro_task_t *task, void *task_data, void *user_data
// TODO: it's possible we get a 401 here and need to redo the auth check with this request
if (!data || data->status < 200 || data->status >= 400)
{
if (data)
webdav_log_http_failure(webdav_mkdir_st->url, data);
webdav_mkdir_st->cb(false, webdav_mkdir_st->cb_st);
free(webdav_mkdir_st);
return;
Expand Down Expand Up @@ -627,6 +650,9 @@ static void webdav_update_cb(retro_task_t *task, void *task_data, void *user_dat
http_transfer_data_t *data = (http_transfer_data_t*)task_data;
bool success = (data && data->status >= 200 && data->status < 300);

if (!success && data)
webdav_log_http_failure(webdav_cb_st->path, data);

// TODO: it's possible we get a 401 here and need to redo the auth check with this request
if (webdav_cb_st)
{
Expand Down Expand Up @@ -697,6 +723,9 @@ static void webdav_delete_cb(retro_task_t *task, void *task_data, void *user_dat
http_transfer_data_t *data = (http_transfer_data_t*)task_data;
bool success = (data != NULL && data->status >= 200 && data->status < 300);

if (!success && data)
webdav_log_http_failure(webdav_cb_st->path, data);

// TODO: it's possible we get a 401 here and need to redo the auth check with this request
if (webdav_cb_st)
{
Expand All @@ -711,6 +740,9 @@ static void webdav_backup_cb(retro_task_t *task, void *task_data, void *user_dat
http_transfer_data_t *data = (http_transfer_data_t*)task_data;
bool success = (data != NULL && data->status >= 200 && data->status < 300);

if (!success && data)
webdav_log_http_failure(webdav_cb_st->path, data);

// TODO: it's possible we get a 401 here and need to redo the auth check with this request
if (webdav_cb_st)
{
Expand Down
85 changes: 51 additions & 34 deletions tasks/task_cloudsync.c
Original file line number Diff line number Diff line change
Expand Up @@ -274,9 +274,33 @@ static void task_cloud_sync_manifest_append_dir(file_list_t *manifest,
}
}

static struct string_list *task_cloud_sync_directory_map(void)
{
static struct string_list *list = NULL;
if (!list)
{
union string_list_elem_attr attr = {0};
char dir[PATH_MAX_LENGTH];
list = string_list_new();

string_list_append(list, "config", attr);
fill_pathname_application_special(dir,
sizeof(dir), APPLICATION_SPECIAL_DIRECTORY_CONFIG);
list->elems[list->size - 1].userdata = strdup(dir);

string_list_append(list, "saves", attr);
list->elems[list->size - 1].userdata = strdup(dir_get_ptr(RARCH_DIR_SAVEFILE));

string_list_append(list, "states", attr);
list->elems[list->size - 1].userdata = strdup(dir_get_ptr(RARCH_DIR_SAVESTATE));
}
return list;
}

static void task_cloud_sync_build_current_manifest(task_cloud_sync_state_t *sync_state)
{
char config_dir[PATH_MAX_LENGTH];
struct string_list *dirlist = task_cloud_sync_directory_map();
int i;

sync_state->current_manifest = (file_list_t *)calloc(1, sizeof(file_list_t));
if (!sync_state->current_manifest)
Expand All @@ -297,13 +321,9 @@ static void task_cloud_sync_build_current_manifest(task_cloud_sync_state_t *sync
return;
}

fill_pathname_application_special(config_dir,
sizeof(config_dir),
APPLICATION_SPECIAL_DIRECTORY_CONFIG);

task_cloud_sync_manifest_append_dir(sync_state->current_manifest, config_dir, "config");
task_cloud_sync_manifest_append_dir(sync_state->current_manifest, dir_get_ptr(RARCH_DIR_SAVEFILE), "saves");
task_cloud_sync_manifest_append_dir(sync_state->current_manifest, dir_get_ptr(RARCH_DIR_SAVESTATE), "states");
for (i = 0; i < dirlist->size; i++)
task_cloud_sync_manifest_append_dir(sync_state->current_manifest,
dirlist->elems[i].userdata, dirlist->elems[i].data);

file_list_sort_on_alt(sync_state->current_manifest);
sync_state->phase = CLOUD_SYNC_PHASE_DIFF;
Expand Down Expand Up @@ -431,19 +451,11 @@ static void task_cloud_sync_fetch_cb(void *user_data, const char *path, bool suc
hash = task_cloud_sync_md5_rfile(file);
filestream_close(file);
RARCH_LOG(CSPFX "successfully fetched %s\n", path);
task_cloud_sync_add_to_updated_manifest(sync_state, path, hash, true);
task_cloud_sync_add_to_updated_manifest(sync_state, path, hash, false);
/* no need to mark need_manifest_uploaded, nothing changed */
}
else
{
/* on failure, don't add it to local manifest, that will cause a fetch again next time */
size_t idx;
if (file_list_search(sync_state->server_manifest, path, &idx))
{
struct item_file *server_file = &sync_state->server_manifest->list[idx];
task_cloud_sync_add_to_updated_manifest(sync_state, path, CS_FILE_HASH(server_file), true);
}
if (!success)
RARCH_WARN(CSPFX "failed to fetch %s\n", path);
else
Expand All @@ -455,27 +467,34 @@ static void task_cloud_sync_fetch_cb(void *user_data, const char *path, bool suc

static void task_cloud_sync_fetch_server_file(task_cloud_sync_state_t *sync_state)
{
char filename[PATH_MAX_LENGTH];
struct item_file *server_file = &sync_state->server_manifest->list[sync_state->server_idx];
const char *key = CS_FILE_KEY(server_file);
const char *path = strchr(key, PATH_DEFAULT_SLASH_C()) + 1;
char directory[PATH_MAX_LENGTH];
settings_t *settings = config_get_ptr();
struct string_list *dirlist = task_cloud_sync_directory_map();
struct item_file *server_file = &sync_state->server_manifest->list[sync_state->server_idx];
const char *key = CS_FILE_KEY(server_file);
const char *path = strchr(key, PATH_DEFAULT_SLASH_C()) + 1;
char directory[PATH_MAX_LENGTH];
char filename[PATH_MAX_LENGTH];
settings_t *settings = config_get_ptr();
int i;

RARCH_LOG(CSPFX "fetching %s\n", key);
/* we're just fetching a file the server has, we can update this now */
task_cloud_sync_add_to_updated_manifest(sync_state, key, CS_FILE_HASH(server_file), true);
/* no need to mark need_manifest_uploaded, nothing changed */

if (string_starts_with(key, "config"))
filename[0] = '\0';
for (i = 0; i < dirlist->size; i++)
{
char config_dir[PATH_MAX_LENGTH];
fill_pathname_application_special(config_dir,
sizeof(config_dir),
APPLICATION_SPECIAL_DIRECTORY_CONFIG);
fill_pathname_join_special(filename, config_dir, path, sizeof(filename));
if (!string_starts_with(key, dirlist->elems[i].data))
continue;
fill_pathname_join_special(filename, dirlist->elems[i].userdata, path, sizeof(filename));
break;
}
if (string_is_empty(filename))
{
/* how did this end up here? we don't know where to put it... */
RARCH_WARN(CSPFX "don't know where to put %s!\n", key);
return;
}
else if (string_starts_with(key, "saves"))
fill_pathname_join_special(filename, dir_get_ptr(RARCH_DIR_SAVEFILE), path, sizeof(filename));
else if (string_starts_with(key, "states"))
fill_pathname_join_special(filename, dir_get_ptr(RARCH_DIR_SAVESTATE), path, sizeof(filename));

if (!settings->bools.cloud_sync_destructive && path_is_valid(filename))
{
Expand All @@ -492,8 +511,6 @@ static void task_cloud_sync_fetch_server_file(task_cloud_sync_state_t *sync_stat
{
RARCH_WARN(CSPFX "wanted to fetch %s but failed\n", key);
sync_state->failures = true;
task_cloud_sync_add_to_updated_manifest(sync_state, key, CS_FILE_HASH(server_file), true);
/* no need to mark need_manifest_uploaded, nothing changed */
}
}

Expand Down
Loading