diff --git a/libretroshare/src/ft/fttransfermodule.cc b/libretroshare/src/ft/fttransfermodule.cc new file mode 100644 index 000000000..8dfd0e07d --- /dev/null +++ b/libretroshare/src/ft/fttransfermodule.cc @@ -0,0 +1,207 @@ +/* + * libretroshare/src/ft: fttransfermodule.cc + * + * File Transfer for RetroShare. + * + * Copyright 2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "fttransfermodule.h" + +const uint32_t PQIPEER_OFFLINE_CHECK = 120; /* check every 2 minutes */ +const uint32_t PQIPEER_DOWNLOAD_TIMEOUT = 60; /* time it out, -> offline after 60 secs */ +const uint32_t PQIPEER_DOWNLOAD_CHECK = 10; /* desired delta = 10 secs */ +const uint32_t PQIPEER_DOWNLOAD_TOO_FAST = 8; /* 8 secs */ +const uint32_t PQIPEER_DOWNLOAD_TOO_SLOW = 12; /* 12 secs */ +const uint32_t PQIPEER_DOWNLOAD_MIN_DELTA = 5; /* 5 secs */ + +ftTransferModule::ftTransferModule(ftFileCreator *fc,ftClientModule *cm) + :mFileCreator(fc),mClientModule(cm),mFlag(0) +{} + +ftTransferModule::~ftTransferModule() +{} + +bool ftTransferModule::setFileSources(std::list peerIds) +{ + std::list::iterator it; + for(it = peerIds.begin(); it != peerIds.end(); it++) + { + mFileSources.push_back(*it); + } + + return 1; +} + +bool ftTransferModule::setPeerState(std::string peerId,uint32_t state,uint32_t maxRate); //state = ONLINE/OFFLINE +{ + bool found = false; + std::list::iterator it; + it = peerIds.begin(); + while (( it != peerIds.end())&&(!found)) + { + if ((*it) == peerId) + found = true; + it++; + } + + if (!found) mFileSources.push_back(*it); + + std::map::iterator mit; + mit = mOnlinePeers.find(peerId); + if (mit == map::end) + { + peerInfo pInfo; + pInfo.state = state; + pInfo.desiredRate = maxRate; + mOnlinePeers.insert(pair(peerId,pInfo)); + } + else + { + (mit->second).state = state; + (mit->second).desiredRate = maxRate; + } + + return 1; +} + +uint32_t ftTransferModule::getDataRate(std::string peerId) +{ + std::map::iterator mit; + mit = mOnlinePeers.find(peerId); + if (mit == map::end) + return 0; + else + return (mit->second).actualRate; +} + +void ftTransferModule::requestData(uint64_t offset, uint32_t chunk_size) +{ + mClientModule->requestData(mHash,offset,chunk_size); +} + +bool ftTransferModule::getChunk(uint64_t &offset, uint32_t &chunk_size) +{ + mFileCreator->getMissingChunk(offset, chunk_size); +} + +bool ftTransferModule::storeData(uint64_t offset, uint32_t chunk_size,void *data) +{ + mFileCreator->storeData(offset, chunk_size, data); +} + +void ftTransferModule::queryInactive() +{ +#ifdef FT_DEBUG + std::ostringstream out; + out<<"ftTransferModule::queryInactive()"; + out<::iterator mit; + for(mit = mOnlinePeers.begin(); mit != mOnlinePeers.end(); mit++) + { + switch ((mit->second).state) + { + //Peer side has change from online to offline during transfer + case PQIPEER_NOT_ONLINE: + if (ts - ((mit->second).lastTS) > PQIPEER_OFFLINE_CHECK) + {//start to request data + getChunk(mOffset,mChunkSize); + if (mChunkSize != 0) + { + (mit->second).req_loc = mOffset; + (mit->second).req_size = mChunkSize; + (mit->second).lastTS = ts; + (mit->second).state = PQIPEER_DOWNLOADING; + requestData(mOffset,mChunkSize); + } + else mFlag = 1; + } + break; + + //file request has been sent to peer side, but no response received yet + case PQIPEER_DOWNLOADING: + if (ts - ((mit->second).lastTS) > PQIPEER_DOWNLOAD_CHECK) + requestData((mit->second).req_loc,(mit->second).req_size); //give a push + break; + + //file response has been received or peer side is just ready for download + case PQIPEER_IDLE: + getChunk(mOffset,mChunkSize); + if (mChunkSize != 0) + { + (mit->second).req_loc = mOffset; + (mit->second).req_size = mChunkSize; + (mit->second).lastTS = ts; + (mit->second).state = PQIPEER_DOWNLOADING; + requestData(mOffset,mChunkSize); + } + else mFlag = 1; + break; + + //file transfer has been stopped + case PQIPEER_SUSPEND: + break; + + default: + break; + }//switch + }//for + +} + +bool ftTransferModule::stopTransfer() +{ + std::map::iterator mit; + for(mit = mOnlinePeers.begin(); mit != mOnlinePeers.end(); mit++) + { + (mit->second).state = PQIPEER_SUSPEND; + } + + return 1; +} + +bool ftTransferModule::resumeTransfer() +{ + std::map::iterator mit; + for(mit = mOnlinePeers.begin(); mit != mOnlinePeers.end(); mit++) + { + (mit->second).state = PQIPEER_IDLE; + } + + return 1; +} + +void ftTransferModule::completeFileTransfer() +{ +} + +int ftTransferModule::tick() +{ + queryInactive(); + if (mFlag != 1) adjustSpeed(); + else + completeFileTransfer(); + + return 0; +}