From: <arn...@us...> - 2006-10-06 21:19:07
|
Revision: 663 http://svn.sourceforge.net/dcplusplus/?rev=663&view=rev Author: arnetheduck Date: 2006-10-06 14:18:32 -0700 (Fri, 06 Oct 2006) Log Message: ----------- Janitory Modified Paths: -------------- dcplusplus/trunk/Compile.txt dcplusplus/trunk/Example.xml dcplusplus/trunk/changelog.txt dcplusplus/trunk/client/DownloadManager.cpp dcplusplus/trunk/client/DownloadManager.h dcplusplus/trunk/client/FinishedManager.cpp dcplusplus/trunk/client/QueueManager.cpp dcplusplus/trunk/client/QueueManager.h dcplusplus/trunk/client/SettingsManager.cpp dcplusplus/trunk/client/ShareManager.cpp dcplusplus/trunk/client/ShareManager.h dcplusplus/trunk/client/StringDefs.cpp dcplusplus/trunk/client/StringDefs.h dcplusplus/trunk/client/UploadManager.cpp dcplusplus/trunk/client/UploadManager.h dcplusplus/trunk/client/UserConnection.cpp dcplusplus/trunk/client/UserConnection.h dcplusplus/trunk/help/changelog.html dcplusplus/trunk/windows/TransferView.cpp Modified: dcplusplus/trunk/Compile.txt =================================================================== --- dcplusplus/trunk/Compile.txt 2006-09-29 16:24:13 UTC (rev 662) +++ dcplusplus/trunk/Compile.txt 2006-10-06 21:18:32 UTC (rev 663) @@ -43,7 +43,7 @@ Linux / Unix: I've made some rudimentary autoconf/automake scripts now, so you can compile the client part into a library without too much hassle (I don't check if it compiles very often though...). You'll need the latest versions -of automake and autoconf, and after getting the source (from CVS is easiest), do +of automake and autoconf, and after getting the source (from SVN is easiest), do "aclocal && automake && autoconf && configure && make" and you'll have the client part nicely compiled. When / if I test it I do it on a Gentoo AMD64 box with the latest gcc in 64-bit mode, so I don't have a clue if the 32-bit compile works... @@ -56,7 +56,7 @@ ugly code, abusable features, feature that I don't like that bloat the application and incompatibility with other modifications I've already done. To increase the chances of your patch being accepted, post them in the DC++ bugzilla as diffs against the latest -code you can find (in the cvs repository on sourceforge most probably). You can find a lot of +code you can find (in the SVN repository on sourceforge most probably). You can find a lot of information about diff and patch by googling for it. I like unified format (diff -u). When diffing, apply diff to the folders of the two versions, so that the paths will be included in the diff. By submitting a patch, you agree to that I get copyright of it. This to avoid stupid situations later on where Modified: dcplusplus/trunk/Example.xml =================================================================== --- dcplusplus/trunk/Example.xml 2006-09-29 16:24:13 UTC (rev 662) +++ dcplusplus/trunk/Example.xml 2006-10-06 21:18:32 UTC (rev 663) @@ -581,6 +581,7 @@ <String Name="UnableToCreateThread">Unable to create thread</String> <String Name="UnableToOpenFilelist">Unable to open filelist: </String> <String Name="UnableToRename">Unable to rename </String> + <String Name="UnableToSendFile">Unable to send file </String> <String Name="Unknown">Unknown</String> <String Name="UnknownAddress">Unknown address</String> <String Name="UnknownCommand">Unknown command: </String> Modified: dcplusplus/trunk/changelog.txt =================================================================== --- dcplusplus/trunk/changelog.txt 2006-09-29 16:24:13 UTC (rev 662) +++ dcplusplus/trunk/changelog.txt 2006-10-06 21:18:32 UTC (rev 663) @@ -1,7 +1,10 @@ -- -- * [bug 1065] Code cleanup (thanks steven sheehy) +* Fixed readme.txt (thanks ullner) +* More code cleanup +* Fixed trusted/untrusted upload view +* Fixed crash on invalid remote command during upload - -- 0.697 2006-09-29 -- * [ADC] Fixed a few protocol issues * Some code cleanup Modified: dcplusplus/trunk/client/DownloadManager.cpp =================================================================== --- dcplusplus/trunk/client/DownloadManager.cpp 2006-09-29 16:24:13 UTC (rev 662) +++ dcplusplus/trunk/client/DownloadManager.cpp 2006-10-06 21:18:32 UTC (rev 663) @@ -45,23 +45,27 @@ static const string DOWNLOAD_AREA = "Downloads"; const string Download::ANTI_FRAG_EXT = ".antifrag"; -const string DownloadManager::USER_LIST_NAME = "files.xml"; -const string DownloadManager::USER_LIST_NAME_BZ = "files.xml.bz2"; - -Download::Download() throw() : file(NULL), +Download::Download(UserConnection& conn) throw() : Transfer(conn), file(0), crcCalc(NULL), treeValid(false) { + conn.setDownload(this); } -Download::Download(QueueItem* qi) throw() : - target(qi->getTarget()), tempTarget(qi->getTempTarget()), file(NULL), - crcCalc(NULL), tth(qi->getTTH()), treeValid(false) { - - setSize(qi->getSize()); - if(qi->isSet(QueueItem::FLAG_USER_LIST)) +Download::Download(UserConnection& conn, QueueItem& qi) throw() : Transfer(conn), + target(qi.getTarget()), tempTarget(qi.getTempTarget()), file(0), + crcCalc(NULL), treeValid(false) +{ + conn.setDownload(this); + + setTTH(qi.getTTH()); + setSize(qi.getSize()); + if(qi.isSet(QueueItem::FLAG_USER_LIST)) setFlag(Download::FLAG_USER_LIST); - if(qi->isSet(QueueItem::FLAG_RESUME)) + if(qi.isSet(QueueItem::FLAG_RESUME)) setFlag(Download::FLAG_RESUME); } +Download::~Download() { + getUserConnection().setDownload(0); +} AdcCommand Download::getCommand(bool zlib) { AdcCommand cmd(AdcCommand::CMD_GET); @@ -126,7 +130,7 @@ if((u_int32_t)(aTick / 1000) % SETTING(AUTODROP_INTERVAL) == 0) { for(Download::Iter i = downloads.begin(); i != downloads.end(); ++i) { u_int32_t timeElapsed = GET_TICK() - (*i)->getStart(); - u_int32_t timeInactive = GET_TICK() - (*i)->getUserConnection()->getLastActivity(); + u_int32_t timeInactive = GET_TICK() - (*i)->getUserConnection().getLastActivity(); u_int64_t bytesDownloaded = (*i)->getTotal(); bool timeElapsedOk = timeElapsed >= (u_int32_t)SETTING(AUTODROP_ELAPSED) * 1000; bool timeInactiveOk = timeInactive <= (u_int32_t)SETTING(AUTODROP_INACTIVITY) * 1000; @@ -139,9 +143,9 @@ (filesizeOk && BOOLSETTING(AUTODROP_ALL)); if(speedTooLow && onlineSourcesOk && dropIt) { if(BOOLSETTING(AUTODROP_DISCONNECT) && !((*i)->isSet(Download::FLAG_USER_LIST))) { - (*i)->getUserConnection()->disconnect(); + (*i)->getUserConnection().disconnect(); } else { - dropTargets.push_back(make_pair((*i)->getTarget(), (*i)->getUserConnection()->getUser())); + dropTargets.push_back(make_pair((*i)->getTarget(), (*i)->getUser())); } } } @@ -271,7 +275,7 @@ } } - Download* d = QueueManager::getInstance()->getDownload(aConn->getUser(), aConn->isSet(UserConnection::FLAG_SUPPORTS_TTHL)); + Download* d = QueueManager::getInstance()->getDownload(*aConn, aConn->isSet(UserConnection::FLAG_SUPPORTS_TTHL)); if(!d) { Lock l(cs); @@ -279,9 +283,6 @@ return; } - d->setUserConnection(aConn); - aConn->setDownload(d); - aConn->setState(UserConnection::STATE_FILELENGTH); if(d->isSet(Download::FLAG_RESUME)) { @@ -323,9 +324,9 @@ if(d->isSet(Download::FLAG_USER_LIST)) { if(aConn->isSet(UserConnection::FLAG_SUPPORTS_XML_BZLIST)) { - d->setSource(USER_LIST_NAME_BZ); + d->setSource(Transfer::USER_LIST_NAME_BZ); } else { - d->setSource(USER_LIST_NAME); + d->setSource(Transfer::USER_LIST_NAME); } } @@ -482,7 +483,6 @@ } if(d->getPos() >= d->getSize()) { // Already finished? - aSource->setDownload(NULL); removeDownload(d); QueueManager::getInstance()->putDownload(d, true); removeConnection(aSource); @@ -561,7 +561,7 @@ dcassert(d->getPos() != -1); d->setStart(GET_TICK()); - aSource->setState(UserConnection::STATE_DONE); + aSource->setState(UserConnection::STATE_RUNNING); fire(DownloadManagerListener::Starting(), d); @@ -598,7 +598,7 @@ /** Download finished! */ void DownloadManager::handleEndData(UserConnection* aSource) { - dcassert(aSource->getState() == UserConnection::STATE_DONE); + dcassert(aSource->getState() == UserConnection::STATE_RUNNING); Download* d = aSource->getDownload(); dcassert(d != NULL); @@ -620,7 +620,6 @@ QueueManager::getInstance()->removeSource(d->getTarget(), aSource->getUser(), QueueItem::Source::FLAG_BAD_TREE, false); - aSource->setDownload(NULL); QueueManager::getInstance()->putDownload(d, false); checkDownloads(aSource); @@ -680,7 +679,6 @@ removeDownload(d); fire(DownloadManagerListener::Complete(), d); - aSource->setDownload(NULL); QueueManager::getInstance()->putDownload(d, true); checkDownloads(aSource); } @@ -720,7 +718,6 @@ fire(DownloadManagerListener::Failed(), d, STRING(SFV_INCONSISTENCY)); QueueManager::getInstance()->removeSource(d->getTarget(), aSource->getUser(), QueueItem::Source::FLAG_CRC_WARN, false); - aSource->setDownload(NULL); QueueManager::getInstance()->putDownload(d, false); checkDownloads(aSource); @@ -734,29 +731,15 @@ return true; } +void Download::getParams(const UserConnection& aSource, StringMap& params) { + Transfer::getParams(aSource, params); + params["target"] = getTarget(); + params["sfv"] = Util::toString(isSet(Download::FLAG_CRC32_OK) ? 1 : 0); +} + void DownloadManager::logDownload(UserConnection* aSource, Download* d) { StringMap params; - params["target"] = d->getTarget(); - params["userNI"] = Util::toString(ClientManager::getInstance()->getNicks(aSource->getUser()->getCID())); - params["userI4"] = aSource->getRemoteIp(); - StringList hubNames = ClientManager::getInstance()->getHubNames(aSource->getUser()->getCID()); - if(hubNames.empty()) - hubNames.push_back(STRING(OFFLINE)); - params["hub"] = Util::toString(hubNames); - StringList hubs = ClientManager::getInstance()->getHubs(aSource->getUser()->getCID()); - if(hubs.empty()) - hubs.push_back(STRING(OFFLINE)); - params["hubURL"] = Util::toString(hubs); - params["fileSI"] = Util::toString(d->getSize()); - params["fileSIshort"] = Util::formatBytes(d->getSize()); - params["fileSIchunk"] = Util::toString(d->getTotal()); - params["fileSIchunkshort"] = Util::formatBytes(d->getTotal()); - params["fileSIactual"] = Util::toString(d->getActual()); - params["fileSIactualshort"] = Util::formatBytes(d->getActual()); - params["speed"] = Util::formatBytes(d->getAverageSpeed()) + "/s"; - params["time"] = Util::formatSeconds((GET_TICK() - d->getStart()) / 1000); - params["sfv"] = Util::toString(d->isSet(Download::FLAG_CRC32_OK) ? 1 : 0); - params["fileTR"] = d->getTTH().toBase32(); + d->getParams(*aSource, params); LOG(LogManager::DOWNLOAD, params); } @@ -798,6 +781,10 @@ failDownload(aSource, STRING(NO_SLOTS_AVAILABLE)); } +void DownloadManager::on(UserConnectionListener::Error, UserConnection* aSource, const string& aError) throw() { + failDownload(aSource, aError); +} + void DownloadManager::on(UserConnectionListener::Failed, UserConnection* aSource, const string& aError) throw() { failDownload(aSource, aError); } @@ -809,7 +796,6 @@ removeDownload(d); fire(DownloadManagerListener::Failed(), d, reason); - aSource->setDownload(0); QueueManager::getInstance()->putDownload(d, false); } removeConnection(aSource); @@ -893,8 +879,6 @@ removeDownload(d); fire(DownloadManagerListener::Failed(), d, d->getTargetFileName() + ": " + STRING(FILE_NOT_AVAILABLE)); - aSource->setDownload(NULL); - QueueManager::getInstance()->removeSource(d->getTarget(), aSource->getUser(), d->isSet(Download::FLAG_TREE_DOWNLOAD) ? QueueItem::Source::FLAG_NO_TREE : QueueItem::Source::FLAG_FILE_NOT_AVAILABLE, false); QueueManager::getInstance()->putDownload(d, false); Modified: dcplusplus/trunk/client/DownloadManager.h =================================================================== --- dcplusplus/trunk/client/DownloadManager.h 2006-09-29 16:24:13 UTC (rev 662) +++ dcplusplus/trunk/client/DownloadManager.h 2006-10-06 21:18:32 UTC (rev 663) @@ -60,11 +60,13 @@ FLAG_TTH_CHECK = 0x800 }; - Download() throw(); - Download(QueueItem* qi) throw(); + Download(UserConnection& conn) throw(); + Download(UserConnection& conn, QueueItem& qi) throw(); - virtual ~Download() { } + virtual void getParams(const UserConnection& aSource, StringMap& params); + virtual ~Download(); + /** * @remarks This function is only used from DownloadManager but its * functionality could be useful in TransferView. @@ -72,12 +74,7 @@ * @return Target filename without path. */ string getTargetFileName() { - string::size_type i = getTarget().rfind('\\'); - if(i != string::npos) { - return getTarget().substr(i + 1); - } else { - return getTarget(); - } + return Util::getFileName(getTarget()); } /** @internal */ @@ -98,7 +95,6 @@ GETSET(string, tempTarget, TempTarget); GETSET(OutputStream*, file, File); GETSET(CrcOS*, crcCalc, CrcCalc); - GETSET(TTHValue, tth, TTH); GETSET(bool, treeValid, TreeValid); private: @@ -198,8 +194,6 @@ return downloads.size(); } - static const string USER_LIST_NAME; - static const string USER_LIST_NAME_BZ; private: enum { MOVER_LIMIT = 10*1024*1024 }; class FileMover : public Thread { @@ -248,6 +242,7 @@ // UserConnectionListener virtual void on(Data, UserConnection*, const u_int8_t*, size_t) throw(); + virtual void on(Error, UserConnection*, const string&) throw(); virtual void on(Failed, UserConnection*, const string&) throw(); virtual void on(Sending, UserConnection*, int64_t) throw(); virtual void on(FileLength, UserConnection*, int64_t) throw(); Modified: dcplusplus/trunk/client/FinishedManager.cpp =================================================================== --- dcplusplus/trunk/client/FinishedManager.cpp 2006-09-29 16:24:13 UTC (rev 662) +++ dcplusplus/trunk/client/FinishedManager.cpp 2006-10-06 21:18:32 UTC (rev 663) @@ -66,8 +66,8 @@ { if(!d->isSet(Download::FLAG_TREE_DOWNLOAD) && (!d->isSet(Download::FLAG_USER_LIST) || BOOLSETTING(LOG_FILELIST_TRANSFERS))) { FinishedItem *item = new FinishedItem( - d->getTarget(), Util::toString(ClientManager::getInstance()->getNicks(d->getUserConnection()->getUser()->getCID())), - Util::toString(ClientManager::getInstance()->getHubNames(d->getUserConnection()->getUser()->getCID())), + d->getTarget(), Util::toString(ClientManager::getInstance()->getNicks(d->getUser()->getCID())), + Util::toString(ClientManager::getInstance()->getHubNames(d->getUser()->getCID())), d->getSize(), d->getTotal(), (GET_TICK() - d->getStart()), GET_TIME(), d->isSet(Download::FLAG_CRC32_OK)); { Lock l(cs); @@ -82,8 +82,8 @@ { if(!u->isSet(Upload::FLAG_TTH_LEAVES) && (!u->isSet(Upload::FLAG_USER_LIST) || BOOLSETTING(LOG_FILELIST_TRANSFERS))) { FinishedItem *item = new FinishedItem( - u->getLocalFileName(), Util::toString(ClientManager::getInstance()->getNicks(u->getUserConnection()->getUser()->getCID())), - Util::toString(ClientManager::getInstance()->getHubNames(u->getUserConnection()->getUser()->getCID())), + u->getSourceFile(), Util::toString(ClientManager::getInstance()->getNicks(u->getUser()->getCID())), + Util::toString(ClientManager::getInstance()->getHubNames(u->getUser()->getCID())), u->getSize(), u->getTotal(), (GET_TICK() - u->getStart()), GET_TIME()); { Lock l(cs); Modified: dcplusplus/trunk/client/QueueManager.cpp =================================================================== --- dcplusplus/trunk/client/QueueManager.cpp 2006-09-29 16:24:13 UTC (rev 662) +++ dcplusplus/trunk/client/QueueManager.cpp 2006-10-06 21:18:32 UTC (rev 663) @@ -724,13 +724,14 @@ } } -Download* QueueManager::getDownload(User::Ptr& aUser, bool supportsTrees) throw() { +Download* QueueManager::getDownload(UserConnection& aSource, bool supportsTrees) throw() { Lock l(cs); + User::Ptr& aUser = aSource.getUser(); // First check PFS's... PfsIter pi = pfsQueue.find(aUser->getCID()); if(pi != pfsQueue.end()) { - Download* d = new Download(); + Download* d = new Download(aSource); d->setFlag(Download::FLAG_PARTIAL_LIST); d->setSource(pi->second); return d; @@ -743,7 +744,7 @@ userQueue.setRunning(q, aUser); - Download* d = new Download(q); + Download* d = new Download(aSource, *q); q->setCurrentDownload(d); @@ -783,18 +784,18 @@ Lock l(cs); if(aDownload->isSet(Download::FLAG_PARTIAL_LIST)) { - pair<PfsIter, PfsIter> range = pfsQueue.equal_range(aDownload->getUserConnection()->getUser()->getCID()); + pair<PfsIter, PfsIter> range = pfsQueue.equal_range(aDownload->getUser()->getCID()); PfsIter i = find_if(range.first, range.second, CompareSecond<CID, string>(aDownload->getSource())); if(i != range.second) { pfsQueue.erase(i); - fire(QueueManagerListener::PartialList(), aDownload->getUserConnection()->getUser(), aDownload->getPFS()); + fire(QueueManagerListener::PartialList(), aDownload->getUser(), aDownload->getPFS()); } } else { QueueItem* q = fileQueue.find(aDownload->getTarget()); if(q) { if(aDownload->isSet(Download::FLAG_USER_LIST)) { - if(aDownload->getSource() == DownloadManager::USER_LIST_NAME_BZ) { + if(aDownload->getSource() == Transfer::USER_LIST_NAME_BZ) { q->setFlag(QueueItem::FLAG_XML_BZLIST); } else { q->unsetFlag(QueueItem::FLAG_XML_BZLIST); @@ -861,7 +862,6 @@ } } } - aDownload->setUserConnection(0); delete aDownload; } Modified: dcplusplus/trunk/client/QueueManager.h =================================================================== --- dcplusplus/trunk/client/QueueManager.h 2006-09-29 16:24:13 UTC (rev 662) +++ dcplusplus/trunk/client/QueueManager.h 2006-10-06 21:18:32 UTC (rev 663) @@ -103,7 +103,7 @@ QueueItem::StringMap& lockQueue() throw() { cs.enter(); return fileQueue.getQueue(); } ; void unlockQueue() throw() { cs.leave(); } - Download* getDownload(User::Ptr& aUser, bool supportsTrees) throw(); + Download* getDownload(UserConnection& aSource, bool supportsTrees) throw(); void putDownload(Download* aDownload, bool finished) throw(); bool hasDownload(const User::Ptr& aUser, QueueItem::Priority minPrio = QueueItem::LOWEST) throw() { Modified: dcplusplus/trunk/client/SettingsManager.cpp =================================================================== --- dcplusplus/trunk/client/SettingsManager.cpp 2006-09-29 16:24:13 UTC (rev 662) +++ dcplusplus/trunk/client/SettingsManager.cpp 2006-10-06 21:18:32 UTC (rev 663) @@ -152,8 +152,8 @@ setDefault(USE_OEM_MONOFONT, false); setDefault(POPUP_PMS, true); setDefault(MIN_UPLOAD_SPEED, 0); - setDefault(LOG_FORMAT_POST_DOWNLOAD, "%Y-%m-%d %H:%M: %[target]" + STRING(DOWNLOADED_FROM) + "%[userNI] (%[userCID]), %[fileSI] (%[fileSIchunk]), %[speed], %[time]"); - setDefault(LOG_FORMAT_POST_UPLOAD, "%Y-%m-%d %H:%M: %[source]" + STRING(UPLOADED_TO) + "%[userNI] (%[userCID]), %[fileSI] (%[fileSIchunk]), %[speed], %[time]"); + setDefault(LOG_FORMAT_POST_DOWNLOAD, "%Y-%m-%d %H:%M: %[target]" + STRING(DOWNLOADED_FROM) + "%[userNI] (%[userCID]), %[fileSI] (%[fileSIchunk]), %[speed], %[time], %[fileTR]"); + setDefault(LOG_FORMAT_POST_UPLOAD, "%Y-%m-%d %H:%M: %[source]" + STRING(UPLOADED_TO) + "%[userNI] (%[userCID]), %[fileSI] (%[fileSIchunk]), %[speed], %[time], %[fileTR]"); setDefault(LOG_FORMAT_MAIN_CHAT, "[%Y-%m-%d %H:%M] %[message]"); setDefault(LOG_FORMAT_PRIVATE_CHAT, "[%Y-%m-%d %H:%M] %[message]"); setDefault(LOG_FORMAT_STATUS, "[%Y-%m-%d %H:%M] %[message]"); Modified: dcplusplus/trunk/client/ShareManager.cpp =================================================================== --- dcplusplus/trunk/client/ShareManager.cpp 2006-09-29 16:24:13 UTC (rev 662) +++ dcplusplus/trunk/client/ShareManager.cpp 2006-10-06 21:18:32 UTC (rev 663) @@ -82,9 +82,8 @@ } } -string ShareManager::translateTTH(const string& TTH) throw(ShareException) { - TTHValue v(TTH); - HashFileIter i = tthIndex.find(v); +string ShareManager::translateTTH(const TTHValue& tth) throw(ShareException) { + HashFileIter i = tthIndex.find(tth); if(i != tthIndex.end()) { return i->second->getADCPath(); } else { @@ -92,67 +91,64 @@ } } -string ShareManager::translateFileName(const string& aFile) throw(ShareException) { - if(aFile == "MyList.DcLst") { +string ShareManager::translateFileName(const string& virtualFile) throw(ShareException) { + if(virtualFile == "MyList.DcLst") { throw ShareException("NMDC-style lists no longer supported, please upgrade your client"); - } else if(aFile == DownloadManager::USER_LIST_NAME || aFile == DownloadManager::USER_LIST_NAME_BZ) { + } else if(virtualFile == Transfer::USER_LIST_NAME_BZ || virtualFile == Transfer::USER_LIST_NAME) { generateXmlList(); return getBZXmlFile(); } else { - if(aFile.length() < 3) - throw ShareException(UserConnection::FILE_NOT_AVAILABLE); - - string file; - + string realFile; Lock l(cs); - // Check for tth root identifier - if(aFile.compare(0, 4, "TTH/") == 0) { - file = translateTTH(aFile.substr(4)); - } else if(aFile[0] != '/') { + Directory::File::Iter it; + if(!checkFile(virtualFile, realFile, it)) { throw ShareException(UserConnection::FILE_NOT_AVAILABLE); - } else { - file = aFile; } + return realFile; + } +} - string::size_type i = file.find('/', 1); - if(i == string::npos) - throw ShareException(UserConnection::FILE_NOT_AVAILABLE); +TTHValue ShareManager::getTTH(const string& virtualName) throw(ShareException) { + Lock l(cs); + string realName; + Directory::File::Iter it; + if(!checkFile(virtualName, realName, it)) + throw ShareException(); + return it->getTTH(); +} - StringPairIter j = lookupVirtual(file.substr(1, i-1)); - if(j == virtualMap.end()) { - throw ShareException(UserConnection::FILE_NOT_AVAILABLE); +MemoryInputStream* ShareManager::getTree(const string& aFile) { + TigerTree tree; + if(aFile.compare(0, 4, "TTH/") == 0) { + if(!HashManager::getInstance()->getTree(TTHValue(aFile.substr(4)), tree)) + return 0; + } else { + try { + TTHValue tth = getTTH(aFile); + HashManager::getInstance()->getTree(tth, tree); + } catch(const Exception&) { + return 0; } - - file = file.substr(i + 1); - Directory::File::Iter it; - if(!checkFile(j->second, file, it)) { - throw ShareException(UserConnection::FILE_NOT_AVAILABLE); - } - -#ifdef _WIN32 - for(i = 0; i < file.length(); ++i) { - if(file[i] == '/') - file[i] = '\\'; - } -#endif - return j->second + file; } + + vector<u_int8_t> buf = tree.getLeafData(); + return new MemoryInputStream(&buf[0], buf.size()); } AdcCommand ShareManager::getFileInfo(const string& aFile) throw(ShareException) { - if(aFile == DownloadManager::USER_LIST_NAME) { + if(aFile == Transfer::USER_LIST_NAME) { generateXmlList(); /** todo fix size... */ AdcCommand cmd(AdcCommand::CMD_RES); - cmd.addParam("FN", DownloadManager::USER_LIST_NAME); + cmd.addParam("FN", aFile); cmd.addParam("TR", xmlRoot.toBase32()); return cmd; - } else if(aFile == DownloadManager::USER_LIST_NAME_BZ) { + } else if(aFile == Transfer::USER_LIST_NAME_BZ) { generateXmlList(); AdcCommand cmd(AdcCommand::CMD_RES); - cmd.addParam("FN", DownloadManager::USER_LIST_NAME_BZ); + cmd.addParam("FN", aFile); cmd.addParam("SI", Util::toString(File::getSize(getBZXmlFile()))); cmd.addParam("TR", xmlbzRoot.toBase32()); return cmd; @@ -176,42 +172,68 @@ return cmd; } -StringPairIter ShareManager::findVirtual(const string& name) { +StringPairIter ShareManager::findVirtual(const string& realName) { for(StringPairIter i = virtualMap.begin(); i != virtualMap. end(); ++i) { - if(Util::stricmp(name, i->second) == 0) + if(Util::stricmp(realName, i->second) == 0) return i; } return virtualMap.end(); } -StringPairIter ShareManager::lookupVirtual(const string& name) { +StringPairIter ShareManager::findReal(const string& virtualName) { for(StringPairIter i = virtualMap.begin(); i != virtualMap. end(); ++i) { - if(Util::stricmp(name, i->first) == 0) + if(Util::stricmp(virtualName, i->first) == 0) return i; } return virtualMap.end(); } -bool ShareManager::checkFile(const string& dir, const string& aFile, Directory::File::Iter& it) { - Directory::MapIter mi = directories.find(dir); +bool ShareManager::checkFile(const string& virtualFile, string& realFile, Directory::File::Iter& it) { + string file; + if(virtualFile.compare(0, 4, "TTH/") == 0) { + file = translateTTH(TTHValue(virtualFile.substr(4))); + } else if(virtualFile.empty() || virtualFile[0] != '/') { + return false; + } else { + file = virtualFile; + } + + string::size_type i = file.find('/', 1); + if(i == string::npos || i == 1) { + return false; + } + + StringPairIter k = findReal(file.substr(1, i-1)); + if(k == virtualMap.end()) { + return false; + } + + file = file.substr(i + 1); + + Directory::MapIter mi = directories.find(k->second); if(mi == directories.end()) return false; Directory* d = mi->second; - string::size_type i; string::size_type j = 0; - while( (i = aFile.find('/', j)) != string::npos) { - mi = d->directories.find(aFile.substr(j, i-j)); + while( (i = file.find('/', j)) != string::npos) { + mi = d->directories.find(file.substr(j, i-j)); j = i + 1; if(mi == d->directories.end()) return false; d = mi->second; } - it = find_if(d->files.begin(), d->files.end(), Directory::File::StringComp(aFile.substr(j))); + it = find_if(d->files.begin(), d->files.end(), Directory::File::StringComp(file.substr(j))); if(it == d->files.end()) return false; + +#ifdef _WIN32 + replace_if(file.begin(), file.end(), bind2nd(equal_to<char>(), '/'), '\\'); +#endif + + realFile = k->second + file; return true; } @@ -249,7 +271,7 @@ newVirt = validateVirtual(newVirt); // add only unique directories - if(lookupVirtual(newVirt) == virtualMap.end()) { + if(findReal(newVirt) == virtualMap.end()) { Directory* dp = new Directory(newVirt); directories[d] = dp; virtualMap.push_back(make_pair(newVirt, d)); @@ -381,7 +403,7 @@ } } - if(lookupVirtual(vName) != virtualMap.end()) { + if(findReal(vName) != virtualMap.end()) { throw ShareException(STRING(VIRTUAL_NAME_EXISTS)); } } @@ -427,13 +449,12 @@ } void ShareManager::renameDirectory(const string& oName, const string& nName) throw(ShareException) { - StringPairIter i; Lock l(cs); //Find the virtual name - i = lookupVirtual(oName); - if (lookupVirtual(nName) != virtualMap.end()) { + if (findReal(nName) != virtualMap.end()) { throw ShareException(STRING(VIRTUAL_NAME_EXISTS)); } else { + StringPairIter i = findReal(oName); // Valid newName, lets rename i->first = nName; @@ -886,7 +907,7 @@ if(first) { first = false; - StringPairIter k = lookupVirtual(dir.substr(j, i-j)); + StringPairIter k = findReal(dir.substr(j, i-j)); if(k == virtualMap.end()) return NULL; it = directories.find(k->second); @@ -911,47 +932,6 @@ return new MemoryInputStream(xml); } -bool ShareManager::getTTH(const string& aFile, TTHValue& tth) throw() { - if(aFile.length() < 3 || aFile[0] != '/') - return false; - - string::size_type i = aFile.find('/', 1); - if(i == string::npos) - return false; - - Lock l(cs); - StringPairIter j = lookupVirtual(aFile.substr(1, i-1)); - if(j == virtualMap.end()) { - return false; - } - - Directory::File::Iter it; - if(!checkFile(j->second, aFile.substr(i + 1), it)) - return false; - - tth = it->getTTH(); - return true; -} - -MemoryInputStream* ShareManager::getTree(const string& aFile) { - TigerTree tree; - if(aFile.compare(0, 4, "TTH/") == 0) { - if(!HashManager::getInstance()->getTree(TTHValue(aFile.substr(4)), tree)) - return NULL; - } else { - try { - TTHValue tth; - if(getTTH(aFile, tth)) - HashManager::getInstance()->getTree(tth, tree); - } catch(const Exception&) { - return NULL; - } - } - - vector<u_int8_t> buf = tree.getLeafData(); - return new MemoryInputStream(&buf[0], buf.size()); -} - static const string& escaper(const string& n, string& tmp) { if(SimpleXML::needsEscape(n, true, false)) { tmp.clear(); Modified: dcplusplus/trunk/client/ShareManager.h =================================================================== --- dcplusplus/trunk/client/ShareManager.h 2006-09-29 16:24:13 UTC (rev 662) +++ dcplusplus/trunk/client/ShareManager.h 2006-10-06 21:18:32 UTC (rev 663) @@ -57,9 +57,10 @@ void addDirectory(const string& aDirectory, const string & aName) throw(ShareException); void removeDirectory(const string& aName, bool duringRefresh = false); void renameDirectory(const string& oName, const string& nName) throw(ShareException); - string translateTTH(const string& TTH) throw(ShareException); + string translateTTH(const TTHValue& tth) throw(ShareException); string translateFileName(const string& aFile) throw(ShareException); - bool getTTH(const string& aFile, TTHValue& tth) throw(); + TTHValue getTTH(const string& aFile) throw(ShareException); + void refresh(bool dirs = false, bool aUpdate = true, bool block = false) throw(ThreadException, ShareException); void setDirty() { xmlDirty = true; } @@ -283,11 +284,11 @@ BloomFilter<5> bloom; /** Find virtual name from real name */ - StringPairIter findVirtual(const string& name); + StringPairIter findVirtual(const string& realName); /** Find real name from virtual name */ - StringPairIter lookupVirtual(const string& name); + StringPairIter findReal(const string& virtualName); - bool checkFile(const string& aDir, const string& aFile, Directory::File::Iter& it); + bool checkFile(const string& virtualFile, string& realFile, Directory::File::Iter& it); Directory* buildTree(const string& aName, Directory* aParent); void addTree(Directory* aDirectory); Modified: dcplusplus/trunk/client/StringDefs.cpp =================================================================== --- dcplusplus/trunk/client/StringDefs.cpp 2006-09-29 16:24:13 UTC (rev 662) +++ dcplusplus/trunk/client/StringDefs.cpp 2006-10-06 21:18:32 UTC (rev 663) @@ -582,6 +582,7 @@ "Unable to create thread", "Unable to open filelist: ", "Unable to rename ", +"Unable to send file ", "Unknown", "Unknown address", "Unknown command: ", @@ -1210,6 +1211,7 @@ "UnableToCreateThread", "UnableToOpenFilelist", "UnableToRename", +"UnableToSendFile", "Unknown", "UnknownAddress", "UnknownCommand", Modified: dcplusplus/trunk/client/StringDefs.h =================================================================== --- dcplusplus/trunk/client/StringDefs.h 2006-09-29 16:24:13 UTC (rev 662) +++ dcplusplus/trunk/client/StringDefs.h 2006-10-06 21:18:32 UTC (rev 663) @@ -585,6 +585,7 @@ UNABLE_TO_CREATE_THREAD, // "Unable to create thread" UNABLE_TO_OPEN_FILELIST, // "Unable to open filelist: " UNABLE_TO_RENAME, // "Unable to rename " + UNABLE_TO_SEND_FILE, // "Unable to send file " UNKNOWN, // "Unknown" UNKNOWN_ADDRESS, // "Unknown address" UNKNOWN_COMMAND, // "Unknown command: " Modified: dcplusplus/trunk/client/UploadManager.cpp =================================================================== --- dcplusplus/trunk/client/UploadManager.cpp 2006-09-29 16:24:13 UTC (rev 662) +++ dcplusplus/trunk/client/UploadManager.cpp 2006-10-06 21:18:32 UTC (rev 663) @@ -37,6 +37,20 @@ static const string UPLOAD_AREA = "Uploads"; +Upload::Upload(UserConnection& conn) : Transfer(conn), stream(0) { + conn.setUpload(this); +} + +Upload::~Upload() { + getUserConnection().setUpload(0); + delete stream; +} + +void Upload::getParams(const UserConnection& aSource, StringMap& params) { + Transfer::getParams(aSource, params); + params["source"] = getSourceFile(); +} + UploadManager::UploadManager() throw() : running(0), extra(0), lastGrant(0) { ClientManager::getInstance()->addListener(this); TimerManager::getInstance()->addListener(this); @@ -55,153 +69,143 @@ } } -bool UploadManager::prepareFile(UserConnection* aSource, const string& aType, const string& aFile, int64_t aStartPos, int64_t aBytes, bool listRecursive) { - if(aSource->getState() != UserConnection::STATE_GET) { - dcdebug("UM:prepFile Wrong state, ignoring\n"); +bool UploadManager::prepareFile(UserConnection& aSource, const string& aType, const string& aFile, int64_t aStartPos, int64_t aBytes, bool listRecursive) { + if(aFile.empty() || aStartPos < 0 || aBytes < -1 || aBytes == 0) { + aSource.fileNotAvail("Invalid request"); return false; } - dcassert(aFile.size() > 0); - - InputStream* is = NULL; + InputStream* is = 0; + int64_t start = 0; + int64_t bytesLeft = 0; int64_t size = 0; - bool userlist = false; - bool free = false; + bool userlist = (aFile == Transfer::USER_LIST_NAME_BZ || aFile == Transfer::USER_LIST_NAME); + bool free = userlist; bool leaves = false; bool partList = false; - string file; + string sourceFile; try { - if(aType == "file") { - file = ShareManager::getInstance()->translateFileName(aFile); - userlist = (aFile == DownloadManager::USER_LIST_NAME_BZ || aFile == DownloadManager::USER_LIST_NAME); + if(aType == Transfer::TYPE_FILE) { + sourceFile = ShareManager::getInstance()->translateFileName(aFile); - try { - if(aFile == DownloadManager::USER_LIST_NAME) { - // Unpack before sending... - string bz2 = File(file, File::READ, File::OPEN).read(); - string xml; - CryptoManager::getInstance()->decodeBZ2(reinterpret_cast<const u_int8_t*>(bz2.data()), bz2.size(), xml); - // Clear to save some memory... - bz2 = string(); - is = new MemoryInputStream(xml); - aBytes = size = xml.size(); - aStartPos = 0; - free = true; - - } else { - File* f = new File(file, File::READ, File::OPEN); + if(aFile == Transfer::USER_LIST_NAME) { + // Unpack before sending... + string bz2 = File(sourceFile, File::READ, File::OPEN).read(); + string xml; + CryptoManager::getInstance()->decodeBZ2(reinterpret_cast<const u_int8_t*>(bz2.data()), bz2.size(), xml); + // Clear to save some memory... + string().swap(bz2); + is = new MemoryInputStream(xml); + start = 0; + bytesLeft = size = xml.size(); + } else { + File* f = new File(sourceFile, File::READ, File::OPEN); - size = f->getSize(); + start = aStartPos; + size = f->getSize(); + bytesLeft = (aBytes == -1) ? size : aBytes; - free = userlist || (size <= (int64_t)(SETTING(SET_MINISLOT_SIZE) * 1024) ); + if(size < (start + bytesLeft)) { + aSource.fileNotAvail(); + delete f; + return false; + } - if(aBytes == -1) { - aBytes = size - aStartPos; - } + free = (size <= (int64_t)(SETTING(SET_MINISLOT_SIZE) * 1024) ); - if((aBytes < 0) || ((aStartPos + aBytes) > size)) { - aSource->fileNotAvail(); - delete f; - return false; - } + f->setPos(start); - f->setPos(aStartPos); - - is = f; - - if((aStartPos + aBytes) < size) { - is = new LimitedInputStream<true>(is, aBytes); - } + is = f; + if((start + bytesLeft) < size) { + is = new LimitedInputStream<true>(is, aBytes); } - } catch(const Exception&) { - aSource->fileNotAvail(); - return false; } - - } else if(aType == "tthl") { - // TTH Leaves... + } else if(aType == Transfer::TYPE_TTHL) { + sourceFile = ShareManager::getInstance()->translateFileName(aFile); MemoryInputStream* mis = ShareManager::getInstance()->getTree(aFile); - file = ShareManager::getInstance()->translateFileName(aFile); - if(mis == NULL) { - aSource->fileNotAvail(); + if(!mis) { + aSource.fileNotAvail(); return false; } - size = mis->getSize(); - aStartPos = 0; + start = 0; + bytesLeft = size = mis->getSize(); is = mis; leaves = true; free = true; - } else if(aType == "list") { + } else if(aType == Transfer::TYPE_LIST) { // Partial file list MemoryInputStream* mis = ShareManager::getInstance()->generatePartialList(aFile, listRecursive); if(mis == NULL) { - aSource->fileNotAvail(); + aSource.fileNotAvail(); return false; } // Some old dc++ clients err here... aBytes = -1; - size = mis->getSize(); - aStartPos = 0; + start = 0; + bytesLeft = size = mis->getSize(); + is = mis; free = true; partList = true; } else { - aSource->fileNotAvail(); + aSource.fileNotAvail("Unknown file type"); return false; } } catch(const ShareException& e) { - aSource->fileNotAvail(e.getError()); + aSource.fileNotAvail(e.getError()); return false; + } catch(const Exception& e) { + LogManager::getInstance()->message(STRING(UNABLE_TO_SEND_FILE) + sourceFile + ": " + e.getError()); + aSource.fileNotAvail(); + return false; } Lock l(cs); bool extraSlot = false; - if(!aSource->isSet(UserConnection::FLAG_HASSLOT)) { - bool hasReserved = (reservedSlots.find(aSource->getUser()) != reservedSlots.end()); - bool isFavorite = FavoriteManager::getInstance()->hasSlot(aSource->getUser()); + if(!aSource.isSet(UserConnection::FLAG_HASSLOT)) { + bool hasReserved = (reservedSlots.find(aSource.getUser()) != reservedSlots.end()); + bool isFavorite = FavoriteManager::getInstance()->hasSlot(aSource.getUser()); if(!(hasReserved || isFavorite || getFreeSlots() > 0 || getAutoSlot())) { - bool supportsFree = aSource->isSet(UserConnection::FLAG_SUPPORTS_MINISLOTS); - bool allowedFree = aSource->isSet(UserConnection::FLAG_HASEXTRASLOT) || aSource->isSet(UserConnection::FLAG_OP) || getFreeExtraSlots() > 0; + bool supportsFree = aSource.isSet(UserConnection::FLAG_SUPPORTS_MINISLOTS); + bool allowedFree = aSource.isSet(UserConnection::FLAG_HASEXTRASLOT) || aSource.isSet(UserConnection::FLAG_OP) || getFreeExtraSlots() > 0; if(free && supportsFree && allowedFree) { extraSlot = true; } else { delete is; - aSource->maxedOut(); + aSource.maxedOut(); // Check for tth root identifier string tFile = aFile; if (tFile.compare(0, 4, "TTH/") == 0) - tFile = ShareManager::getInstance()->translateTTH(aFile.substr(4)); + tFile = ShareManager::getInstance()->translateTTH(TTHValue(aFile.substr(4))); addFailedUpload(aSource, tFile + - " (" + Util::toString((aStartPos*1000/(File::getSize(file)+10))/10.0)+"% of " + Util::formatBytes(File::getSize(file)) + " done)"); - aSource->disconnect(); + " (" + Util::toString((aStartPos*1000/(size+10))/10.0)+"% of " + Util::formatBytes(size) + " done)"); + aSource.disconnect(); return false; } } else { - clearUserFiles(aSource->getUser()); // this user is using a full slot, nix them. + clearUserFiles(aSource.getUser()); // this user is using a full slot, nix them. } setLastGrant(GET_TICK()); } - Upload* u = new Upload(); - u->setUserConnection(aSource); - u->setFile(is); + Upload* u = new Upload(aSource); + u->setStream(is); if(aBytes == -1) u->setSize(size); else - u->setSize(aStartPos + aBytes); + u->setSize(start + bytesLeft); - u->setStartPos(aStartPos); - u->setFileName(file); - u->setLocalFileName(file); + u->setStartPos(start); + u->setSourceFile(sourceFile); if(userlist) u->setFlag(Upload::FLAG_USER_LIST); @@ -210,36 +214,45 @@ if(partList) u->setFlag(Upload::FLAG_PARTIAL_LIST); - dcassert(aSource->getUpload() == NULL); - aSource->setUpload(u); + dcassert(aSource.getUpload() == NULL); uploads.push_back(u); - if(!aSource->isSet(UserConnection::FLAG_HASSLOT)) { + if(!aSource.isSet(UserConnection::FLAG_HASSLOT)) { if(extraSlot) { - if(!aSource->isSet(UserConnection::FLAG_HASEXTRASLOT)) { - aSource->setFlag(UserConnection::FLAG_HASEXTRASLOT); + if(!aSource.isSet(UserConnection::FLAG_HASEXTRASLOT)) { + aSource.setFlag(UserConnection::FLAG_HASEXTRASLOT); extra++; } } else { - if(aSource->isSet(UserConnection::FLAG_HASEXTRASLOT)) { - aSource->unsetFlag(UserConnection::FLAG_HASEXTRASLOT); + if(aSource.isSet(UserConnection::FLAG_HASEXTRASLOT)) { + aSource.unsetFlag(UserConnection::FLAG_HASEXTRASLOT); extra--; } - aSource->setFlag(UserConnection::FLAG_HASSLOT); + aSource.setFlag(UserConnection::FLAG_HASSLOT); running++; } - reservedSlots.erase(aSource->getUser()); + reservedSlots.erase(aSource.getUser()); } return true; } +bool UploadManager::getAutoSlot() { + /** A 0 in settings means disable */ + if(SETTING(MIN_UPLOAD_SPEED) == 0) + return false; + /** Only grant one slot per 30 sec */ + if(GET_TICK() < getLastGrant() + 30*1000) + return false; + /** Grant if upload speed is less than the threshold speed */ + return getAverageSpeed() < (SETTING(MIN_UPLOAD_SPEED)*1024); +} + void UploadManager::removeUpload(Upload* aUpload) { Lock l(cs); dcassert(find(uploads.begin(), uploads.end(), aUpload) != uploads.end()); uploads.erase(remove(uploads.begin(), uploads.end(), aUpload), uploads.end()); - aUpload->setUserConnection(NULL); delete aUpload; } @@ -253,7 +266,12 @@ } void UploadManager::on(UserConnectionListener::Get, UserConnection* aSource, const string& aFile, int64_t aResume) throw() { - if(prepareFile(aSource, "file", Util::toAdcFile(aFile), aResume, -1)) { + if(aSource->getState() != UserConnection::STATE_GET) { + dcdebug("UM::onGet Bad state, ignoring\n"); + return; + } + + if(prepareFile(*aSource, Transfer::TYPE_FILE, Util::toAdcFile(aFile), aResume, -1)) { aSource->setState(UserConnection::STATE_SEND); aSource->fileLength(Util::toString(aSource->getUpload()->getSize())); } @@ -269,13 +287,43 @@ dcassert(u != NULL); u->setStart(GET_TICK()); - aSource->setState(UserConnection::STATE_DONE); - aSource->transmitFile(u->getFile()); + aSource->setState(UserConnection::STATE_RUNNING); + aSource->transmitFile(u->getStream()); fire(UploadManagerListener::Starting(), u); } +void UploadManager::on(AdcCommand::GET, UserConnection* aSource, const AdcCommand& c) throw() { + int64_t aBytes = Util::toInt64(c.getParam(3)); + int64_t aStartPos = Util::toInt64(c.getParam(2)); + const string& fname = c.getParam(1); + const string& type = c.getParam(0); + + if(prepareFile(*aSource, type, fname, aStartPos, aBytes, c.hasFlag("RE", 4))) { + Upload* u = aSource->getUpload(); + dcassert(u != NULL); + + AdcCommand cmd(AdcCommand::CMD_SND); + cmd.addParam(type).addParam(fname) + .addParam(Util::toString(u->getPos())) + .addParam(Util::toString(u->getSize() - u->getPos())); + + if(c.hasFlag("ZL", 4)) { + u->setStream(new FilteredInputStream<ZFilter, true>(u->getStream())); + u->setFlag(Upload::FLAG_ZUPLOAD); + cmd.addParam("ZL1"); + } + + aSource->send(cmd); + + u->setStart(GET_TICK()); + aSource->setState(UserConnection::STATE_RUNNING); + aSource->transmitFile(u->getStream()); + fire(UploadManagerListener::Starting(), u); + } +} + void UploadManager::on(UserConnectionListener::BytesSent, UserConnection* aSource, size_t aBytes, size_t aActual) throw() { - dcassert(aSource->getState() == UserConnection::STATE_DONE); + dcassert(aSource->getState() == UserConnection::STATE_RUNNING); Upload* u = aSource->getUpload(); dcassert(u != NULL); u->addPos(aBytes, aActual); @@ -285,7 +333,6 @@ Upload* u = aSource->getUpload(); if(u) { - aSource->setUpload(NULL); fire(UploadManagerListener::Failed(), u, aError); dcdebug("UM::onFailed: Removing upload\n"); @@ -296,35 +343,15 @@ } void UploadManager::on(UserConnectionListener::TransmitDone, UserConnection* aSource) throw() { - dcassert(aSource->getState() == UserConnection::STATE_DONE); + dcassert(aSource->getState() == UserConnection::STATE_RUNNING); Upload* u = aSource->getUpload(); dcassert(u != NULL); - aSource->setUpload(NULL); aSource->setState(UserConnection::STATE_GET); if(BOOLSETTING(LOG_UPLOADS) && !u->isSet(Upload::FLAG_TTH_LEAVES) && (BOOLSETTING(LOG_FILELIST_TRANSFERS) || !u->isSet(Upload::FLAG_USER_LIST))) { StringMap params; - params["source"] = u->getFileName(); - params["userNI"] = Util::toString(ClientManager::getInstance()->getNicks(aSource->getUser()->getCID())); - params["userI4"] = aSource->getRemoteIp(); - StringList hubNames = ClientManager::getInstance()->getHubNames(aSource->getUser()->getCID()); - if(hubNames.empty()) - hubNames.push_back(STRING(OFFLINE)); - params["hub"] = Util::toString(hubNames); - StringList hubs = ClientManager::getInstance()->getHubs(aSource->getUser()->getCID()); - if(hubs.empty()) - hubs.push_back(STRING(OFFLINE)); - params["hubURL"] = Util::toString(hubs); - params["fileSI"] = Util::toString(u->getSize()); - params["fileSIshort"] = Util::formatBytes(u->getSize()); - params["fileSIchunk"] = Util::toString(u->getTotal()); - params["fileSIchunkshort"] = Util::formatBytes(u->getTotal()); - params["fileSIactual"] = Util::toString(u->getActual()); - params["fileSIactualshort"] = Util::formatBytes(u->getActual()); - params["speed"] = Util::formatBytes(u->getAverageSpeed()) + "/s"; - params["time"] = Util::formatSeconds((GET_TICK() - u->getStart()) / 1000); - params["tth"] = u->getTTH().toBase32(); + u->getParams(*aSource, params); LOG(LogManager::UPLOAD, params); } @@ -332,15 +359,15 @@ removeUpload(u); } -void UploadManager::addFailedUpload(UserConnection::Ptr source, string filename) { +void UploadManager::addFailedUpload(const UserConnection& source, string filename) { { Lock l(cs); - if (!count_if(waitingUsers.begin(), waitingUsers.end(), UserMatch(source->getUser()))) - waitingUsers.push_back(WaitingUser(source->getUser(), GET_TICK())); - waitingFiles[source->getUser()].insert(filename); //files for which user's asked + if (!count_if(waitingUsers.begin(), waitingUsers.end(), UserMatch(source.getUser()))) + waitingUsers.push_back(WaitingUser(source.getUser(), GET_TICK())); + waitingFiles[source.getUser()].insert(filename); //files for which user's asked } - fire(UploadManagerListener::WaitingAddFile(), source->getUser(), filename); + fire(UploadManagerListener::WaitingAddFile(), source.getUser(), filename); } void UploadManager::clearUserFiles(const User::Ptr& source) { @@ -368,94 +395,65 @@ return waitingFiles.find(u)->second; } -void UploadManager::removeConnection(UserConnection::Ptr aConn) { - dcassert(aConn->getUpload() == NULL); - aConn->removeListener(this); - if(aConn->isSet(UserConnection::FLAG_HASSLOT)) { +void UploadManager::removeConnection(UserConnection* aSource) { + dcassert(aSource->getUpload() == NULL); + aSource->removeListener(this); + if(aSource->isSet(UserConnection::FLAG_HASSLOT)) { running--; - aConn->unsetFlag(UserConnection::FLAG_HASSLOT); + aSource->unsetFlag(UserConnection::FLAG_HASSLOT); } - if(aConn->isSet(UserConnection::FLAG_HASEXTRASLOT)) { + if(aSource->isSet(UserConnection::FLAG_HASEXTRASLOT)) { extra--; - aConn->unsetFlag(UserConnection::FLAG_HASEXTRASLOT); + aSource->unsetFlag(UserConnection::FLAG_HASEXTRASLOT); } } void UploadManager::on(TimerManagerListener::Minute, u_int32_t /* aTick */) throw() { - Lock l(cs); + User::List disconnects; + { + Lock l(cs); - UserList::iterator i = stable_partition(waitingUsers.begin(), waitingUsers.end(), WaitingUserFresh()); - for (UserList::iterator j = i; j != waitingUsers.end(); ++j) { - FilesMap::iterator fit = waitingFiles.find(j->first); - if (fit != waitingFiles.end()) waitingFiles.erase(fit); - fire(UploadManagerListener::WaitingRemoveUser(), j->first); - } + UserList::iterator i = stable_partition(waitingUsers.begin(), waitingUsers.end(), WaitingUserFresh()); + for (UserList::iterator j = i; j != waitingUsers.end(); ++j) { + FilesMap::iterator fit = waitingFiles.find(j->first); + if (fit != waitingFiles.end()) waitingFiles.erase(fit); + fire(UploadManagerListener::WaitingRemoveUser(), j->first); + } - waitingUsers.erase(i, waitingUsers.end()); + waitingUsers.erase(i, waitingUsers.end()); - if( BOOLSETTING(AUTO_KICK) ) { - for(Upload::Iter i = uploads.begin(); i != uploads.end(); ++i) { - Upload* u = *i; - if(u->getUser()->isOnline()) { - u->unsetFlag(Upload::FLAG_PENDING_KICK); - continue; - } + if( BOOLSETTING(AUTO_KICK) ) { + for(Upload::Iter i = uploads.begin(); i != uploads.end(); ++i) { + Upload* u = *i; + if(u->getUser()->isOnline()) { + u->unsetFlag(Upload::FLAG_PENDING_KICK); + continue; + } - if(u->isSet(Upload::FLAG_PENDING_KICK)) { - u->getUserConnection()->disconnect(true); - LogManager::getInstance()->message(STRING(DISCONNECTED_USER) + Util::toString(ClientManager::getInstance()->getNicks(u->getUser()->getCID()))); - } + if(u->isSet(Upload::FLAG_PENDING_KICK)) { + disconnects.push_back(u->getUser()); + continue; + } - if(BOOLSETTING(AUTO_KICK_NO_FAVS) && FavoriteManager::getInstance()->isFavoriteUser(u->getUser())) { - continue; - } + if(BOOLSETTING(AUTO_KICK_NO_FAVS) && FavoriteManager::getInstance()->isFavoriteUser(u->getUser())) { + continue; + } - u->setFlag(Upload::FLAG_PENDING_KICK); + u->setFlag(Upload::FLAG_PENDING_KICK); + } } } + for(User::Iter i = disconnects.begin(); i != disconnects.end(); ++i) { + LogManager::getInstance()->message(STRING(DISCONNECTED_USER) + Util::toString(ClientManager::getInstance()->getNicks((*i)->getCID()))); + ConnectionManager::getInstance()->disconnect(*i, false); + } } void UploadManager::on(GetListLength, UserConnection* conn) throw() { conn->listLen("42"); } -void UploadManager::on(AdcCommand::GET, UserConnection* aSource, const AdcCommand& c) throw() { - int64_t aBytes = Util::toInt64(c.getParam(3)); - int64_t aStartPos = Util::toInt64(c.getParam(2)); - const string& fname = c.getParam(1); - const string& type = c.getParam(0); - string tmp; - - if(prepareFile(aSource, type, fname, aStartPos, aBytes, c.hasFlag("RE", 4))) { - Upload* u = aSource->getUpload(); - dcassert(u != NULL); - if(aBytes == -1) - aBytes = u->getSize() - aStartPos; - - dcassert(aBytes >= 0); - - u->setStart(GET_TICK()); - - AdcCommand cmd(AdcCommand::CMD_SND); - cmd.addParam(c.getParam(0)); - cmd.addParam(c.getParam(1)); - cmd.addParam(Util::toString(u->getPos())); - cmd.addParam(Util::toString(u->getSize() - u->getPos())); - - if(c.hasFlag("ZL", 4)) { - u->setFile(new FilteredInputStream<ZFilter, true>(u->getFile())); - u->setFlag(Upload::FLAG_ZUPLOAD); - cmd.addParam("ZL1"); - } - - aSource->send(cmd); - aSource->setState(UserConnection::STATE_DONE); - aSource->transmitFile(u->getFile()); - fire(UploadManagerListener::Starting(), u); - } -} - void UploadManager::on(AdcCommand::GFI, UserConnection* aSource, const AdcCommand& c) throw() { if(c.getParameters().size() < 2) { aSource->send(AdcCommand(AdcCommand::SEV_RECOVERABLE, AdcCommand::ERROR_PROTOCOL_GENERIC, "Missing parameters")); @@ -465,22 +463,20 @@ const string& type = c.getParam(0); const string& ident = c.getParam(1); - if(type == "file") { - SearchResult::List l; - StringList sl; - - if(ident.compare(0, 4, "TTH/") != 0) { - aSource->send(AdcCommand(AdcCommand::SEV_RECOVERABLE, AdcCommand::ERROR_PROTOCOL_GENERIC, "Invalid identifier")); - return; + if(type == Transfer::TYPE_FILE) { + try { + string realFile = ShareManager::getInstance()->translateFileName(ident); + TTHValue tth = ShareManager::getInstance()->getTTH(ident); + string virtualFile = ShareManager::getInstance()->translateTTH(tth); + int64_t size = File::getSize(realFile); + SearchResult* sr = new SearchResult(SearchResult::TYPE_FILE, size, virtualFile, tth); + aSource->send(sr->toRES(AdcCommand::TYPE_CLIENT)); + sr->decRef(); + } catch(const ShareException&) { + aSource->fileNotAvail(); } - sl.push_back("TH" + ident.substr(4)); - ShareManager::getInstance()->search(l, sl, 1); - if(l.empty()) { - aSource->send(AdcCommand(AdcCommand::SEV_RECOVERABLE, AdcCommand::ERROR_FILE_NOT_AVAILABLE, "Not found")); - } else { - aSource->send(l[0]->toRES(AdcCommand::TYPE_CLIENT)); - l[0]->decRef(); - } + } else { + aSource->fileNotAvail(); } } Modified: dcplusplus/trunk/client/UploadManager.h =================================================================== --- dcplusplus/trunk/client/UploadManager.h 2006-09-29 16:24:13 UTC (rev 662) +++ dcplusplus/trunk/client/UploadManager.h 2006-10-06 21:18:32 UTC (rev 663) @@ -27,9 +27,10 @@ #include "Singleton.h" #include "ClientManagerListener.h" -#include "File.h" #include "MerkleTree.h" +class InputStream; + class Upload : public Transfer, public Flags { public: enum Flags { @@ -44,17 +45,13 @@ typedef vector<Ptr> List; typedef List::iterator Iter; - Upload() : file(0) { } - virtual ~Upload() { - delete file; - } + Upload(UserConnection& conn); + virtual ~Upload(); - User::Ptr& getUser() { dcassert(getUserConnection() != NULL); return getUserConnection()->getUser(); } + virtual void getParams(const UserConnection& aSource, StringMap& params); - GETSET(string, fileName, FileName); - GETSET(string, localFileName, LocalFileName); - GETSET(TTHValue, tth, TTH); - GETSET(InputStream*, file, File); + GETSET(string, sourceFile, SourceFile); + GETSET(InputStream*, stream, Stream); }; class UploadManagerListener { @@ -105,18 +102,6 @@ int getFreeSlots() { return max((SETTING(SLOTS) - running), 0); } /** @internal */ - bool getAutoSlot() { - /** A 0 in settings means disable */ - if(SETTING(MIN_UPLOAD_SPEED) == 0) - return false; - /** Only grant one slot per 30 sec */ - if(GET_TICK() < getLastGrant() + 30*1000) - return false; - /** Grant if upload speed is less than the threshold speed */ - return getAverageSpeed() < (SETTING(MIN_UPLOAD_SPEED)*1024); - } - - /** @internal */ int getFreeExtraSlots() { return max(3 - getExtra(), 0); } /** @param aUser Reserve an upload slot for this user and connect. */ @@ -163,13 +148,14 @@ //functions for manipulating waitingFiles and waitingUsers UserList waitingUsers; //this one merely lists the users waiting for slots FilesMap waitingFiles; //set of files which this user has asked for - void addFailedUpload(UserConnection::Ptr source, string filename); + void addFailedUpload(const UserConnection& source, string filename); friend class Singleton<UploadManager>; UploadManager() throw(); virtual ~UploadManager() throw(); - void removeConnection(UserConnection::Ptr aConn); + bool getAutoSlot(); + void removeConnection(UserConnection* aConn); void removeUpload(Upload* aUpload); // ClientManagerListener @@ -190,7 +176,7 @@ virtual void on(AdcCommand::GET, UserConnection*, const AdcCommand&) throw(); virtual void on(AdcCommand::GFI, UserConnection*, const AdcCommand&) throw(); - bool prepareFile(UserConnection* aSource, const string& aType, const string& aFile, int64_t aResume, int64_t aBytes, bool listRecursive = false); + bool prepareFile(UserConnection& aSource, const string& aType, const string& aFile, int64_t aResume, int64_t aBytes, bool listRecursive = false); }; #endif // !defined(UPLOAD_MANAGER_H) Modified: dcplusplus/trunk/client/UserConnection.cpp =================================================================== --- dcplusplus/trunk/client/UserConnection.cpp 2006-09-29 16:24:13 UTC (rev 662) +++ dcplusplus/trunk/client/UserConnection.cpp 2006-10-06 21:18:32 UTC (rev 663) @@ -21,6 +21,7 @@ #include "UserConnection.h" #include "ClientManager.h" +#include "ResourceManager.h" #include "StringTokenizer.h" #include "AdcCommand.h" @@ -37,9 +38,19 @@ const string UserConnection::FILE_NOT_AVAILABLE = "File Not Available"; +const string Transfer::TYPE_FILE = "file"; +const string Transfer::TYPE_LIST = "list"; +const string Transfer::TYPE_TTHL = "tthl"; + +const string Transfer::USER_LIST_NAME = "files.xml"; +const string Transfer::USER_LIST_NAME_BZ = "files.xml.bz2"; + const string UserConnection::UPLOAD = "Upload"; const string UserConnection::DOWNLOAD = "Download"; +Transfer::Transfer(UserConnection& conn) : start(0), lastTick(GET_TICK()), runningAverage(0), +last(0), actual(0), pos(0), startPos(0), size(-1), userConnection(conn) { } + void Transfer::updateRunningAverage() { u_int32_t tick = GET_TICK(); if(tick > lastTick) { @@ -64,6 +75,32 @@ lastTick = tick; } +void Transfer::getParams(const UserConnection& aSource, StringMap& params) { + params["userNI"] = Util::toString(ClientManager::getInstance()->getNicks(aSource.getUser()->getCID())); + params["userI4"] = aSource.getRemoteIp(); + StringList hubNames = ClientManager::getInstance()->getHubNames(aSource.getUser()->getCID()); + if(hubNames.empty()) + hubNames.push_back(STRING(OFFLINE)); + params["hub"] = Util::toString(hubNames); + StringList hubs = ClientManager::getInstance()->getHubs(aSource.getUser()->getCID()); + if(hubs.empty()) + hubs.push_back(STRING(OFFLINE)); + params["hubURL"] = Util::toString(hubs); + params["fileSI"] = Util::toString(getSize()); + params["fileSIshort"] = Util::formatBytes(getSize()); + params["fileSIchunk"] = Util::toString(getTotal()); + params["fileSIchunkshort"] = Util::formatBytes(getTotal()); + params["fileSIactual"] = Util::toString(getActual()); + params["fileSIactualshort"] = Util::formatBytes(getActual()); + params["speed"] = Util::formatBytes(getAverageSpeed()) + "/s"; + params["time"] = Util::formatSeconds((GET_TICK() - getStart()) / 1000); + params["fileTR"] = getTTH().toBase32(); +} + +User::Ptr Transfer::getUser() { + return getUserConnection().getUser(); +} + void UserConnection::on(BufferedSocketListener::Line, const string& aLine) throw () { if(aLine.length() < 2) Modified: dcplusplus/trunk/client/UserConnection.h =================================================================== --- dcplusplus/trunk/client/UserConnection.h 2006-09-29 16:24:13 UTC (rev 662) +++ dcplusplus/trunk/client/UserConnection.h 2006-10-06 21:18:32 UTC (rev 663) @@ -30,6 +30,7 @@ #include "File.h" #include "User.h" #include "AdcCommand.h" +#include "MerkleTree.h" class UserConnection; @@ -46,6 +47,7 @@ typedef X<5> Key; typedef X<6> Direction; typedef X<7> Get; + typedef X<8> Error; typedef X<10> Sending; typedef X<11> FileLength; typedef X<12> Send; @@ -63,6 +65,7 @@ virtual void on(BytesSent, UserConnection*, size_t, size_t) throw() { } virtual void on(Connected, UserConnection*) throw() { } virtual void on(Data, UserConnection*, const u_int8_t*, size_t) throw() { } + virtual void on(Error, UserConnection*, const string&) throw() { } virtual void on(Failed, UserConnection*, const string&) throw() { } virtual void on(CLock, UserConnection*, const string&, const string&) throw() { } virtual void on(Key, UserConnection*, const string&) throw() { } @@ -92,10 +95,16 @@ class Transfer { public: - Transfer() : userConnection(NULL), start(0), lastTick(GET_TICK()), runningAverage(0), - last(0), actual(0), pos(0), startPos(0), size(-1) { } - virtual ~Transfer() { } + static const string TYPE_FILE; ///< File transfer + static const string TYPE_LIST; ///< Partial file list + static const string TYPE_TTHL; ///< TTH Leaves + static const string USER_LIST_NAME; + static const string USER_LIST_NAME_BZ; + + Transfer(UserConnection& conn); + virtual ~Transfer() { }; + int64_t getPos() const { return pos; } void setPos(int64_t aPos) { pos = aPos; } @@ -113,7 +122,6 @@ int64_t getSize() const { return size; } void setSize(int64_t aSize) { size = aSize; } - void setSize(const string& aSize) { setSize(Util::toInt64(aSize)); } int64_t getAverageSpeed() const { int64_t diff = (int64_t)(GET_TICK() - getStart()); @@ -130,10 +138,17 @@ return getSize() - getPos(); } - GETSET(UserConnection*, userConnection, UserConnection); + virtual void getParams(const UserConnection& aSource, StringMap& params); + + User::Ptr getUser(); + + UserConnection& getUserConnection() { return userConnection; } + const UserConnection& getUserConnection() const { return userConnection; } + GETSET(u_int32_t, start, Start); GETSET(u_int32_t, lastTick, LastTick); GETSET(int64_t, runningAverage, RunningAverage); + GETSET(TTHValue, tth, TTH); private: Transfer(const Transfer&); Transfer& operator=(const Transfer&); @@ -149,6 +164,7 @@ /** Target size of this transfer */ int64_t size; + UserConnection& userConnection; }; class ServerSocket; @@ -214,9 +230,10 @@ STATE_KEY, // UploadManager - STATE_GET, - STATE_SEND, - STATE_DONE, + STATE_GET, // Waiting for GET + STATE_SEND, // Waiting for $Send + STATE_RUNNING, // Transmitting data + // DownloadManager STATE_FILELENGTH, STATE_TREE @@ -273,6 +290,7 @@ return isSet(FLAG_UPLOAD) ? UPLOAD : DOWNLOAD; } + const User::Ptr& getUser() const { return user... [truncated message content] |