예제 #1
0
void CFileConn::_HandleClientFilePullFileReq(CImPdu *pPdu)
{
    if (!_IsAuth()) {
		return;
	}
    
    IM::File::IMFilePullDataReq 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 mode = msg.trans_mode();
	uint32_t offset = msg.offset();
	uint32_t datasize = msg.data_size();
    
    IM::File::IMFilePullDataRsp msg2;
    msg2.set_result_code(1);
    msg2.set_task_id(task_id);
    msg2.set_user_id(user_id);
    msg2.set_offset(offset);
    msg2.set_data("");
    CImPdu pdu;
    pdu.SetPBMsg(&msg2);
    pdu.SetServiceId(SID_FILE);
    pdu.SetCommandId(CID_FILE_PULL_DATA_RSP);
    pdu.SetSeqNum(pPdu->GetSeqNum());
    // since the task had been created when the recver logged-in
    // we can find task in g_file_task_map here
    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);
        log("invalid task id %s ", task_id.c_str());
        SendPdu(&pdu);
        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 /*for the realtime recver*/ && t->to_user_id != user_id /*for the offline download*/) {
        // invalid user
        log("illieage user %d for task %s", user_id, task_id.c_str());
        SendPdu(&pdu);
        
        t->unlock(__LINE__);
        return;
    }
    
    switch (mode) {
        case IM::BaseDefine::FILE_TYPE_ONLINE: // transfer request to sender
        {
            CFileConn* pConn = (CFileConn*)t->GetOpponentConn(user_id);
            pConn->SendPdu(pPdu);
            break;
        }
        case IM::BaseDefine::FILE_TYPE_OFFLINE: // for the offline download
        {
            // find file use task id
            // send header info to user
            // send data
            // save path manager not used
            
            // save transfered info into task
            // like FILE*
            // transfered size
            
            
            // haven't been opened
            size_t size = 0;
            if (NULL == t->fp) {
                char save_path[BUFSIZ] = {0};
                snprintf(save_path, BUFSIZ, "%s/%d", g_current_save_path, user_id); // those who can only get files under their user_id-dir
                
                int ret = mkdir(save_path, 0755);
                if ( (ret != 0) && (errno != EEXIST) ) {
                    log("mkdir failed for path: %s", save_path);
                    SendPdu(&pdu);
                    t->unlock(__LINE__);
                    return;
                }
                
                strncat(save_path, "/", BUFSIZ);
                strncat(save_path, task_id.c_str(), BUFSIZ); // use task_id as file name, in case of same-name file
                
                // open at first time
                t->fp = fopen(save_path, "rb");  // save fp
                if (!t->fp) {
                    log("can not open file");
                    SendPdu(&pdu);
                    
                    t->unlock(__LINE__);
                    return;
                }
                
                // read head at open
                if (NULL == t->file_head) {
                    t->file_head = new file_header_t;
                    if (NULL == t->file_head) {
                        // close to ensure next time will new file-header again
                        log("read file head failed.");

                        fclose(t->fp);
                        SendPdu(&pdu);
                        
                        t->unlock(__LINE__);
                        return;
                    }
                }
                
                size = fread(t->file_head, 1, sizeof(file_header_t), t->fp); // read header
                if (sizeof(file_header_t) > size) {
                    // close to ensure next time will read again
                    log("read file head failed.");
                    fclose(t->fp); // error to get header
                    SendPdu(&pdu);
                    
                    t->unlock(__LINE__);
                    return;
                } // the header won't be sent to recver, because the msg svr had already notified it.
                // if the recver needs to check it, it could be helpful
                // or sometime later, the recver needs it in some way.
            }
            
            // read data and send based on offset and datasize.
            char* tmpbuf = new char[datasize];
            if (NULL == tmpbuf) {
                // alloc mem failed
                log("alloc mem failed.");
                SendPdu(&pdu);
                t->unlock(__LINE__);
                return;
            }
            memset(tmpbuf, 0, datasize);
            
            // offset file_header_t
            int iret = fseek(t->fp, sizeof(file_header_t) + offset, SEEK_SET); // read after file_header_t
            if (0 != iret) {
                log("seek offset failed.");
                SendPdu(&pdu);
                delete[] tmpbuf;
                
                t->unlock(__LINE__);
                return;
                // offset failed
            }
            size = fread(tmpbuf, 1, datasize, t->fp);
            msg2.set_data(tmpbuf, size);
            CImPdu pdu2;
            pdu2.SetPBMsg(&msg2);
            pdu2.SetServiceId(SID_FILE);
            pdu2.SetCommandId(CID_FILE_PULL_DATA_RSP);
            pdu2.SetSeqNum(pPdu->GetSeqNum());
            pdu2.SetSeqNum(pPdu->GetSeqNum());
            SendPdu(&pdu2);
            delete[] tmpbuf;
            
            t->transfered_size += size; // record transfered size for next time offset
            if (0 == size) {
                fclose(t->fp);
                t->fp = NULL;
                
                _StatesNotify(CLIENT_FILE_DONE, task_id.c_str(), user_id, this);
                Close();
                
                t->self_destroy = true;
                t->unlock(__LINE__);
                return;
            }
            
            break;
        }
        default:
            break;
    }
  
    t->unlock(__LINE__);
    return;
}
예제 #2
0
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);
	}
}
예제 #3
0
/// yunfan add 2014.8.7
/// offline file upload
/// file-svr will send pull-data-req to sender
/// then wait for sender's rsp
void* _DoUpload(void* lparam)
{
    if (NULL == lparam) {
        return NULL;
    }
    transfer_task_t* t = reinterpret_cast<transfer_task_t*>(lparam);
    
    t->create_time = time(NULL);
    
    // at begin
    // send 10 data-pull-req
    for (uint32_t cnt = 0; cnt < 1; ++cnt) {
        std::map<uint32_t, upload_package_t*>::iterator iter = t->upload_packages.begin();
        if (t->upload_packages.end() != iter) {
            IM::File::IMFilePullDataReq msg;
            msg.set_task_id(t->task_id);
            msg.set_user_id(t->from_user_id);
            msg.set_trans_mode(::IM::BaseDefine::FILE_TYPE_OFFLINE);
            msg.set_offset(iter->second->offset);
            msg.set_data_size(iter->second->size);
            CImPdu pdu;
            pdu.SetPBMsg(&msg);
            pdu.SetServiceId(SID_FILE);
            pdu.SetCommandId(CID_FILE_PULL_DATA_REQ);
            CFileConn* pConn = (CFileConn*)t->GetConn(t->from_user_id);
            pConn->SendPdu(&pdu);
            log("Pull Data Req");
        }
        ++iter;
    }
    
    // what if there is no rsp?
    // still send req?
    // no!
    // at last, the user will cancel
    // next ver, do change
    while (t->transfered_size != t->upload_packages.size()) {
        if (t->self_destroy) {
        	log("timeout, exit thread, task %s", t->task_id.c_str());
        	return NULL;
        }
        sleep(1);
    }
    

    t->lock(__LINE__);
    
    // write head
    if (NULL == t->file_head) {
        t->file_head = new file_header_t;
    }
    if (NULL == t->file_head) {
        log("create file header failed %s", t->task_id.c_str());
        // beacuse all data in mem
        // it has to be released
        
        /*
        UserMap_t::iterator ator = g_file_user_map.find(t->from_user_id);
        if (g_file_user_map.end() != ator) {
            CFileConn* pConn = (CFileConn*)ator->second;
            pConn->Close();
        }
         */
        CFileConn* pConn = (CFileConn*)t->GetConn(t->from_user_id);
        pConn->Close();
        
        t->self_destroy = true;
        t->unlock(__LINE__);
        return NULL;
        
    }
    t->file_head->set_create_time(time(NULL));
    t->file_head->set_task_id(t->task_id.c_str());
    t->file_head->set_from_user_id(t->from_user_id);
    t->file_head->set_to_user_id(t->to_user_id);
    t->file_head->set_file_name("");
    t->file_head->set_file_size(t->file_size);
    fwrite(t->file_head, 1, sizeof(file_header_t), t->fp);
    
    std::map<uint32_t, upload_package_t*>::iterator itor = t->upload_packages.begin();
    for ( ; itor != t->upload_packages.end(); ++itor) {
        fwrite(itor->second->data, 1, itor->second->size, t->fp);
    }
    
    fflush(t->fp);
    if (t->fp) {
    	fclose(t->fp);
        t->fp = NULL;
    }

    t->unlock(__LINE__);
    return NULL;
}
예제 #4
0
void FileTransferSocket::_filePullDataReqResponse(IN std::string& body)//发
{
	IM::File::IMFilePullDataReq imFilePullDataReq;
    if (!imFilePullDataReq.ParseFromString(body))
    {
        LOG__(ERR, _T("parse failed,body:%s"), util::stringToCString(body));
        return;
    }
	UInt32 fileSize = imFilePullDataReq.data_size();
	UInt32 fileOffset = imFilePullDataReq.offset();
	std::string taskId = imFilePullDataReq.task_id();
	
	TransferFileEntity fileEntity;
	if (!TransferFileEntityManager::getInstance()->getFileInfoByTaskId(taskId, fileEntity))
	{
		LOG__(ERR, _T("PullDataReqResponse: can't find the fileInfo"));
		return;
	}
	LOG__(DEBG, _T("send:taskId=%s,filesize=%d,name=%s,BolckSize=%d")
		,util::stringToCString(fileEntity.sTaskID)
		,fileEntity.nFileSize
		,fileEntity.getRealFileName()
        ,fileSize);
	std::string buff;
	if (nullptr == fileEntity.pFileObject)
	{
		LOG__(ERR, _T("PullDataReqResponse: file boject Destoryed!"));
		return;
	}
	fileEntity.pFileObject->readBlock(fileOffset, fileSize, buff);//读取本地文件的数据块
	IM::File::IMFilePullDataRsp imFilePullDataRsp;//todo check
    imFilePullDataRsp.set_result_code(0);
	imFilePullDataRsp.set_task_id(taskId);
	imFilePullDataRsp.set_user_id(util::stringToInt32(fileEntity.sFromID));
	imFilePullDataRsp.set_offset(fileOffset);
    imFilePullDataRsp.set_file_data((void*)buff.data(), fileSize);

    //send packet
    sendPacket(IM::BaseDefine::ServiceID::SID_FILE, IM::BaseDefine::FileCmdID::CID_FILE_PULL_DATA_RSP
        , &imFilePullDataRsp);

	fileEntity.nProgress = fileOffset + fileSize;
	if (fileEntity.nProgress < fileEntity.nFileSize)
	{
		//更新进度条
		TransferFileEntityManager::getInstance()->updateFileInfoBysTaskID(fileEntity);//保存当前进度
		module::getFileTransferModule()->asynNotifyObserver(module::KEY_FILESEVER_UPDATA_PROGRESSBAR
            , fileEntity.sTaskID);
	}
	else//传输完成
	{
		if (fileEntity.pFileObject)
		{
			delete fileEntity.pFileObject;
			fileEntity.pFileObject = nullptr;
		}
		module::getFileTransferModule()->asynNotifyObserver(module::KEY_FILESEVER_PROGRESSBAR_FINISHED
            , fileEntity.sTaskID);
	}
	TransferFileEntityManager::getInstance()->updateFileInfoBysTaskID(fileEntity);
}