[client] Use http-sync exclusively for repos version > 0.

For repo version > 0, if requests to '/seafhttp/*' urls fail,
and https is not used, fall back to send requests to 8082 port directly.
This commit is contained in:
Jiaqiang Xu 2015-04-18 14:04:17 +08:00
parent 9d6482c034
commit 7a97fc055d
6 changed files with 311 additions and 124 deletions

View File

@ -278,8 +278,7 @@ check_head_commit_done (HttpHeadCommit *result, void *user_data)
memcpy (task->server_head_id, result->head_commit, 40);
start_clone_v2 (task);
} else {
task->http_sync = FALSE;
connect_non_http_server (task);
transition_to_error (task, CLONE_ERROR_CONNECT);
}
}
@ -289,12 +288,48 @@ http_check_head_commit (CloneTask *task)
http_tx_manager_check_head_commit (seaf->http_tx_mgr,
task->repo_id,
task->repo_version,
task->server_url,
task->effective_url,
task->token,
task->use_fileserver_port,
check_head_commit_done,
task);
}
static char *
http_fileserver_url (const char *url)
{
char *colon;
char *url_no_port;
char *ret = NULL;
colon = strrchr (url, ':');
if (colon) {
url_no_port = g_strndup(url, colon - url);
ret = g_strconcat(url_no_port, ":8082", NULL);
} else {
ret = g_strconcat(url, ":8082", NULL);
}
return ret;
}
static void
check_http_fileserver_protocol_done (HttpProtocolVersion *result, void *user_data)
{
CloneTask *task = user_data;
if (result->check_success && !result->not_supported) {
task->http_protocol_version = result->version;
task->effective_url = http_fileserver_url (task->server_url);
task->use_fileserver_port = TRUE;
task->http_sync = TRUE;
http_check_head_commit (task);
} else {
/* Wait for periodic retry. */
transition_state (task, CLONE_STATE_CONNECT);
}
}
static void
check_http_protocol_done (HttpProtocolVersion *result, void *user_data)
{
@ -302,10 +337,21 @@ check_http_protocol_done (HttpProtocolVersion *result, void *user_data)
if (result->check_success && !result->not_supported) {
task->http_protocol_version = result->version;
task->effective_url = g_strdup(task->server_url);
task->http_sync = TRUE;
http_check_head_commit (task);
} else
connect_non_http_server (task);
} else if (strncmp(task->server_url, "https", 5) != 0) {
char *host_fileserver = http_fileserver_url(task->server_url);
http_tx_manager_check_protocol_version (seaf->http_tx_mgr,
host_fileserver,
TRUE,
check_http_fileserver_protocol_done,
task);
g_free (host_fileserver);
} else {
/* Wait for periodic retry. */
transition_state (task, CLONE_STATE_CONNECT);
}
}
static void
@ -313,6 +359,7 @@ check_http_protocol (CloneTask *task)
{
http_tx_manager_check_protocol_version (seaf->http_tx_mgr,
task->server_url,
FALSE,
check_http_protocol_done,
task);
transition_state (task, CLONE_STATE_CHECK_HTTP);
@ -359,6 +406,7 @@ clone_task_free (CloneTask *task)
g_free (task->email);
g_free (task->random_key);
g_free (task->server_url);
g_free (task->effective_url);
g_free (task);
}
@ -539,10 +587,18 @@ restart_task (sqlite3_stmt *stmt, void *data)
if (repo != NULL && repo->head != NULL) {
transition_state (task, CLONE_STATE_DONE);
return TRUE;
} else if (seaf->enable_http_sync && task->repo_version > 0 && task->server_url)
check_http_protocol (task);
else
}
if (task->repo_version > 0) {
if (seaf->enable_http_sync && task->server_url) {
check_http_protocol (task);
} else {
transition_to_error (task, CLONE_ERROR_CONNECT);
return TRUE;
}
} else {
connect_non_http_server (task);
}
g_hash_table_insert (mgr->tasks, g_strdup(task->repo_id), task);
@ -603,7 +659,10 @@ static int check_connect_pulse (void *vmanager)
while (g_hash_table_iter_next (&iter, &key, &value)) {
task = value;
if (task->state == CLONE_STATE_CONNECT) {
continue_task_when_peer_connected (task);
if (task->repo_version == 0)
continue_task_when_peer_connected (task);
else
check_http_protocol (task);
}
}
@ -790,7 +849,7 @@ add_transfer_task (CloneTask *task, GError **error)
int ret = http_tx_manager_add_download (seaf->http_tx_mgr,
task->repo_id,
task->repo_version,
task->server_url,
task->effective_url,
task->token,
task->server_head_id,
TRUE,
@ -798,6 +857,7 @@ add_transfer_task (CloneTask *task, GError **error)
task->worktree,
task->http_protocol_version,
task->email,
task->use_fileserver_port,
error);
if (ret < 0)
return -1;
@ -1251,10 +1311,16 @@ add_task_common (SeafCloneManager *mgr,
return NULL;
}
if (seaf->enable_http_sync && task->repo_version > 0 && task->server_url)
check_http_protocol (task);
else
if (task->repo_version > 0) {
if (seaf->enable_http_sync && task->server_url) {
check_http_protocol (task);
} else {
clone_task_free (task);
return NULL;
}
} else {
connect_non_http_server (task);
}
/* The old task for this repo will be freed. */
g_hash_table_insert (mgr->tasks, g_strdup(task->repo_id), task);
@ -2238,7 +2304,10 @@ on_repo_http_fetched (SeafileSession *seaf,
transition_state (task, CLONE_STATE_CANCELED);
return;
} else if (tx_task->state == HTTP_TASK_STATE_ERROR) {
transition_to_error (task, CLONE_ERROR_FETCH);
if (add_transfer_task (task, NULL) == 0)
transition_state (task, CLONE_STATE_FETCH);
else
transition_to_error (task, CLONE_ERROR_FETCH);
return;
}
@ -2347,7 +2416,8 @@ check_folder_permissions (CloneTask *task)
/* The requests list will be freed in http tx manager. */
http_tx_manager_get_folder_perms (seaf->http_tx_mgr,
task->server_url,
task->effective_url,
task->use_fileserver_port,
requests,
check_folder_perms_done,
task);

