Example #1
0
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);
	}
}