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_send_update (processor, SC_BAD_ARGS, SS_BAD_ARGS, NULL, 0); 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 ccnet_processor_keep_alive_response (CcnetProcessor *processor) { if (IS_SLAVE (processor)) ccnet_processor_send_response (processor, SC_PROC_ALIVE, SS_PROC_ALIVE, NULL, 0); else ccnet_processor_send_update (processor, SC_PROC_ALIVE, SS_PROC_ALIVE, NULL, 0); }
static void handle_update (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { /* ccnet_debug ("[Svc Stub] %d handle update: %s %s\n", */ /* PRINT_ID(processor->id), code, code_msg); */ ccnet_processor_send_update (processor, code, code_msg, content, clen); }
void ccnet_processor_keep_alive (CcnetProcessor *processor) { if (IS_SLAVE (processor)) ccnet_processor_send_response (processor, SC_PROC_KEEPALIVE, SS_PROC_KEEPALIVE, NULL, 0); else ccnet_processor_send_update (processor, SC_PROC_KEEPALIVE, SS_PROC_KEEPALIVE, NULL, 0); processor->t_keepalive_sent = time (NULL); }
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 send_commits (CcnetProcessor *processor, const char *head) { TransferTask *task = ((SeafileSendcommitV2Proc *)processor)->tx_task; gboolean ret; ret = seaf_commit_manager_traverse_commit_tree (seaf->commit_mgr, task->repo_id, task->repo_version, head, traverse_commit, processor, FALSE); if (!ret) { ccnet_processor_send_update (processor, SC_NOT_FOUND, SS_NOT_FOUND, NULL, 0); ccnet_processor_done (processor, FALSE); } ccnet_processor_send_update (processor, SC_END, SS_END, NULL, 0); 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); } }
inline static void request_object_batch_flush (CcnetProcessor *processor, SeafileGetcommitProcPriv *priv) { if (priv->bufptr == priv->buf) return; *priv->bufptr = '\0'; /* add ending '\0' */ priv->bufptr++; ccnet_processor_send_update (processor, SC_GET_OBJECT, SS_GET_OBJECT, priv->buf, priv->bufptr - priv->buf); g_debug ("[getcommit] Request more objects:\n%s", priv->buf); }
static void send_object_list_segment (CcnetProcessor *processor) { USE_PRIV; char buf[OBJECT_LIST_SEGMENT_LEN]; if (priv->needed_objs == NULL) { seaf_debug ("All objects saved. Done.\n"); ccnet_processor_send_update (processor, SC_END, SS_END, NULL, 0); ccnet_processor_done (processor, TRUE); return; } priv->n_pending = 0; priv->n_saved = 0; int i = 0; char *p = buf; char *obj_id; while (priv->needed_objs != NULL) { obj_id = priv->needed_objs->data; priv->needed_objs = g_list_delete_link (priv->needed_objs, priv->needed_objs); memcpy (p, obj_id, 40); p += 40; g_free (obj_id); if (++i == OBJECT_LIST_SEGMENT_N) break; } if (i > 0) { seaf_debug ("Send %d object ids.\n", i); priv->n_pending = i; ccnet_processor_send_update (processor, SC_OBJ_LIST_SEG, SS_OBJ_LIST_SEG, buf, i * 40); } }
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 handle_response (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { SeafileCheckTxV2Proc *proc = (SeafileCheckTxV2Proc *)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_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 v2] 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 compute_upload_commits_done (void *vdata) { CcnetProcessor *processor = vdata; USE_PRIV; if (!priv->compute_success) { ccnet_processor_send_update (processor, SC_NOT_FOUND, SS_NOT_FOUND, NULL, 0); ccnet_processor_done (processor, FALSE); return; } send_one_commit (processor); }
inline static void request_object_batch_flush (CcnetProcessor *processor, SeafileGetfsProcPriv *priv) { if (priv->bufptr == priv->buf) return; *priv->bufptr = '\0'; /* add ending '\0' */ priv->bufptr++; ccnet_processor_send_update (processor, SC_GET_OBJECT, SS_GET_OBJECT, priv->buf, priv->bufptr - priv->buf); /* Clean state */ priv->n_batch = 0; priv->bufptr = priv->buf; }
static void send_challenge_user(CcnetProcessor *processor, CcnetUser *user) { CcnetKeepaliveProcPriv *priv = GET_PRIV (processor); unsigned char *buf; int len; ccnet_debug ("[Keepalive] Send user challenge to %.8s\n", processor->peer->id); RAND_pseudo_bytes (priv->random_buf, 40); buf = public_key_encrypt (user->pubkey, priv->random_buf, 40, &len); ccnet_processor_send_update (processor, "321", NULL, (char *)buf, len); g_free(buf); processor->state = WAIT_CHALLENGE_USER; reset_timeout (processor); }
static int check_object (CcnetProcessor *processor) { USE_PRIV; char *obj_id; SeafDir *dir; static int i = 0; request_object_batch_begin(priv); /* process inspect queue */ /* Note: All files in a directory must be checked in an iteration, * so we may send out more items than REQUEST_THRESHOLD */ while (g_hash_table_size (priv->fs_objects) < MAX_NUM_UNREVD) { obj_id = (char *) g_queue_pop_head (priv->inspect_queue); if (obj_id == NULL) break; if (!seaf_fs_manager_object_exists(seaf->fs_mgr, obj_id)) { request_object_batch (processor, priv, obj_id); } else { dir = seaf_fs_manager_get_seafdir (seaf->fs_mgr, obj_id); if (!dir) { /* corrupt dir object */ request_object_batch (processor, priv, obj_id); } else { check_seafdir(processor, dir); seaf_dir_free (dir); } } g_free (obj_id); /* free the memory */ } request_object_batch_flush (processor, priv); /* check end condition */ if (i%10 == 0) seaf_debug ("[getfs] pending objects num: %d\n", priv->pending_objects); ++i; if (priv->pending_objects == 0 && g_queue_is_empty(priv->inspect_queue)) { ccnet_processor_send_update (processor, SC_END, SS_END, NULL, 0); ccnet_processor_done (processor, TRUE); return FALSE; } else return TRUE; }
static void send_commits (CcnetProcessor *processor, const char *head) { gboolean ret; ret = seaf_commit_manager_traverse_commit_tree (seaf->commit_mgr, head, traverse_commit, processor); if (!ret) { ccnet_processor_send_update (processor, SC_NOT_FOUND, SS_NOT_FOUND, NULL, 0); ccnet_processor_done (processor, FALSE); return; } send_one_commit (processor); }
static void on_fs_write (OSAsyncResult *res, void *cb_data) { CcnetProcessor *processor = cb_data; USE_PRIV; if (!res->success) { seaf_warning ("[getfs] Failed to write %s.\n", res->obj_id); ccnet_processor_send_update (processor, SC_BAD_OBJECT, SS_BAD_OBJECT, NULL, 0); ccnet_processor_done (processor, FALSE); return; } seaf_debug ("[getfs] Wrote fs object %s.\n", res->obj_id); if (++(priv->n_saved) == priv->n_pending) send_object_list_segment (processor); }
void ccnet_processor_handle_response (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { g_return_if_fail (CCNET_PROCESSOR_GET_CLASS(processor)->handle_response != NULL); g_object_ref (processor); processor->is_active = TRUE; if (code[0] == '5') { ccnet_warning ("[Proc] Shutdown processor %s(%d) for bad response: %s %s from %s\n", GET_PNAME(processor), PRINT_ID(processor->id), code, code_msg, processor->peer_id); if (memcmp(code, SC_UNKNOWN_SERVICE, 3) == 0) processor->failure = PROC_NO_SERVICE; else if (memcmp(code, SC_PERM_ERR, 3) == 0) processor->failure = PROC_PERM_ERR; else if (memcmp(code, SC_NETDOWN, 3) == 0) processor->failure = PROC_REMOTE_DEAD; else processor->failure = PROC_BAD_RESP; ccnet_processor_done (processor, FALSE); return; } if (strncmp (code, SC_PROC_KEEPALIVE, 3) == 0) { ccnet_processor_send_update (processor, SC_PROC_ALIVE, SS_PROC_ALIVE, NULL, 0); } else if (strncmp (code, SC_PROC_DEAD, 3) == 0) { g_warning ("[proc] Shutdown processor %s(%d) when peer(%.8s) processor is dead\n", GET_PNAME(processor), PRINT_ID(processor->id), processor->peer_id); processor->failure = PROC_REMOTE_DEAD; ccnet_processor_done (processor, FALSE); } else { CCNET_PROCESSOR_GET_CLASS (processor)->handle_response (processor, code, code_msg, content, clen); } processor->is_active = FALSE; g_object_unref (processor); }
static void send_one_commit (CcnetProcessor *processor) { USE_PRIV; char *commit_id; if (!priv->id_list) { ccnet_processor_send_update (processor, SC_END, SS_END, NULL, 0); ccnet_processor_done (processor, TRUE); return; } commit_id = priv->id_list->data; priv->id_list = g_list_delete_link (priv->id_list, priv->id_list); send_commit (processor, commit_id); g_free (commit_id); }
void ccnet_processor_done (CcnetProcessor *processor, gboolean success) { if (processor->thread_running) { processor->delay_shutdown = TRUE; processor->was_success = success; return; } if (processor->state == STATE_IN_SHUTDOWN) { return; } processor->state = STATE_IN_SHUTDOWN; if (processor->failure == PROC_NOTSET) processor->failure = PROC_DONE; if (!processor->peer->is_local) ccnet_debug ("Processsor %s(%d) done %d\n", GET_PNAME(processor), PRINT_ID(processor->id), success); if (!processor->detached && success) { if (!IS_SLAVE (processor)) { ccnet_processor_send_update (processor, SC_PROC_DONE, SS_PROC_DONE, NULL, 0); } } /* When we emit the done signal, the corresponding handler may * shutdown the peer, we should remove this processor from the * peers processor list, otherwise this processor will be freed * twice. */ g_signal_emit (processor, signals[DONE_SIG], 0, success); if (!processor->detached) { ccnet_peer_remove_processor (processor->peer, processor); } ccnet_processor_release_resource (processor); ccnet_proc_factory_recycle (processor->session->proc_factory, processor); }
int seafile_getblock_v2_proc_get_block (SeafileGetblockV2Proc *proc, int block_idx) { CcnetProcessor *processor = (CcnetProcessor *)proc; char *block_id; char buf[128]; int len; ++(proc->pending_blocks); BitfieldAdd (&proc->active, block_idx); block_id = g_ptr_array_index (proc->tx_task->block_list->block_ids, block_idx); len = snprintf (buf, 128, "%d %s", block_idx, block_id); ccnet_processor_send_update (processor, SC_GET_BLOCK, SS_GET_BLOCK, buf, len + 1); return 0; }
static void handle_response (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { if (code[0] == '4' || code[0] == '5') { ccnet_warning ("[Keepalive] Error from peer %s %s\n", code, code_msg); close_processor (processor); return; } struct Handler *handler = get_handler(code, rsp_handler_tab); if (!handler) { ccnet_processor_send_update (processor, SC_BAD_RESPONSE_CODE, SS_BAD_RESPONSE_CODE, NULL, 0); close_processor (processor); return; } handler->handler(processor, code, code_msg, content, clen); }
static int recv_fs_object (CcnetProcessor *processor, char *content, int clen) { ObjectPack *pack = (ObjectPack *)content; /* SeafFSObject *fs_obj = NULL; */ if (clen < sizeof(ObjectPack)) { seaf_warning ("invalid object id.\n"); goto bad; } seaf_debug ("[getfs] Recv fs object %.8s.\n", pack->id); /* Check object integrity by parsing it. */ /* fs_obj = seaf_fs_object_from_data(pack->id, */ /* pack->object, clen - sizeof(ObjectPack), */ /* (priv->repo_version > 0)); */ /* if (!fs_obj) { */ /* seaf_warning ("Bad fs object %s.\n", pack->id); */ /* goto bad; */ /* } */ /* seaf_fs_object_free (fs_obj); */ if (save_fs_object (processor, pack, clen) < 0) { goto bad; } return 0; bad: ccnet_processor_send_update (processor, SC_BAD_OBJECT, SS_BAD_OBJECT, NULL, 0); seaf_warning ("[getfs] Bad fs object received.\n"); ccnet_processor_done (processor, FALSE); /* seaf_fs_object_free (fs_obj); */ return -1; }
static void handle_response (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { SeafileSendcommitProc *proc = (SeafileSendcommitProc *)processor; TransferTask *task = proc->tx_task; if (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 (memcmp (code, SC_OK, 3) == 0) send_commit_ids (processor); else { seaf_warning ("Bad response: %s %s.\n", code, code_msg); ccnet_processor_done (processor, FALSE); } break; case SEND_OBJECT: if (strncmp(code, SC_GET_OBJECT, 3) == 0) { send_commits (processor, content, clen); } else if (strncmp(code, SC_END, 3) == 0) { ccnet_processor_done (processor, TRUE); } else { seaf_warning ("[sendcommit] Bad response in state SEND_OBJECT: %s %s\n", code, code_msg); ccnet_processor_done (processor, FALSE); } break; default: g_return_if_reached (); } }
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 send_commits (CcnetProcessor *processor, char *content, int clen) { char *object_id; int n_objects; int i; if (clen % 41 != 1 || content[clen-1] != '\0') { seaf_warning ("Bad fs object list.\n"); ccnet_processor_send_update (processor, SC_BAD_OL, SS_BAD_OL, NULL, 0); ccnet_processor_done (processor, FALSE); return; } n_objects = clen/41; object_id = content; for (i = 0; i < n_objects; ++i) { object_id[40] = '\0'; if (send_commit (processor, object_id) == FALSE) return; object_id += 41; } }
static void handle_response (CcnetProcessor *processor, char *code, char *code_msg, char *content, int clen) { switch (processor->state) { case INIT: if (strncmp (code, SC_OK, 3) == 0) processor->state = CHECK_OBJECT_LIST; else { seaf_warning ("Bad response: %s %s\n", code, code_msg); ccnet_processor_done (processor, FALSE); } break; case CHECK_OBJECT_LIST: if (strncmp (code, SC_OBJ_LIST_SEG, 3) == 0) { if (clen % 40 != 0) { seaf_warning ("Invalid object list segment length %d.\n", clen); ccnet_processor_send_update (processor, SC_SHUTDOWN, SS_SHUTDOWN, NULL, 0); ccnet_processor_done (processor, FALSE); return; } process_recv_object_list (processor, content, clen); } else if (strncmp (code, SC_OBJ_LIST_SEG_END, 3) == 0) { ccnet_processor_thread_create (processor, seaf->job_mgr, calculate_needed_object_list, calculate_needed_object_list_done, processor); } else if (strncmp (code, SC_END, 3) == 0) { /* The server finds nothing to put. */ ccnet_processor_done (processor, TRUE); } else { seaf_warning ("Bad response: %s %s\n", code, code_msg); ccnet_processor_send_update (processor, SC_BAD_RESPONSE_CODE, SS_BAD_RESPONSE_CODE, NULL, 0); ccnet_processor_done (processor, FALSE); } break; case GET_OBJECTS: if (strncmp(code, SC_OBJ_SEG, 3) == 0) { recv_fs_object_seg (processor, content, clen); } else if (strncmp(code, SC_OBJ_SEG_END, 3) == 0) { recv_fs_object_seg (processor, content, clen); process_fs_object_seg (processor); } else if (strncmp(code, SC_OBJECT, 3) == 0) { recv_fs_object (processor, content, clen); } else { seaf_warning ("Bad response: %s %s\n", code, code_msg); ccnet_processor_send_update (processor, SC_BAD_RESPONSE_CODE, SS_BAD_RESPONSE_CODE, NULL, 0); ccnet_processor_done (processor, FALSE); } break; default: g_return_if_reached (); } }
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); } }