static void handle_upload_ok (CcnetProcessor *processor, TransferTask *task, char *content, int clen) { if (clen == 0) { ccnet_processor_send_update (processor, SC_GET_TOKEN, SS_GET_TOKEN, NULL, 0); return; } if (clen != 41 || content[clen-1] != '\0') { g_warning ("Bad response content.\n"); transfer_task_set_error (task, TASK_ERR_UNKNOWN); ccnet_processor_send_update (processor, SC_BAD_ARGS, SS_BAD_ARGS, NULL, 0); ccnet_processor_done (processor, FALSE); return; } memcpy (task->remote_head, content, 41); /* Check fast-forward here. */ if (strcmp (task->head, task->remote_head) != 0 && !is_fast_forward (task->head, task->remote_head)) { g_warning ("Upload is not fast-forward.\n"); transfer_task_set_error (task, TASK_ERR_NOT_FAST_FORWARD); ccnet_processor_send_update (processor, SC_SHUTDOWN, SS_SHUTDOWN, NULL, 0); ccnet_processor_done (processor, FALSE); return; } ccnet_processor_send_update (processor, SC_GET_TOKEN, SS_GET_TOKEN, NULL, 0); }
static void commit_write_cb (OSAsyncResult *res, void *data) { CcnetProcessor *processor = data; TransferTask *task = ((SeafileGetcommitV3Proc *)processor)->tx_task; SeafCommit *commit; if (!res->success) { seaf_warning ("Failed to write commit %.8s.\n", res->obj_id); transfer_task_set_error (task, TASK_ERR_DOWNLOAD_COMMIT); ccnet_processor_send_update (processor, SC_SHUTDOWN, SS_SHUTDOWN, NULL, 0); ccnet_processor_done (processor, FALSE); return; } commit = seaf_commit_from_data (res->obj_id, res->data, res->len); if (!commit) { seaf_warning ("[getcommit] Bad commit object received.\n"); transfer_task_set_error (task, TASK_ERR_DOWNLOAD_COMMIT); ccnet_processor_send_update (processor, SC_BAD_OBJECT, SS_BAD_OBJECT, NULL, 0); ccnet_processor_done (processor, FALSE); return; } if (strcmp (commit->root_id, EMPTY_SHA1) != 0) object_list_insert (task->fs_roots, commit->root_id); seaf_commit_unref (commit); ccnet_processor_done (processor, TRUE); }
static void handle_response (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { SeafileGetcommitProc *proc = (SeafileGetcommitProc *)processor; if (proc->tx_task->state != TASK_STATE_NORMAL) { /* TODO: not tested yet */ ccnet_processor_send_update (processor, SC_SHUTDOWN, SS_SHUTDOWN, NULL, 0); ccnet_processor_done (processor, TRUE); return; } switch (processor->state) { case INIT: if (strncmp(code, SC_OK, 3) == 0) { processor->state = RECV_IDS; } else { g_warning ("[getcommit] Bad response: %s %s\n", code, code_msg); transfer_task_set_error (proc->tx_task, TASK_ERR_DOWNLOAD_COMMIT); ccnet_processor_done (processor, FALSE); } break; case RECV_IDS: if (strncmp(code, SC_COMMIT_IDS, 3) == 0) { /* add to inspect queue */ process_commit_list (processor, content, clen); } else if (strncmp(code, SC_END, 3) == 0) { /* change state to FETCH_OBJECT */ processor->state = FETCH_OBJECT; } else { g_warning ("[getcommit] Bad response: %s %s\n", code, code_msg); transfer_task_set_error (proc->tx_task, TASK_ERR_DOWNLOAD_COMMIT); ccnet_processor_done (processor, FALSE); } break; case FETCH_OBJECT: if (strncmp(code, SC_OBJECT, 3) == 0) { receive_commit (processor, content, clen); } else { g_warning ("[getcommit] Bad response: %s %s\n", code, code_msg); /* Transfer the task state to error when an error ocurred */ transfer_task_set_error (proc->tx_task, TASK_ERR_DOWNLOAD_COMMIT); ccnet_processor_done (processor, FALSE); } break; default: g_assert (0); } }
static void receive_commit (CcnetProcessor *processor, char *content, int clen) { ObjectPack *pack = (ObjectPack *)content; if (clen < sizeof(ObjectPack)) { seaf_warning ("[getcommit] invalid object id.\n"); goto bad; } seaf_debug ("[getcommit] recv commit object %.8s\n", pack->id); if (save_commit (processor, pack, clen) < 0) { goto bad; } return; bad: seaf_warning ("[getcommit] Bad commit object received.\n"); transfer_task_set_error (((SeafileGetcommitV3Proc *)processor)->tx_task, TASK_ERR_DOWNLOAD_COMMIT); ccnet_processor_send_update (processor, SC_BAD_OBJECT, SS_BAD_OBJECT, NULL, 0); ccnet_processor_done (processor, FALSE); }
static void fs_object_write_cb (OSAsyncResult *res, void *data) { CcnetProcessor *processor = data; USE_PRIV; if (!res->success) { seaf_warning ("Failed to write object %.8s.\n", res->obj_id); transfer_task_set_error (((SeafileGetfsProc *)processor)->tx_task, TASK_ERR_DOWNLOAD_FS); ccnet_processor_send_update (processor, SC_SHUTDOWN, SS_SHUTDOWN, NULL, 0); ccnet_processor_done (processor, FALSE); return; } seaf_debug ("Written object %.8s.\n", res->obj_id); --(priv->pending_objects); int type = seaf_metadata_type_from_data (res->data, res->len); if (type == SEAF_METADATA_TYPE_DIR) g_queue_push_tail (priv->inspect_queue, g_strdup(res->obj_id)); end_or_check_next_dir (processor, priv); }
static void end_or_check_next_dir (CcnetProcessor *processor, SeafileGetfsProcPriv *priv) { if (check_end_condition (priv)) { seaf_debug ("Get fs end.\n"); ccnet_processor_send_update (processor, SC_END, SS_END, NULL, 0); ccnet_processor_done (processor, TRUE); return; } if (priv->worker_running) { return; } /* Trigger checking the next dir. */ char *next_dir_id = g_queue_pop_head (priv->inspect_queue); if (next_dir_id) { if (check_fs_tree_from (processor, next_dir_id) < 0) { transfer_task_set_error (((SeafileGetfsProc *)processor)->tx_task, TASK_ERR_DOWNLOAD_FS); ccnet_processor_send_update (processor, SC_SHUTDOWN, SS_SHUTDOWN, NULL, 0); ccnet_processor_done (processor, FALSE); } g_free (next_dir_id); } }
static void handle_response (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { SeafileSendcommitV3Proc *proc = (SeafileSendcommitV3Proc *)processor; TransferTask *task = proc->tx_task; if (task->state != TASK_STATE_NORMAL) { ccnet_processor_done (processor, TRUE); return; } switch (processor->state) { case INIT: if (memcmp (code, SC_OK, 3) == 0) { processor->state = SEND_OBJECT; send_commits (processor, task->head); return; } break; case SEND_OBJECT: if (memcmp (code, SC_ACK, 3) == 0) { send_one_commit (processor); return; } break; default: g_return_if_reached (); } g_warning ("Bad response: %s %s.\n", code, code_msg); if (memcmp (code, SC_ACCESS_DENIED, 3) == 0) transfer_task_set_error (task, TASK_ERR_ACCESS_DENIED); ccnet_processor_done (processor, FALSE); }
static void process_commit_list (CcnetProcessor *processor, char *content, int clen) { USE_PRIV; char *object_id; int n_objects; int i; if (clen % 41 != 1 || content[clen-1] != '\0') { g_warning ("[getcommit] Bad commit id list.\n"); ccnet_processor_send_update (processor, SC_BAD_OL, SS_BAD_OL, NULL, 0); transfer_task_set_error (((SeafileGetcommitProc *)processor)->tx_task, TASK_ERR_DOWNLOAD_COMMIT); ccnet_processor_done (processor, FALSE); return; } n_objects = clen/41; request_object_batch_begin(priv); object_id = content; for (i = 0; i < n_objects; ++i) { object_id[40] = '\0'; check_commit (processor, object_id); object_id += 41; } request_object_batch_flush (processor, priv); if (priv->pending_objects == 0) { ccnet_processor_send_update (processor, SC_END, SS_END, NULL, 0); ccnet_processor_done (processor, TRUE); } }
static void receive_commit (CcnetProcessor *processor, char *content, int clen) { USE_PRIV; ObjectPack *pack = (ObjectPack *)content; if (clen < sizeof(ObjectPack)) { g_warning ("[getcommit] invalid object id.\n"); goto bad; } g_debug ("[getcommit] recv commit object %s\n", pack->id); --priv->pending_objects; if (save_commit (pack, clen) < 0) { goto bad; } if (priv->pending_objects == 0) { g_debug ("[getcommit] Receive commit completed.\n"); ccnet_processor_send_update (processor, SC_END, SS_END, NULL, 0); ccnet_processor_done (processor, TRUE); } return; bad: ccnet_processor_send_update (processor, SC_BAD_OBJECT, SS_BAD_OBJECT, NULL, 0); g_warning ("[getcommit] Bad commit object received.\n"); transfer_task_set_error (((SeafileGetcommitProc *)processor)->tx_task, TASK_ERR_DOWNLOAD_COMMIT); ccnet_processor_done (processor, FALSE); }
static void handle_response (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { SeafileSendfsProc *proc = (SeafileSendfsProc *)processor; TransferTask *task = proc->tx_task; switch (processor->state) { case SEND_ROOT: if (strncmp(code, SC_OK, 3) == 0) { send_fs_roots (processor); return; } break; case SEND_OBJECT: if (strncmp(code, SC_GET_OBJECT, 3) == 0) { send_fs_objects (processor, content, clen); return; } else if (strncmp(code, SC_END, 3) == 0) { seaf_debug ("Send fs objects end.\n"); ccnet_processor_done (processor, TRUE); return; } break; default: g_assert (0); } g_warning ("Bad response: %s %s.\n", code, code_msg); if (memcmp (code, SC_ACCESS_DENIED, 3) == 0) transfer_task_set_error (task, TASK_ERR_ACCESS_DENIED); ccnet_processor_done (processor, FALSE); }
static int recv_fs_object (CcnetProcessor *processor, char *content, int clen) { USE_PRIV; ObjectPack *pack = (ObjectPack *)content; uint32_t type; /* TransferTask *task = ((SeafileGetfsProc *)processor)->tx_task; */ if (clen < sizeof(ObjectPack)) { g_warning ("[getfs] invalid object id.\n"); goto bad; } --priv->pending_objects; type = seaf_metadata_type_from_data(pack->object, clen); if (type == SEAF_METADATA_TYPE_DIR) { SeafDir *dir; dir = seaf_dir_from_data (pack->id, pack->object, clen - 41); if (!dir) { g_warning ("[getfs] Bad directory object %s.\n", pack->id); goto bad; } g_queue_push_tail (priv->inspect_queue, g_strdup(dir->dir_id)); seaf_dir_free (dir); } else if (type == SEAF_METADATA_TYPE_FILE) { /* TODO: check seafile format. */ #if 0 int ret = seafile_check_data_format (pack->object, clen - 41); if (ret < 0) { goto bad; } #endif } else { g_warning ("[getfs] Invalid object type.\n"); goto bad; } if (save_fs_object (pack, clen) < 0) { goto bad; } g_hash_table_remove (priv->fs_objects, pack->id); return 0; bad: g_warning ("Bad fs object received.\n"); transfer_task_set_error (((SeafileGetfsProc *)processor)->tx_task, TASK_ERR_DOWNLOAD_FS); ccnet_processor_send_update (processor, SC_BAD_OBJECT, SS_BAD_OBJECT, NULL, 0); ccnet_processor_done (processor, FALSE); return -1; }
static void handle_response (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { SeafileCheckTxV3Proc *proc = (SeafileCheckTxV3Proc *)processor; TransferTask *task = proc->task; if (strncmp(code, SC_OK, 3) == 0) { if (proc->type == CHECK_TX_TYPE_UPLOAD) handle_upload_ok (processor, task, content, clen); else handle_download_ok (processor, task, content, clen); } else if (strncmp (code, SC_PUT_TOKEN, 3) == 0) { /* In LAN sync, we don't use session token. */ if (clen == 0) { ccnet_processor_done (processor, TRUE); return; } if (content[clen-1] != '\0') { g_warning ("Bad response content.\n"); transfer_task_set_error (task, TASK_ERR_UNKNOWN); ccnet_processor_send_update (processor, SC_BAD_ARGS, SS_BAD_ARGS, NULL, 0); ccnet_processor_done (processor, FALSE); return; } task->session_token = g_strdup (content); ccnet_processor_send_update (processor, SC_GET_VERSION, SS_GET_VERSION, NULL, 0); } else if (strncmp (code, SC_VERSION, 3) == 0) { task->protocol_version = atoi(content); ccnet_processor_done (processor, TRUE); } else { g_warning ("[check tx v3] Bad response: %s %s", code, code_msg); if (strncmp(code, SC_ACCESS_DENIED, 3) == 0) transfer_task_set_error (task, TASK_ERR_ACCESS_DENIED); else if (strncmp(code, SC_QUOTA_ERROR, 3) == 0) transfer_task_set_error (task, TASK_ERR_CHECK_QUOTA); else if (strncmp(code, SC_QUOTA_FULL, 3) == 0) transfer_task_set_error (task, TASK_ERR_QUOTA_FULL); else if (strncmp(code, SC_PROTOCOL_MISMATCH, 3) == 0) transfer_task_set_error (task, TASK_ERR_PROTOCOL_VERSION); else if (strncmp(code, SC_BAD_REPO, 3) == 0) transfer_task_set_error (task, TASK_ERR_BAD_REPO_ID); else transfer_task_set_error (task, TASK_ERR_UNKNOWN); ccnet_processor_done (processor, FALSE); } }
static void handle_download_ok (CcnetProcessor *processor, TransferTask *task, char *content, int clen) { if (clen != 41 || content[clen-1] != '\0') { g_warning ("Bad response content.\n"); transfer_task_set_error (task, TASK_ERR_UNKNOWN); ccnet_processor_done (processor, FALSE); return; } memcpy (task->head, content, 41); ccnet_processor_send_update (processor, SC_GET_TOKEN, SS_GET_TOKEN, NULL, 0); }
static void handle_response (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { SeafileSendblockV2Proc *proc = (SeafileSendblockV2Proc *)processor; USE_PRIV; if (proc->tx_task->state != TASK_STATE_NORMAL) { g_debug ("Task not running, send-block proc exits.\n"); ccnet_processor_done (processor, TRUE); return; } switch (priv->tdata->state) { case REQUEST_SENT: if (memcmp (code, SC_OK, 3) == 0) { send_block_list (processor); priv->tdata->state = BLOCKLIST_SENT; return; } break; case BLOCKLIST_SENT: if (memcmp (code, SC_BBITMAP, 3) == 0) { process_block_bitmap (processor, content, clen); return; } break; case GET_PORT: if (memcmp (code, SC_SEND_PORT, 3) == 0) { get_port (processor, content, clen); return; } break; case READY: if (memcmp (code, SC_ACK, 3) == 0) { process_ack (processor, content, clen); return; } } g_warning ("Bad response: %s %s.\n", code, code_msg); if (memcmp (code, SC_ACCESS_DENIED, 3) == 0) transfer_task_set_error (proc->tx_task, TASK_ERR_ACCESS_DENIED); ccnet_processor_done (processor, FALSE); }
static void handle_response (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { SeafileGetfsProc *proc = (SeafileGetfsProc *)processor; TransferTask *task = proc->tx_task; switch (processor->state) { case REQUEST_SENT: if (strncmp(code, SC_OK, 3) == 0) { load_fsroot_list (processor); processor->timer = ccnet_timer_new ( (TimerCB)check_object, processor, CHECK_INTERVAL); processor->state = FETCH_OBJECT; return; } break; case FETCH_OBJECT: if (strncmp(code, SC_OBJ_SEG, 3) == 0) { recv_fs_object_seg (processor, content, clen); return; } else if (strncmp(code, SC_OBJ_SEG_END, 3) == 0) { recv_fs_object_seg (processor, content, clen); process_fs_object_seg (processor); return; } else if (strncmp(code, SC_OBJECT, 3) == 0) { recv_fs_object (processor, content, clen); return; } break; default: g_assert (0); } g_warning ("Bad response: %s %s.\n", code, code_msg); if (memcmp (code, SC_ACCESS_DENIED, 3) == 0) transfer_task_set_error (task, TASK_ERR_ACCESS_DENIED); ccnet_processor_done (processor, FALSE); }
static void handle_response (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { SeafileGetcommitV3Proc *proc = (SeafileGetcommitV3Proc *)processor; if (proc->tx_task->state != TASK_STATE_NORMAL) { ccnet_processor_done (processor, TRUE); return; } if (strncmp(code, SC_OK, 3) == 0) { receive_commit (processor, content, clen); return; } seaf_warning ("Bad response: %s %s.\n", code, code_msg); if (memcmp (code, SC_ACCESS_DENIED, 3) == 0) transfer_task_set_error (proc->tx_task, TASK_ERR_ACCESS_DENIED); ccnet_processor_done (processor, FALSE); }
static void handle_upload_ok (CcnetProcessor *processor, TransferTask *task, char *content, int clen) { if (clen == 0) { ccnet_processor_send_update (processor, SC_GET_TOKEN, SS_GET_TOKEN, NULL, 0); return; } if (clen != 41 || content[clen-1] != '\0') { seaf_warning ("Bad response content.\n"); transfer_task_set_error (task, TASK_ERR_UNKNOWN); ccnet_processor_send_update (processor, SC_BAD_ARGS, SS_BAD_ARGS, NULL, 0); ccnet_processor_done (processor, FALSE); return; } /* Ignore the returned remote head id, just use the head of master branch. * For protocol version >= 6, the complete hitstory is not downloaded, so * there is no way to check fast forward on the client. For protocol version * < 6, the server will check fast forward anyway. */ SeafBranch *master = seaf_branch_manager_get_branch (seaf->branch_mgr, task->repo_id, "master"); if (!master) { seaf_warning ("Cannot find branch master for repo %s.\n", task->repo_id); ccnet_processor_send_update (processor, SC_SHUTDOWN, SS_SHUTDOWN, NULL, 0); ccnet_processor_done (processor, FALSE); return; } memcpy (task->remote_head, master->commit_id, 40); seaf_branch_unref (master); ccnet_processor_send_update (processor, SC_GET_TOKEN, SS_GET_TOKEN, NULL, 0); }
static void receive_commit (CcnetProcessor *processor, char *content, int clen) { ObjectPack *pack = (ObjectPack *)content; TransferTask *task = ((SeafileGetcommitV2Proc *)processor)->tx_task; SeafCommit *commit; if (clen < sizeof(ObjectPack)) { g_warning ("[getcommit] invalid object id.\n"); goto bad; } seaf_debug ("[getcommit] recv commit object %.8s\n", pack->id); if (save_commit (pack, clen) < 0) { goto bad; } commit = seaf_commit_manager_get_commit (seaf->commit_mgr, pack->id); if (!commit) goto bad; if (strcmp (commit->root_id, EMPTY_SHA1) != 0) object_list_insert (task->fs_roots, commit->root_id); seaf_commit_unref (commit); return; bad: g_warning ("[getcommit] Bad commit object received.\n"); transfer_task_set_error (((SeafileGetcommitV2Proc *)processor)->tx_task, TASK_ERR_DOWNLOAD_COMMIT); ccnet_processor_send_update (processor, SC_BAD_OBJECT, SS_BAD_OBJECT, NULL, 0); ccnet_processor_done (processor, FALSE); }
static void handle_response (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { SeafileGetcommitV2Proc *proc = (SeafileGetcommitV2Proc *)processor; if (proc->tx_task->state != TASK_STATE_NORMAL) { ccnet_processor_done (processor, TRUE); return; } switch (processor->state) { case INIT: if (strncmp(code, SC_OK, 3) == 0) { processor->state = RECV_OBJECT; return; } break; case RECV_OBJECT: if (strncmp(code, SC_OBJECT, 3) == 0) { receive_commit (processor, content, clen); return; } else if (strncmp (code, SC_END, 3) == 0) { seaf_debug ("[getcommit] Get commit end.\n"); ccnet_processor_done (processor, TRUE); return; } break; default: g_return_if_reached (); } g_warning ("Bad response: %s %s.\n", code, code_msg); if (memcmp (code, SC_ACCESS_DENIED, 3) == 0) transfer_task_set_error (proc->tx_task, TASK_ERR_ACCESS_DENIED); ccnet_processor_done (processor, FALSE); }
static void handle_response (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { SeafileCheckTxV3Proc *proc = (SeafileCheckTxV3Proc *)processor; TransferTask *task = proc->task; if (strncmp(code, SC_OK, 3) == 0) { if (proc->type == CHECK_TX_TYPE_UPLOAD) handle_upload_ok (processor, task, content, clen); else handle_download_ok (processor, task, content, clen); } else if (strncmp (code, SC_PUT_TOKEN, 3) == 0) { /* In LAN sync, we don't use session token. */ if (clen == 0) { ccnet_processor_done (processor, TRUE); return; } if (content[clen-1] != '\0') { seaf_warning ("Bad response content.\n"); transfer_task_set_error (task, TASK_ERR_UNKNOWN); ccnet_processor_send_update (processor, SC_BAD_ARGS, SS_BAD_ARGS, NULL, 0); ccnet_processor_done (processor, FALSE); return; } task->session_token = g_strdup (content); ccnet_processor_send_update (processor, SC_GET_VERSION, SS_GET_VERSION, NULL, 0); } else if (strncmp (code, SC_VERSION, 3) == 0) { int server_version = atoi(content); /* There is a bug in block transfer in version 4, so it's not supported. */ if (server_version == 4) server_version = 3; task->protocol_version = MIN (server_version, CURRENT_PROTO_VERSION); if (task->protocol_version < 5) { seaf_warning ("Deprecated server protocol version %d.\n", task->protocol_version); transfer_task_set_error (task, TASK_ERR_DEPRECATED_SERVER); ccnet_processor_done (processor, FALSE); return; } if (task->repo_version == 0) task->protocol_version = 5; else if (task->protocol_version == 5) { /* Syncing version 1 reop with 2.x server is not supported. * Actually version 1 repo can only be created by 3.x servers. * If version 1 repos exist on 2.x server, it means a down-grade * operation has been performed, which is not supported. */ seaf_warning ("Syncing version %d repo with protocol version %d " "is not supported.\n", task->repo_version, task->protocol_version); transfer_task_set_error (task, TASK_ERR_DEPRECATED_SERVER); ccnet_processor_done (processor, FALSE); return; } if (task->protocol_version >= 7 && !task->server_side_merge) task->protocol_version = 6; if (task->protocol_version >= 7 && task->type == TASK_TYPE_DOWNLOAD) set_download_head_info (task); seaf_message ("repo version is %d, protocol version is %d.\n", task->repo_version, task->protocol_version); ccnet_processor_done (processor, TRUE); } else { seaf_warning ("[check tx v3] Bad response: %s %s", code, code_msg); if (strncmp(code, SC_ACCESS_DENIED, 3) == 0) transfer_task_set_error (task, TASK_ERR_ACCESS_DENIED); else if (strncmp(code, SC_QUOTA_ERROR, 3) == 0) transfer_task_set_error (task, TASK_ERR_CHECK_QUOTA); else if (strncmp(code, SC_QUOTA_FULL, 3) == 0) transfer_task_set_error (task, TASK_ERR_QUOTA_FULL); else if (strncmp(code, SC_PROTOCOL_MISMATCH, 3) == 0) transfer_task_set_error (task, TASK_ERR_PROTOCOL_VERSION); else if (strncmp(code, SC_BAD_REPO, 3) == 0) transfer_task_set_error (task, TASK_ERR_BAD_REPO_ID); else transfer_task_set_error (task, TASK_ERR_UNKNOWN); ccnet_processor_done (processor, FALSE); } }