View File

@ -61,6 +61,8 @@ struct _CloneTask {
/* Http sync fields */
char *server_url;
char *effective_url;
gboolean use_fileserver_port;
int http_protocol_version;
gboolean http_sync;
char server_head_id[41];

View File

@ -692,6 +692,7 @@ transition_state (HttpTxTask *task, int state, int rt_state)
typedef struct {
char *host;
gboolean use_fileserver_port;
HttpProtocolVersionCallback callback;
void *user_data;
@ -753,7 +754,10 @@ check_protocol_version_thread (void *vdata)
curl = conn->curl;
url = g_strdup_printf ("%s/seafhttp/protocol-version", data->host);
if (!data->use_fileserver_port)
url = g_strdup_printf ("%s/seafhttp/protocol-version", data->host);
else
url = g_strdup_printf ("%s/protocol-version", data->host);
if (http_get (curl, url, NULL, &status, &rsp_content, &rsp_size, NULL, NULL, FALSE) < 0) {
goto out;
@ -799,12 +803,14 @@ check_protocol_version_done (void *vdata)
int
http_tx_manager_check_protocol_version (HttpTxManager *manager,
const char *host,
gboolean use_fileserver_port,
HttpProtocolVersionCallback callback,
void *user_data)
{
CheckProtocolData *data = g_new0 (CheckProtocolData, 1);
data->host = g_strdup(host);
data->use_fileserver_port = use_fileserver_port;
data->callback = callback;
data->user_data = user_data;
@ -823,6 +829,7 @@ typedef struct {
int repo_version;
char *host;
char *token;
gboolean use_fileserver_port;
HttpHeadCommitCallback callback;
void *user_data;
@ -892,8 +899,12 @@ check_head_commit_thread (void *vdata)
curl = conn->curl;
url = g_strdup_printf ("%s/seafhttp/repo/%s/commit/HEAD",
data->host, data->repo_id);
if (!data->use_fileserver_port)
url = g_strdup_printf ("%s/seafhttp/repo/%s/commit/HEAD",
data->host, data->repo_id);
else
url = g_strdup_printf ("%s/repo/%s/commit/HEAD",
data->host, data->repo_id);
if (http_get (curl, url, data->token, &status, &rsp_content, &rsp_size,
NULL, NULL, FALSE) < 0)
@ -942,6 +953,7 @@ http_tx_manager_check_head_commit (HttpTxManager *manager,
int repo_version,
const char *host,
const char *token,
gboolean use_fileserver_port,
HttpHeadCommitCallback callback,
void *user_data)
{
@ -953,6 +965,7 @@ http_tx_manager_check_head_commit (HttpTxManager *manager,
data->token = g_strdup(token);
data->callback = callback;
data->user_data = user_data;
data->use_fileserver_port = use_fileserver_port;
ccnet_job_manager_schedule_job (seaf->job_mgr,
check_head_commit_thread,
@ -989,6 +1002,7 @@ http_folder_perm_res_free (HttpFolderPermRes *res)
typedef struct {
char *host;
gboolean use_fileserver_port;
GList *requests;
HttpGetFolderPermsCallback callback;
void *user_data;
@ -1229,7 +1243,10 @@ get_folder_perms_thread (void *vdata)
curl = conn->curl;
url = g_strdup_printf ("%s/seafhttp/repo/folder-perm", data->host);
if (!data->use_fileserver_port)
url = g_strdup_printf ("%s/seafhttp/repo/folder-perm", data->host);
else
url = g_strdup_printf ("%s/repo/folder-perm", data->host);
req_content = compose_get_folder_perms_request (data->requests);
if (!req_content)
@ -1283,6 +1300,7 @@ get_folder_perms_done (void *vdata)
int
http_tx_manager_get_folder_perms (HttpTxManager *manager,
const char *host,
gboolean use_fileserver_port,
GList *folder_perm_requests,
HttpGetFolderPermsCallback callback,
void *user_data)
@ -1293,6 +1311,7 @@ http_tx_manager_get_folder_perms (HttpTxManager *manager,
data->requests = folder_perm_requests;
data->callback = callback;
data->user_data = user_data;
data->use_fileserver_port = use_fileserver_port;
ccnet_job_manager_schedule_job (seaf->job_mgr,
get_folder_perms_thread,
@ -1335,17 +1354,18 @@ check_permission (HttpTxTask *task, Connection *conn)
curl = conn->curl;
const char *type = (task->type == HTTP_TASK_TYPE_DOWNLOAD) ? "download" : "upload";
const char *url_prefix = (task->use_fileserver_port) ? "" : "seafhttp/";
if (seaf->session->base.name) {
char *client_name = g_uri_escape_string (seaf->session->base.name,
NULL, FALSE);
url = g_strdup_printf ("%s/seafhttp/repo/%s/permission-check/?op=%s"
url = g_strdup_printf ("%s/%srepo/%s/permission-check/?op=%s"
"&client_id=%s&client_name=%s",
task->host, task->repo_id, type,
task->host, url_prefix, task->repo_id, type,
seaf->session->base.id, client_name);
g_free (client_name);
} else {
url = g_strdup_printf ("%s/seafhttp/repo/%s/permission-check/?op=%s",
task->host, task->repo_id, type);
url = g_strdup_printf ("%s/%srepo/%s/permission-check/?op=%s",
task->host, url_prefix, task->repo_id, type);
}
if (http_get (curl, url, task->token, &status, NULL, NULL, NULL, NULL, FALSE) < 0) {
@ -1379,6 +1399,7 @@ http_tx_manager_add_upload (HttpTxManager *manager,
const char *host,
const char *token,
int protocol_version,
gboolean use_fileserver_port,
GError **error)
{
HttpTxTask *task;
@ -1405,6 +1426,8 @@ http_tx_manager_add_upload (HttpTxManager *manager,
task->state = TASK_STATE_NORMAL;
task->use_fileserver_port = use_fileserver_port;
g_hash_table_insert (manager->priv->upload_tasks,
g_strdup(repo_id),
task);
@ -1541,8 +1564,12 @@ check_quota (HttpTxTask *task, Connection *conn)
curl = conn->curl;
url = g_strdup_printf ("%s/seafhttp/repo/%s/quota-check/?delta=%"G_GINT64_FORMAT"",
task->host, task->repo_id, delta);
if (!task->use_fileserver_port)
url = g_strdup_printf ("%s/seafhttp/repo/%s/quota-check/?delta=%"G_GINT64_FORMAT"",
task->host, task->repo_id, delta);
else
url = g_strdup_printf ("%s/repo/%s/quota-check/?delta=%"G_GINT64_FORMAT"",
task->host, task->repo_id, delta);
if (http_get (curl, url, task->token, &status, NULL, NULL, NULL, NULL, FALSE) < 0) {
task->error = HTTP_TASK_ERR_NET;
@ -1583,8 +1610,12 @@ send_commit_object (HttpTxTask *task, Connection *conn)
curl = conn->curl;
url = g_strdup_printf ("%s/seafhttp/repo/%s/commit/%s",
task->host, task->repo_id, task->head);
if (!task->use_fileserver_port)
url = g_strdup_printf ("%s/seafhttp/repo/%s/commit/%s",
task->host, task->repo_id, task->head);
else
url = g_strdup_printf ("%s/repo/%s/commit/%s",
task->host, task->repo_id, task->head);
if (http_put (curl, url, task->token,
data, len,
@ -1903,8 +1934,12 @@ send_fs_objects (HttpTxTask *task, Connection *conn, GList **send_fs_list)
curl = conn->curl;
url = g_strdup_printf ("%s/seafhttp/repo/%s/recv-fs/",
task->host, task->repo_id);
if (!task->use_fileserver_port)
url = g_strdup_printf ("%s/seafhttp/repo/%s/recv-fs/",
task->host, task->repo_id);
else
url = g_strdup_printf ("%s/repo/%s/recv-fs/",
task->host, task->repo_id);
if (http_post (curl, url, task->token,
package, evbuffer_get_length(buf),
@ -2177,8 +2212,12 @@ send_block (HttpTxTask *task, Connection *conn, const char *block_id)
curl = conn->curl;
url = g_strdup_printf ("%s/seafhttp/repo/%s/block/%s",
task->host, task->repo_id, block_id);
if (!task->use_fileserver_port)
url = g_strdup_printf ("%s/seafhttp/repo/%s/block/%s",
task->host, task->repo_id, block_id);
else
url = g_strdup_printf ("%s/repo/%s/block/%s",
task->host, task->repo_id, block_id);
if (http_put (curl, url, task->token,
NULL, bmd->size,
@ -2219,8 +2258,12 @@ update_branch (HttpTxTask *task, Connection *conn)
curl = conn->curl;
url = g_strdup_printf ("%s/seafhttp/repo/%s/commit/HEAD/?head=%s",
task->host, task->repo_id, task->head);
if (!task->use_fileserver_port)
url = g_strdup_printf ("%s/seafhttp/repo/%s/commit/HEAD/?head=%s",
task->host, task->repo_id, task->head);
else
url = g_strdup_printf ("%s/repo/%s/commit/HEAD/?head=%s",
task->host, task->repo_id, task->head);
if (http_put (curl, url, task->token,
NULL, 0,
@ -2338,8 +2381,12 @@ http_upload_thread (void *vdata)
goto out;
}
url = g_strdup_printf ("%s/seafhttp/repo/%s/check-fs/",
task->host, task->repo_id);
if (!task->use_fileserver_port)
url = g_strdup_printf ("%s/seafhttp/repo/%s/check-fs/",
task->host, task->repo_id);
else
url = g_strdup_printf ("%s/repo/%s/check-fs/",
task->host, task->repo_id);
while (send_fs_list != NULL) {
if (upload_check_id_list_segment (task, conn, url,
@ -2373,8 +2420,12 @@ http_upload_thread (void *vdata)
goto out;
}
url = g_strdup_printf ("%s/seafhttp/repo/%s/check-blocks/",
task->host, task->repo_id);
if (!task->use_fileserver_port)
url = g_strdup_printf ("%s/seafhttp/repo/%s/check-blocks/",
task->host, task->repo_id);
else
url = g_strdup_printf ("%s/repo/%s/check-blocks/",
task->host, task->repo_id);
while (block_list != NULL) {
if (upload_check_id_list_segment (task, conn, url,
@ -2466,6 +2517,7 @@ http_tx_manager_add_download (HttpTxManager *manager,
const char *worktree,
int protocol_version,
const char *email,
gboolean use_fileserver_port,
GError **error)
{
HttpTxTask *task;
@ -2496,6 +2548,8 @@ http_tx_manager_add_download (HttpTxManager *manager,
task->state = TASK_STATE_NORMAL;
task->use_fileserver_port = use_fileserver_port;
g_hash_table_insert (manager->priv->download_tasks,
g_strdup(repo_id),
task);
@ -2520,8 +2574,12 @@ get_commit_object (HttpTxTask *task, Connection *conn)
curl = conn->curl;
url = g_strdup_printf ("%s/seafhttp/repo/%s/commit/%s",
task->host, task->repo_id, task->head);
if (!task->use_fileserver_port)
url = g_strdup_printf ("%s/seafhttp/repo/%s/commit/%s",
task->host, task->repo_id, task->head);
else
url = g_strdup_printf ("%s/repo/%s/commit/%s",
task->host, task->repo_id, task->head);
if (http_get (curl, url, task->token, &status,
&rsp_content, &rsp_size,
@ -2573,6 +2631,8 @@ get_needed_fs_id_list (HttpTxTask *task, Connection *conn, GList **fs_id_list)
json_error_t jerror;
const char *obj_id;
const char *url_prefix = (task->use_fileserver_port) ? "" : "seafhttp/";
if (!task->is_clone) {
master = seaf_branch_manager_get_branch (seaf->branch_mgr,
task->repo_id,
@ -2583,15 +2643,15 @@ get_needed_fs_id_list (HttpTxTask *task, Connection *conn, GList **fs_id_list)
return -1;
}
url = g_strdup_printf ("%s/seafhttp/repo/%s/fs-id-list/"
url = g_strdup_printf ("%s/%srepo/%s/fs-id-list/"
"?server-head=%s&client-head=%s",
task->host, task->repo_id,
task->host, url_prefix, task->repo_id,
task->head, master->commit_id);
seaf_branch_unref (master);
} else {
url = g_strdup_printf ("%s/seafhttp/repo/%s/fs-id-list/?server-head=%s",
task->host, task->repo_id, task->head);
url = g_strdup_printf ("%s/%srepo/%s/fs-id-list/?server-head=%s",
task->host, url_prefix, task->repo_id, task->head);
}
curl = conn->curl;
@ -2720,7 +2780,10 @@ get_fs_objects (HttpTxTask *task, Connection *conn, GList **fs_list)
curl = conn->curl;
url = g_strdup_printf ("%s/seafhttp/repo/%s/pack-fs/", task->host, task->repo_id);
if (!task->use_fileserver_port)
url = g_strdup_printf ("%s/seafhttp/repo/%s/pack-fs/", task->host, task->repo_id);
else
url = g_strdup_printf ("%s/repo/%s/pack-fs/", task->host, task->repo_id);
if (http_post (curl, url, task->token,
data, len,
@ -2877,8 +2940,12 @@ get_block (HttpTxTask *task, Connection *conn, const char *block_id)
curl = conn->curl;
url = g_strdup_printf ("%s/seafhttp/repo/%s/block/%s",
task->host, task->repo_id, block_id);
if (!task->use_fileserver_port)
url = g_strdup_printf ("%s/seafhttp/repo/%s/block/%s",
task->host, task->repo_id, block_id);
else
url = g_strdup_printf ("%s/repo/%s/block/%s",
task->host, task->repo_id, block_id);
if (http_get (curl, url, task->token, &status, NULL, NULL,
get_block_callback, &data, TRUE) < 0) {

View File

@ -69,6 +69,7 @@ struct _HttpTxTask {
char *host;
gboolean is_clone;
char *email;
gboolean use_fileserver_port;
char head[41];
@ -109,6 +110,7 @@ http_tx_manager_add_download (HttpTxManager *manager,
const char *worktree,
int protocol_version,
const char *email,
gboolean use_fileserver_port,
GError **error);
int
@ -118,6 +120,7 @@ http_tx_manager_add_upload (HttpTxManager *manager,
const char *host,
const char *token,
int protocol_version,
gboolean use_fileserver_port,
GError **error);
struct _HttpProtocolVersion {
@ -136,6 +139,7 @@ typedef void (*HttpProtocolVersionCallback) (HttpProtocolVersion *result,
int
http_tx_manager_check_protocol_version (HttpTxManager *manager,
const char *host,
gboolean use_fileserver_port,
HttpProtocolVersionCallback callback,
void *user_data);
@ -157,6 +161,7 @@ http_tx_manager_check_head_commit (HttpTxManager *manager,
int repo_version,
const char *host,
const char *token,
gboolean use_fileserver_port,
HttpHeadCommitCallback callback,
void *user_data);
@ -192,6 +197,7 @@ typedef void (*HttpGetFolderPermsCallback) (HttpFolderPerms *result,
int
http_tx_manager_get_folder_perms (HttpTxManager *manager,
const char *host,
gboolean use_fileserver_port,
GList *folder_perm_requests, /* HttpFolderPermReq */
HttpGetFolderPermsCallback callback,
void *user_data);

View File

@ -89,6 +89,9 @@ struct _SeafRepo {
/* Used for http sync. */
char *server_url;
/* Can be server_url or server_url:8082, depends on which one works. */
char *effective_host;
gboolean use_fileserver_port;
};

View File

@ -42,9 +42,13 @@ struct _ServerState {
typedef struct _ServerState ServerState;
struct _HttpServerState {
gboolean http_not_supported;
int http_version;
gboolean checking;
gint64 last_http_check_time;
char *testing_host;
/* Can be server_url or server_url:8082, depends on which one works. */
char *effective_host;
gboolean use_fileserver_port;
gboolean folder_perms_not_supported;
gint64 last_check_perms_time;
@ -96,7 +100,7 @@ static int
sync_repo_v2 (SeafSyncManager *manager, SeafRepo *repo, gboolean is_manual_sync);
static gboolean
check_http_protocol (SeafSyncManager *mgr, SeafRepo *repo, gboolean *is_checking);
check_http_protocol (SeafSyncManager *mgr, SeafRepo *repo);
SeafSyncManager*
seaf_sync_manager_new (SeafileSession *seaf)
@ -217,7 +221,10 @@ add_repo_relays ()
for (ptr = repo_list; ptr; ptr = ptr->next) {
SeafRepo *repo = ptr->data;
if (repo->relay_id) {
/* Only use non-http sync protocol for old repos.
* If no old repos exist, we don't need to connect to 10001 port.
*/
if (repo->version == 0 && repo->relay_id) {
add_relay_if_needed (repo);
}
}
@ -406,32 +413,25 @@ seaf_sync_manager_add_sync_task (SeafSyncManager *mgr,
if (info->in_sync)
return 0;
gboolean is_checking_http = FALSE;
if (seaf->enable_http_sync && repo->version > 0) {
if (check_http_protocol (mgr, repo, &is_checking_http)) {
sync_repo_v2 (mgr, repo, TRUE);
if (repo->version > 0) {
if (seaf->enable_http_sync) {
if (check_http_protocol (mgr, repo)) {
sync_repo_v2 (mgr, repo, TRUE);
return 0;
}
} else
return 0;
} else {
/* If relay is not ready or protocol version is not determined,
* need to wait.
*/
if (!check_relay_status (mgr, repo)) {
seaf_warning ("Relay for repo %s(%.8s) is not ready or protocol version"
"is not detected.\n", repo->name, repo->id);
return 0;
}
}
/* If relay is not ready or protocol version is not determined,
* need to wait.
*/
if (!check_relay_status (mgr, repo)) {
seaf_warning ("Relay for repo %s(%.8s) is not ready or protocol version"
"is not detected.\n", repo->name, repo->id);
return 0;
}
ServerState *state = g_hash_table_lookup (mgr->server_states,
repo->relay_id);
if (repo->version == 0 ||
state->server_side_merge == SERVER_SIDE_MERGE_UNSUPPORTED ||
has_old_commits_to_upload (repo))
start_sync (mgr, repo, TRUE, TRUE, FALSE);
else if (state->server_side_merge == SERVER_SIDE_MERGE_SUPPORTED)
sync_repo_v2 (mgr, repo, TRUE);
}
return 0;
}
@ -696,9 +696,10 @@ start_upload_if_necessary (SyncTask *task)
if (http_tx_manager_add_upload (seaf->http_tx_mgr,
repo->id,
repo->version,
repo->server_url,
repo->effective_host,
repo->token,
task->http_version,
repo->use_fileserver_port,
&error) < 0) {
seaf_warning ("Failed to start http upload: %s\n", error->message);
seaf_sync_manager_set_task_error (task, SYNC_ERROR_START_UPLOAD);
@ -743,13 +744,14 @@ start_fetch_if_necessary (SyncTask *task, const char *remote_head)
if (http_tx_manager_add_download (seaf->http_tx_mgr,
repo->id,
repo->version,
repo->server_url,
repo->effective_host,
repo->token,
remote_head,
FALSE,
NULL, NULL,
task->http_version,
repo->email,
repo->use_fileserver_port,
&error) < 0) {
seaf_warning ("Failed to start http download: %s.\n", error->message);
seaf_sync_manager_set_task_error (task, SYNC_ERROR_START_FETCH);
@ -1502,8 +1504,9 @@ check_head_commit_http (SyncTask *task)
int ret = http_tx_manager_check_head_commit (seaf->http_tx_mgr,
repo->id, repo->version,
repo->server_url,
repo->effective_host,
repo->token,
repo->use_fileserver_port,
check_head_commit_done,
task);
if (ret == 0)
@ -1751,10 +1754,8 @@ create_sync_task_v2 (SeafSyncManager *manager, SeafRepo *repo,
HttpServerState *state = g_hash_table_lookup (manager->http_server_states,
repo->server_url);
if (state) {
if (!state->http_not_supported) {
task->http_sync = TRUE;
task->http_version = state->http_version;
}
task->http_sync = TRUE;
task->http_version = state->http_version;
}
}
@ -1970,34 +1971,68 @@ check_relay_status (SeafSyncManager *mgr, SeafRepo *repo)
}
}
static char *
http_fileserver_url (const char *url)
{
char *colon;
char *url_no_port;
char *ret = NULL;
colon = strrchr (url, ':');
if (colon) {
url_no_port = g_strndup(url, colon - url);
ret = g_strconcat(url_no_port, ":8082", NULL);
} else {
ret = g_strconcat(url, ":8082", NULL);
}
return ret;
}
static void
check_http_protocol_done (HttpProtocolVersion *result, void *user_data)
check_http_fileserver_protocol_done (HttpProtocolVersion *result, void *user_data)
{
HttpServerState *state = user_data;
state->checking = FALSE;
if (result->check_success) {
state->http_not_supported = result->not_supported;
if (!result->not_supported)
state->http_version = result->version;
} else
state->http_not_supported = TRUE;
if (result->check_success && !result->not_supported) {
state->http_version = result->version;
state->effective_host = http_fileserver_url(state->testing_host);
state->use_fileserver_port = TRUE;
}
}
static void
check_http_protocol_done (HttpProtocolVersion *result, void *user_data)
{
HttpServerState *state = user_data;
if (result->check_success && !result->not_supported) {
state->http_version = result->version;
state->effective_host = g_strdup(state->testing_host);
state->checking = FALSE;
} else if (strncmp(state->testing_host, "https", 5) != 0) {
char *host_fileserver = http_fileserver_url(state->testing_host);
http_tx_manager_check_protocol_version (seaf->http_tx_mgr,
host_fileserver,
TRUE,
check_http_fileserver_protocol_done,
state);
g_free (host_fileserver);
} else {
state->checking = FALSE;
}
}
#define CHECK_HTTP_INTERVAL 10
/*
* Returns TRUE if we can use http-sync; otherwise FALSE.
* If FALSE is returned, the caller should also check @is_checking value.
* If @is_checking is set to TRUE, we're still determining whether the
* server supports http-sync.
* Returns TRUE if we're ready to use http-sync; otherwise FALSE.
*/
static gboolean
check_http_protocol (SeafSyncManager *mgr, SeafRepo *repo, gboolean *is_checking)
check_http_protocol (SeafSyncManager *mgr, SeafRepo *repo)
{
*is_checking = FALSE;
/* If a repo was cloned before 4.0, server-url is not set. */
if (!repo->server_url)
return FALSE;
@ -2011,21 +2046,36 @@ check_http_protocol (SeafSyncManager *mgr, SeafRepo *repo, gboolean *is_checking
}
if (state->checking) {
*is_checking = TRUE;
return FALSE;
}
if (state->http_not_supported)
return FALSE;
if (state->http_version > 0)
if (state->http_version > 0) {
if (!repo->effective_host) {
repo->effective_host = g_strdup(state->effective_host);
repo->use_fileserver_port = state->use_fileserver_port;
}
return TRUE;
}
/* If we haven't detected the server url successfully, retry every 10 seconds. */
gint64 now = time(NULL);
if (now - state->last_http_check_time < CHECK_HTTP_INTERVAL)
return FALSE;
/* First try repo->server_url.
* If it fails and https is not used, try server_url:8082 instead.
*/
g_free (state->testing_host);
state->testing_host = g_strdup(repo->server_url);
state->last_http_check_time = (gint64)time(NULL);
http_tx_manager_check_protocol_version (seaf->http_tx_mgr,
repo->server_url,
FALSE,
check_http_protocol_done,
state);
state->checking = TRUE;
*is_checking = TRUE;
return FALSE;
}
@ -2381,7 +2431,8 @@ check_folder_permissions_one_server (SeafSyncManager *mgr,
/* The requests list will be freed in http tx manager. */
http_tx_manager_get_folder_perms (seaf->http_tx_mgr,
host,
server_state->effective_host,
server_state->use_fileserver_port,
requests,
check_folder_perms_done,
server_state);
@ -2494,32 +2545,20 @@ auto_sync_pulse (void *vmanager)
if (info->in_sync)
continue;
/* Try to use http sync first if enabled. */
gboolean is_checking_http = FALSE;
if (seaf->enable_http_sync && repo->version > 0) {
if (check_http_protocol (manager, repo, &is_checking_http)) {
sync_repo_v2 (manager, repo, FALSE);
continue;
} else if (is_checking_http)
continue;
/* Otherwise we've determined the server doesn't support http-sync. */
if (repo->version > 0) {
/* For repo version > 0, only use http sync. */
if (seaf->enable_http_sync) {
if (check_http_protocol (manager, repo)) {
sync_repo_v2 (manager, repo, FALSE);
}
}
} else {
/* If relay is not ready or protocol version is not determined,
* need to wait.
*/
if (check_relay_status (manager, repo))
sync_repo (manager, repo);
}
/* If relay is not ready or protocol version is not determined,
* need to wait.
*/
if (!check_relay_status (manager, repo))
continue;
ServerState *state = g_hash_table_lookup (manager->server_states,
repo->relay_id);
if (repo->version == 0 ||
state->server_side_merge == SERVER_SIDE_MERGE_UNSUPPORTED ||
has_old_commits_to_upload (repo))
sync_repo (manager, repo);
else if (state->server_side_merge == SERVER_SIDE_MERGE_SUPPORTED)
sync_repo_v2 (manager, repo, FALSE);
}
g_list_free (repos);