void CFileConn::_HandleClientFilePullFileRsp(CImPdu *pPdu) { if (!_IsAuth()) { return; } IM::File::IMFilePullDataRsp msg; CHECK_PB_PARSE_MSG(msg.ParseFromArray(pPdu->GetBodyData(), pPdu->GetBodyLength())); uint32_t user_id = msg.user_id(); string task_id = msg.task_id(); uint32_t offset = msg.offset(); uint32_t data_size = msg.data().length(); pthread_rwlock_wrlock(&g_file_task_map_lock); TaskMap_t::iterator iter = g_file_task_map.find(task_id.c_str()); if (g_file_task_map.end() == iter) { // invalid task id pthread_rwlock_unlock(&g_file_task_map_lock); return; } transfer_task_t* t = iter->second; pthread_rwlock_unlock(&g_file_task_map_lock); t->lock(__LINE__); t->create_time = time(NULL); if (t->from_user_id != user_id && t->to_user_id != user_id) { // invalid user t->unlock(__LINE__); return; } switch (t->transfer_mode) { case FILE_TYPE_ONLINE: // transfer request to sender { CFileConn* pConn = (CFileConn*)t->GetOpponentConn(user_id); pConn->SendPdu(pPdu); /// send to recver break; } case FILE_TYPE_OFFLINE: /// this is the response to the server pull-data-req { if (t->upload_packages.size() <= 0) { log("FATAL ERROR"); t->unlock(__LINE__); return; } // check if data size ok std::map<uint32_t, upload_package_t*>::iterator itPacks = t->upload_packages.find(offset); if (t->upload_packages.end() != itPacks) { // offset right // check if data size ok if (data_size != itPacks->second->size) { // the rsp's data size is different from req's // refuse it or dynamic adjust // do not adjust now, maybe later uint32_t offset = itPacks->second->offset; uint32_t size = itPacks->second->size; // resend req IM::File::IMFilePullDataReq msg2; msg2.set_task_id(task_id); msg2.set_user_id(user_id); msg2.set_trans_mode((::IM::BaseDefine::FileType)t->transfer_mode); msg2.set_offset(offset); msg2.set_data_size(size); CImPdu pdu; pdu.SetPBMsg(&msg2); pdu.SetServiceId(SID_FILE); pdu.SetCommandId(CID_FILE_PULL_DATA_REQ); SendPdu(&pdu); log("size not match"); t->unlock(__LINE__); return; } // check if data-ptr OK if (NULL == itPacks->second->data) { itPacks->second->data = new char[itPacks->second->size]; if (NULL == itPacks->second->data) { uint32_t offset = itPacks->second->offset; uint32_t size = itPacks->second->size; log("alloc mem failed"); // resend req IM::File::IMFilePullDataReq msg2; msg2.set_task_id(task_id); msg2.set_user_id(user_id); msg2.set_trans_mode((::IM::BaseDefine::FileType)t->transfer_mode); msg2.set_offset(offset); msg2.set_data_size(size); CImPdu pdu; pdu.SetPBMsg(&msg2); pdu.SetServiceId(SID_FILE); pdu.SetCommandId(CID_FILE_PULL_DATA_REQ); SendPdu(&pdu); t->unlock(__LINE__); return; } } // copy data memset(itPacks->second->data, 0, itPacks->second->size); memcpy(itPacks->second->data, msg.data().c_str(), msg.data().length()); ++t->transfered_size; } // find which segment hasn't got data yet bool bFound = false; std::map<uint32_t, upload_package_t*>::iterator itor = t->upload_packages.begin(); for ( ; itor != t->upload_packages.end(); ++itor) { if (NULL == itor->second->data) { bFound = true; break; } } if (!bFound) { // all packages recved _StatesNotify(IM::BaseDefine::CLIENT_FILE_DONE, task_id.c_str(), user_id, t->GetConn(user_id)); Close(); t->unlock(__LINE__); return; } // prepare to send req for this segment uint32_t next_offset = itor->second->offset; uint32_t next_size = itor->second->size; // send pull-data-req IM::File::IMFilePullDataReq msg2; msg2.set_task_id(task_id); msg2.set_user_id(user_id); msg2.set_trans_mode((::IM::BaseDefine::FileType)t->transfer_mode); msg2.set_offset(next_offset); msg2.set_data_size(next_size); CImPdu pdu; pdu.SetPBMsg(&msg2); pdu.SetServiceId(SID_FILE); pdu.SetCommandId(CID_FILE_PULL_DATA_REQ); SendPdu(&pdu); break; } default: break; } t->unlock(__LINE__); return; }
void FileTransferSocket::_filePullDataRspResponse(IN std::string& body)//收 { IM::File::IMFilePullDataRsp imFilePullDataRsp; if (!imFilePullDataRsp.ParseFromString(body)) { LOG__(ERR, _T("parse failed,body:%s"), util::stringToCString(body)); return; } UInt32 nRes = imFilePullDataRsp.result_code(); if (0 != nRes) { LOG__(ERR, _T("PullDataRspResponse: error result:%d"),nRes); return; } std::string taskId = imFilePullDataRsp.task_id(); const std::string& strData = imFilePullDataRsp.file_data();//todo ?????要长度 void* pData = (void*)(strData.data()); UInt32 nBlockSize = strData.size(); UInt32 fileOffset = imFilePullDataRsp.offset(); TransferFileEntity fileEntity; if (!TransferFileEntityManager::getInstance()->getFileInfoByTaskId(taskId, fileEntity)) { LOG__(ERR, _T("can't find the fileInfo")); return; } LOG__(DEBG, _T("receive:taskId=%s,filesize=%d,name=%s,BolckSize=%d") , util::stringToCString(fileEntity.sTaskID) , fileEntity.nFileSize , fileEntity.getRealFileName() , nBlockSize); //存文件... if (!fileEntity.pFileObject->writeBlock(fileOffset, nBlockSize, pData)) { LOG__(DEBG, _T("writeBlock failed ")); return; } fileEntity.nProgress = fileOffset + nBlockSize; if (fileEntity.nProgress < fileEntity.nFileSize) { //更新进度条 TransferFileEntityManager::getInstance()->updateFileInfoBysTaskID(fileEntity);//保存当前进度 module::getFileTransferModule()->asynNotifyObserver(module::KEY_FILESEVER_UPDATA_PROGRESSBAR , fileEntity.sTaskID); //继续发file block req... int mode = fileEntity.nClientMode == IM::BaseDefine::ClientFileRole::CLIENT_OFFLINE_DOWNLOAD ? IM::BaseDefine::TransferFileType::FILE_TYPE_OFFLINE : IM::BaseDefine::TransferFileType::FILE_TYPE_ONLINE; IM::File::IMFilePullDataReq imFilePullDataReq; imFilePullDataReq.set_task_id(taskId); imFilePullDataReq.set_user_id(util::stringToInt32(fileEntity.sToID)); imFilePullDataReq.set_trans_mode(static_cast<IM::BaseDefine::TransferFileType>(mode)); imFilePullDataReq.set_offset(fileEntity.nProgress); UInt32 pullSize = fileEntity.nFileSize - fileEntity.nProgress; pullSize > nBlockSize ? imFilePullDataReq.set_data_size(nBlockSize) : imFilePullDataReq.set_data_size(pullSize); // 发包 sendPacket(IM::BaseDefine::ServiceID::SID_FILE, IM::BaseDefine::FileCmdID::CID_FILE_PULL_DATA_REQ, &imFilePullDataReq); } else//传输完成 { if (fileEntity.pFileObject) { delete fileEntity.pFileObject; fileEntity.pFileObject = nullptr; } //告知对方文件传输完成了。 IM::File::IMFileState imFileState; imFileState.set_state(IM::BaseDefine::ClientFileState::CLIENT_FILE_DONE); imFileState.set_task_id(taskId); imFileState.set_user_id(util::stringToInt32(fileEntity.sToID)); sendPacket(IM::BaseDefine::ServiceID::SID_FILE, IM::BaseDefine::FileCmdID::CID_FILE_STATE, &imFileState); TransferFileEntityManager::getInstance()->updateFileInfoBysTaskID(fileEntity); module::getFileTransferModule()->asynNotifyObserver(module::KEY_FILESEVER_PROGRESSBAR_FINISHED, fileEntity.sTaskID); } }