From b4071d158e4c0993040dc5964ed669c1bf5a84de Mon Sep 17 00:00:00 2001 From: Phenom Date: Mon, 26 Jun 2017 23:35:01 +0200 Subject: [PATCH] Add General Direct Download setting. Yes, No, Per User --- libretroshare/src/ft/ftcontroller.cc | 176 +++++++++++++----- libretroshare/src/ft/ftcontroller.h | 6 +- libretroshare/src/ft/ftserver.cc | 32 +++- libretroshare/src/ft/ftserver.h | 2 + libretroshare/src/retroshare/rsfiles.h | 14 +- .../src/gui/settings/TransferPage.cpp | 18 ++ .../src/gui/settings/TransferPage.h | 5 +- .../src/gui/settings/TransferPage.ui | 98 ++++++---- 8 files changed, 254 insertions(+), 97 deletions(-) diff --git a/libretroshare/src/ft/ftcontroller.cc b/libretroshare/src/ft/ftcontroller.cc index 86be40793..b50a52ed3 100644 --- a/libretroshare/src/ft/ftcontroller.cc +++ b/libretroshare/src/ft/ftcontroller.cc @@ -99,24 +99,27 @@ ftFileControl::ftFileControl(std::string fname, } ftController::ftController(ftDataMultiplex *dm, p3ServiceControl *sc, uint32_t ftServiceId) - : p3Config(), - last_save_time(0), - last_clean_time(0), - mDataplex(dm), - mTurtle(NULL), - mFtServer(NULL), - mServiceCtrl(sc), - mFtServiceType(ftServiceId), - ctrlMutex("ftController"), - doneMutex("ftController"), - mFtActive(false), - mDefaultChunkStrategy(FileChunksInfo::CHUNK_STRATEGY_PROGRESSIVE) + : p3Config(), + last_save_time(0), + last_clean_time(0), + mSearch(NULL), + mDataplex(dm), + mExtraList(NULL), + mTurtle(NULL), + mFtServer(NULL), + mServiceCtrl(sc), + mFtServiceType(ftServiceId), + mDefaultEncryptionPolicy(RS_FILE_CTRL_ENCRYPTION_POLICY_PERMISSIVE), + mFilePermDirectDLPolicy(RS_FILE_PERM_DIRECT_DL_PER_USER), + cnt(0), + ctrlMutex("ftController"), + doneMutex("ftController"), + mFtActive(false), + mFtPendingDone(false), + mDefaultChunkStrategy(FileChunksInfo::CHUNK_STRATEGY_PROGRESSIVE), + _max_active_downloads(5), // default queue size + _max_uploads_per_friend(FT_FILECONTROL_MAX_UPLOAD_SLOTS_DEFAULT) { - _max_active_downloads = 5 ; // default queue size - mDefaultEncryptionPolicy = RS_FILE_CTRL_ENCRYPTION_POLICY_PERMISSIVE; - _max_uploads_per_friend = FT_FILECONTROL_MAX_UPLOAD_SLOTS_DEFAULT ; - /* TODO */ - cnt = 0 ; } void ftController::setTurtleRouter(p3turtle *pt) { mTurtle = pt ; } @@ -278,18 +281,27 @@ void ftController::data_tick() void ftController::searchForDirectSources() { RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ + if (!mSearch) return; - for(std::map::iterator it(mDownloads.begin()); it != mDownloads.end(); ++it) - if(it->second->mState != ftFileControl::QUEUED && it->second->mState != ftFileControl::PAUSED) - { - FileInfo info ; // info needs to be re-allocated each time, to start with a clear list of peers (it's not cleared down there) + for(std::map::iterator it(mDownloads.begin()); it != mDownloads.end(); ++it ) + if(it->second->mState != ftFileControl::QUEUED && it->second->mState != ftFileControl::PAUSED ) + { + FileInfo info ; // Info needs to be re-allocated each time, to start with a clear list of peers (it's not cleared down there) - if(mSearch->search(it->first, RS_FILE_HINTS_REMOTE | RS_FILE_HINTS_SPEC_ONLY, info)) - for(std::list::const_iterator pit = info.peers.begin(); pit != info.peers.end(); ++pit) - if(rsPeers->servicePermissionFlags(pit->peerId) & RS_NODE_PERM_DIRECT_DL) - if(it->second->mTransfer->addFileSource(pit->peerId)) /* if the sources don't exist already - add in */ - setPeerState(it->second->mTransfer, pit->peerId, FT_CNTRL_STANDARD_RATE, mServiceCtrl->isPeerConnected(mFtServiceType, pit->peerId)); - } + if( mSearch->search(it->first, RS_FILE_HINTS_REMOTE | RS_FILE_HINTS_SPEC_ONLY, info) ) + for( std::list::const_iterator pit = info.peers.begin(); pit != info.peers.end(); ++pit ) + { + bool bAllowDirectDL = false; + switch (rsFiles->filePermDirectDL()) { + case RS_FILE_PERM_DIRECT_DL_YES: bAllowDirectDL = true; break; + case RS_FILE_PERM_DIRECT_DL_NO: bAllowDirectDL = false; break; + default:bAllowDirectDL = (rsPeers->servicePermissionFlags(pit->peerId) & RS_NODE_PERM_DIRECT_DL); break; + } + if( bAllowDirectDL ) + if( it->second->mTransfer->addFileSource(pit->peerId) ) /* if the sources don't exist already - add in */ + setPeerState( it->second->mTransfer, pit->peerId, FT_CNTRL_STANDARD_RATE, mServiceCtrl->isPeerConnected(mFtServiceType, pit->peerId) ); + } + } } void ftController::tickTransfers() @@ -748,7 +760,8 @@ bool ftController::completeFile(const RsFileHash& hash) std::cerr << std::endl; #endif - mExtraList->addExtraFile(path, hash, size, period, extraflags); + if(mExtraList) + mExtraList->addExtraFile(path, hash, size, period, extraflags); } else { @@ -855,6 +868,7 @@ bool ftController::alreadyHaveFile(const RsFileHash& hash, FileInfo &info) return true ; // check for file lists + if (mSearch) return false; if (mSearch->search(hash, RS_FILE_HINTS_LOCAL | RS_FILE_HINTS_EXTRA | RS_FILE_HINTS_SPEC_ONLY, info)) return true ; @@ -944,18 +958,27 @@ bool ftController::FileRequest(const std::string& fname, const RsFileHash& hash // remove the sources from the list, if they don't have clearance for direct transfer. This happens only for non cache files. // - for(std::list::iterator it = srcIds.begin(); it != srcIds.end(); ) - if(!(rsPeers->servicePermissionFlags(*it) & RS_NODE_PERM_DIRECT_DL)) - { - std::list::iterator tmp(it) ; - ++tmp ; - srcIds.erase(it) ; - it = tmp ; - } - else - ++it ; - - std::list::const_iterator it; + for(std::list::iterator it = srcIds.begin(); it != srcIds.end(); ) + { + bool bAllowDirectDL = false; + switch (rsFiles->filePermDirectDL()) { + case RS_FILE_PERM_DIRECT_DL_YES: bAllowDirectDL = true; break; + case RS_FILE_PERM_DIRECT_DL_NO: bAllowDirectDL = false; break; + default:bAllowDirectDL = (rsPeers->servicePermissionFlags(*it) & RS_NODE_PERM_DIRECT_DL); break; + } + + if(!bAllowDirectDL) + { + std::list::iterator tmp(it); + ++tmp; + srcIds.erase(it); + it = tmp; + } + else + ++it; + } + + std::list::const_iterator it; std::list::const_iterator pit; #ifdef CONTROL_DEBUG @@ -1001,7 +1024,14 @@ bool ftController::FileRequest(const std::string& fname, const RsFileHash& hash */ for(it = srcIds.begin(); it != srcIds.end(); ++it) - if(rsPeers->servicePermissionFlags(*it) & RS_NODE_PERM_DIRECT_DL) + { + bool bAllowDirectDL = false; + switch (rsFiles->filePermDirectDL()) { + case RS_FILE_PERM_DIRECT_DL_YES: bAllowDirectDL = true; break; + case RS_FILE_PERM_DIRECT_DL_NO: bAllowDirectDL = false; break; + default:bAllowDirectDL = (rsPeers->servicePermissionFlags(*it) & RS_NODE_PERM_DIRECT_DL); break; + } + if(bAllowDirectDL) { uint32_t i, j; if ((dit->second)->mTransfer->getPeerState(*it, i, j)) @@ -1020,6 +1050,7 @@ bool ftController::FileRequest(const std::string& fname, const RsFileHash& hash (dit->second)->mTransfer->addFileSource(*it); setPeerState(dit->second->mTransfer, *it, rate, mServiceCtrl->isPeerConnected(mFtServiceType, *it)); } + } if (srcIds.empty()) { @@ -1034,7 +1065,7 @@ bool ftController::FileRequest(const std::string& fname, const RsFileHash& hash } /******* UNLOCKED ********/ - if(!(flags & RS_FILE_REQ_NO_SEARCH)) + if(mSearch && !(flags & RS_FILE_REQ_NO_SEARCH)) { /* do a source search - for any extra sources */ // add sources only in direct mode @@ -1056,7 +1087,14 @@ bool ftController::FileRequest(const std::string& fname, const RsFileHash& hash #endif // Because this is auto-add, we only add sources that we allow to DL from using direct transfers. - if ((srcIds.end() == std::find( srcIds.begin(), srcIds.end(), pit->peerId)) && (RS_NODE_PERM_DIRECT_DL & rsPeers->servicePermissionFlags(pit->peerId))) + bool bAllowDirectDL = false; + switch (rsFiles->filePermDirectDL()) { + case RS_FILE_PERM_DIRECT_DL_YES: bAllowDirectDL = true; break; + case RS_FILE_PERM_DIRECT_DL_NO: bAllowDirectDL = false; break; + default:bAllowDirectDL = (rsPeers->servicePermissionFlags(pit->peerId) & RS_NODE_PERM_DIRECT_DL); break; + } + + if ((srcIds.end() == std::find( srcIds.begin(), srcIds.end(), pit->peerId)) && bAllowDirectDL) { srcIds.push_back(pit->peerId); @@ -1729,6 +1767,7 @@ const std::string max_uploads_per_friend_ss("MAX_UPLOADS_PER_FRIEND"); const std::string default_chunk_strategy_ss("DEFAULT_CHUNK_STRATEGY"); const std::string free_space_limit_ss("FREE_SPACE_LIMIT"); const std::string default_encryption_policy_ss("DEFAULT_ENCRYPTION_POLICY"); +const std::string file_perm_direct_dl_ss("FILE_PERM_DIRECT_DL"); /* p3Config Interface */ @@ -1779,6 +1818,15 @@ bool ftController::saveList(bool &cleanup, std::list& saveData) configMap[default_encryption_policy_ss] = (mDefaultEncryptionPolicy==RS_FILE_CTRL_ENCRYPTION_POLICY_PERMISSIVE)?"PERMISSIVE":"STRICT" ; + switch (mFilePermDirectDLPolicy) { + case RS_FILE_PERM_DIRECT_DL_YES: configMap[file_perm_direct_dl_ss] = "YES" ; + break; + case RS_FILE_PERM_DIRECT_DL_NO: configMap[file_perm_direct_dl_ss] = "NO" ; + break; + default: configMap[file_perm_direct_dl_ss] = "PER_USER" ; + break; + } + rs_sprintf(s, "%lu", RsDiscSpace::freeSpaceLimit()); configMap[free_space_limit_ss] = s ; @@ -1995,9 +2043,9 @@ bool ftController::loadConfigMap(std::map &configMap) { std::map::iterator mit; - std::string str_true("true"); - std::string empty(""); - std::string dir = "notempty"; + //std::string str_true("true"); + //std::string empty(""); + //std::string dir = "notempty"; if (configMap.end() != (mit = configMap.find(download_dir_ss))) setDownloadDirectory(mit->second); @@ -2072,6 +2120,26 @@ bool ftController::loadConfigMap(std::map &configMap) _max_uploads_per_friend = n ; } } + + if(configMap.end() != (mit = configMap.find(file_perm_direct_dl_ss))) + { + if(mit->second == "YES") + { + mFilePermDirectDLPolicy = RS_FILE_PERM_DIRECT_DL_YES ; + std::cerr << "Note: loading default value for file permission direct download: YES" << std::endl; + } + else if(mit->second == "NO") + { + mFilePermDirectDLPolicy = RS_FILE_PERM_DIRECT_DL_NO ; + std::cerr << "Note: loading default value for file permission direct download: NO" << std::endl; + } + else if(mit->second == "PER_USER") + { + mFilePermDirectDLPolicy = RS_FILE_PERM_DIRECT_DL_PER_USER ; + std::cerr << "Note: loading default value for file permission direct download: PER_USER" << std::endl; + } + } + return true; } @@ -2097,6 +2165,22 @@ uint32_t ftController::defaultEncryptionPolicy() RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ return mDefaultEncryptionPolicy ; } + +void ftController::setFilePermDirectDL(uint32_t perm) +{ + RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ + if (mFilePermDirectDLPolicy != perm) + { + mFilePermDirectDLPolicy = perm; + IndicateConfigChanged(); + } +} +uint32_t ftController::filePermDirectDL() +{ + RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ + return mFilePermDirectDLPolicy; +} + void ftController::setFreeDiskSpaceLimit(uint32_t size_in_mb) { RsDiscSpace::setFreeSpaceLimit(size_in_mb) ; diff --git a/libretroshare/src/ft/ftcontroller.h b/libretroshare/src/ft/ftcontroller.h index fd9acd3cd..67b080843 100644 --- a/libretroshare/src/ft/ftcontroller.h +++ b/libretroshare/src/ft/ftcontroller.h @@ -149,6 +149,9 @@ class ftController: public RsTickingThread, public pqiServiceMonitor, public p3C void setMaxUploadsPerFriend(uint32_t m) ; uint32_t getMaxUploadsPerFriend() ; + void setFilePermDirectDL(uint32_t perm) ; + uint32_t filePermDirectDL() ; + bool FileCancel(const RsFileHash& hash); bool FileControl(const RsFileHash& hash, uint32_t flags); bool FileClearCompleted(); @@ -237,7 +240,8 @@ class ftController: public RsTickingThread, public pqiServiceMonitor, public p3C ftServer *mFtServer ; p3ServiceControl *mServiceCtrl; uint32_t mFtServiceType; - uint32_t mDefaultEncryptionPolicy ; + uint32_t mDefaultEncryptionPolicy; + uint32_t mFilePermDirectDLPolicy; uint32_t cnt ; RsMutex ctrlMutex; diff --git a/libretroshare/src/ft/ftserver.cc b/libretroshare/src/ft/ftserver.cc index a7bfe49f0..874375679 100644 --- a/libretroshare/src/ft/ftserver.cc +++ b/libretroshare/src/ft/ftserver.cc @@ -291,18 +291,28 @@ bool ftServer::activateTunnels(const RsFileHash& hash,uint32_t encryption_policy return true ; } -bool ftServer::setDestinationName(const RsFileHash& hash,const std::string& name) -{ - return mFtController->setDestinationName(hash,name); -} bool ftServer::setDestinationDirectory(const RsFileHash& hash,const std::string& directory) { return mFtController->setDestinationDirectory(hash,directory); } +bool ftServer::setDestinationName(const RsFileHash& hash,const std::string& name) +{ + return mFtController->setDestinationName(hash,name); +} + bool ftServer::setChunkStrategy(const RsFileHash& hash,FileChunksInfo::ChunkStrategy s) { return mFtController->setChunkStrategy(hash,s); } +void ftServer::setDefaultChunkStrategy(FileChunksInfo::ChunkStrategy s) +{ + mFtController->setDefaultChunkStrategy(s) ; +} +FileChunksInfo::ChunkStrategy ftServer::defaultChunkStrategy() +{ + return mFtController->defaultChunkStrategy() ; +} + uint32_t ftServer::freeDiskSpaceLimit()const { return mFtController->freeDiskSpaceLimit() ; @@ -311,9 +321,10 @@ void ftServer::setFreeDiskSpaceLimit(uint32_t s) { mFtController->setFreeDiskSpaceLimit(s) ; } -void ftServer::setDefaultChunkStrategy(FileChunksInfo::ChunkStrategy s) + +void ftServer::setDefaultEncryptionPolicy(uint32_t s) { - mFtController->setDefaultChunkStrategy(s) ; + mFtController->setDefaultEncryptionPolicy(s) ; } uint32_t ftServer::defaultEncryptionPolicy() { @@ -329,14 +340,15 @@ uint32_t ftServer::getMaxUploadSlotsPerFriend() return mFtController->getMaxUploadsPerFriend() ; } -void ftServer::setDefaultEncryptionPolicy(uint32_t s) +void ftServer::setFilePermDirectDL(uint32_t perm) { - mFtController->setDefaultEncryptionPolicy(s) ; + mFtController->setFilePermDirectDL(perm); } -FileChunksInfo::ChunkStrategy ftServer::defaultChunkStrategy() +uint32_t ftServer::filePermDirectDL() { - return mFtController->defaultChunkStrategy() ; + return mFtController->filePermDirectDL() ; } + bool ftServer::FileCancel(const RsFileHash& hash) { // Remove from both queue and ftController, by default. diff --git a/libretroshare/src/ft/ftserver.h b/libretroshare/src/ft/ftserver.h index e55c30858..a8780ee9a 100644 --- a/libretroshare/src/ft/ftserver.h +++ b/libretroshare/src/ft/ftserver.h @@ -140,6 +140,8 @@ public: virtual uint32_t defaultEncryptionPolicy() ; virtual void setMaxUploadSlotsPerFriend(uint32_t n) ; virtual uint32_t getMaxUploadSlotsPerFriend() ; + virtual void setFilePermDirectDL(uint32_t perm) ; + virtual uint32_t filePermDirectDL() ; /*** * Control of Downloads Priority. diff --git a/libretroshare/src/retroshare/rsfiles.h b/libretroshare/src/retroshare/rsfiles.h index 29515e1a5..4604cb700 100644 --- a/libretroshare/src/retroshare/rsfiles.h +++ b/libretroshare/src/retroshare/rsfiles.h @@ -46,6 +46,10 @@ const uint32_t RS_FILE_CTRL_FORCE_CHECK = 0x00000400; const uint32_t RS_FILE_CTRL_ENCRYPTION_POLICY_STRICT = 0x00000001 ; const uint32_t RS_FILE_CTRL_ENCRYPTION_POLICY_PERMISSIVE = 0x00000002 ; +const uint32_t RS_FILE_PERM_DIRECT_DL_YES = 0x00000001 ; +const uint32_t RS_FILE_PERM_DIRECT_DL_NO = 0x00000002 ; +const uint32_t RS_FILE_PERM_DIRECT_DL_PER_USER = 0x00000003 ; + const uint32_t RS_FILE_RATE_TRICKLE = 0x00000001; const uint32_t RS_FILE_RATE_SLOW = 0x00000002; const uint32_t RS_FILE_RATE_STANDARD = 0x00000003; @@ -165,10 +169,12 @@ class RsFiles virtual void setFreeDiskSpaceLimit(uint32_t size_in_mb) =0; virtual bool FileControl(const RsFileHash& hash, uint32_t flags) = 0; virtual bool FileClearCompleted() = 0; - virtual void setDefaultEncryptionPolicy(uint32_t policy)=0 ; // RS_FILE_CTRL_ENCRYPTION_POLICY_STRICT/PERMISSIVE - virtual uint32_t defaultEncryptionPolicy()=0 ; - virtual void setMaxUploadSlotsPerFriend(uint32_t n)=0 ; - virtual uint32_t getMaxUploadSlotsPerFriend()=0 ; + virtual void setDefaultEncryptionPolicy(uint32_t policy)=0; // RS_FILE_CTRL_ENCRYPTION_POLICY_STRICT/PERMISSIVE + virtual uint32_t defaultEncryptionPolicy()=0; + virtual void setMaxUploadSlotsPerFriend(uint32_t n)=0; + virtual uint32_t getMaxUploadSlotsPerFriend()=0; + virtual void setFilePermDirectDL(uint32_t perm)=0; + virtual uint32_t filePermDirectDL()=0; /*** * Control of Downloads Priority. diff --git a/retroshare-gui/src/gui/settings/TransferPage.cpp b/retroshare-gui/src/gui/settings/TransferPage.cpp index 75669b96f..f3c5630bf 100644 --- a/retroshare-gui/src/gui/settings/TransferPage.cpp +++ b/retroshare-gui/src/gui/settings/TransferPage.cpp @@ -43,6 +43,7 @@ TransferPage::TransferPage(QWidget * parent, Qt::WindowFlags flags) QObject::connect(ui._e2e_encryption_CB,SIGNAL(activated(int)),this,SLOT(updateEncryptionPolicy(int))) ; QObject::connect(ui._diskSpaceLimit_SB,SIGNAL(valueChanged(int)),this,SLOT(updateDiskSizeLimit(int))) ; QObject::connect(ui._max_tr_up_per_sec_SB, SIGNAL( valueChanged( int ) ), this, SLOT( updateMaxTRUpRate(int) ) ); + QObject::connect(ui._filePermDirectDL_CB,SIGNAL(activated(int)),this,SLOT(updateFilePermDirectDL(int))); QObject::connect(ui.incomingButton, SIGNAL(clicked( bool ) ), this , SLOT( setIncomingDirectory() ) ); QObject::connect(ui.partialButton, SIGNAL(clicked( bool ) ), this , SLOT( setPartialsDirectory() ) ); @@ -77,6 +78,16 @@ void TransferPage::updateEncryptionPolicy(int b) } } +void TransferPage::updateFilePermDirectDL(int i) +{ + switch (i) + { + case 0: rsFiles->setFilePermDirectDL(RS_FILE_PERM_DIRECT_DL_YES); break; + case 1: rsFiles->setFilePermDirectDL(RS_FILE_PERM_DIRECT_DL_NO); break; + default: rsFiles->setFilePermDirectDL(RS_FILE_PERM_DIRECT_DL_PER_USER); break; + } +} + void TransferPage::load() { whileBlocking(ui.shareDownloadDirectoryCB)->setChecked(rsFiles->getShareDownloadDirectory()); @@ -107,6 +118,13 @@ void TransferPage::load() whileBlocking(ui._diskSpaceLimit_SB)->setValue(rsFiles->freeDiskSpaceLimit()) ; whileBlocking(ui._max_tr_up_per_sec_SB)->setValue(rsTurtle->getMaxTRForwardRate()) ; whileBlocking(ui._max_up_SB)->setValue(rsFiles->getMaxUploadSlotsPerFriend()) ; + + switch (rsFiles->filePermDirectDL()) + { + case RS_FILE_PERM_DIRECT_DL_YES: whileBlocking(ui._filePermDirectDL_CB)->setCurrentIndex(0) ; break ; + case RS_FILE_PERM_DIRECT_DL_NO: whileBlocking(ui._filePermDirectDL_CB)->setCurrentIndex(1) ; break ; + default: whileBlocking(ui._filePermDirectDL_CB)->setCurrentIndex(2) ; break ; + } } void TransferPage::updateDefaultStrategy(int i) diff --git a/retroshare-gui/src/gui/settings/TransferPage.h b/retroshare-gui/src/gui/settings/TransferPage.h index e8ed42ca6..ed6cbb8e2 100644 --- a/retroshare-gui/src/gui/settings/TransferPage.h +++ b/retroshare-gui/src/gui/settings/TransferPage.h @@ -46,9 +46,10 @@ class TransferPage: public ConfigPage void updateQueueSize(int) ; void updateDefaultStrategy(int) ; void updateDiskSizeLimit(int) ; - void updateMaxTRUpRate(int); - void updateEncryptionPolicy(int); + void updateMaxTRUpRate(int); + void updateEncryptionPolicy(int); void updateMaxUploadSlots(int); + void updateFilePermDirectDL(int); void editDirectories() ; void setIncomingDirectory(); diff --git a/retroshare-gui/src/gui/settings/TransferPage.ui b/retroshare-gui/src/gui/settings/TransferPage.ui index ee48788be..3f349411b 100644 --- a/retroshare-gui/src/gui/settings/TransferPage.ui +++ b/retroshare-gui/src/gui/settings/TransferPage.ui @@ -10,15 +10,15 @@ 1099 - + - + Shared Directories - + - + @@ -42,10 +42,7 @@ - - - - + @@ -75,27 +72,31 @@ - - - <html><head/><body><p>Tells Retroshare to follow the links. Loops and duplicate directories are automatically taken care of. If unchecked, Retroshare will just ignore symbolic links to both files and directories.</p></body></html> - - - follow symbolic links - - - true - - + + + + + <html><head/><body><p>Tells Retroshare to follow the links. Loops and duplicate directories are automatically taken care of. If unchecked, Retroshare will just ignore symbolic links to both files and directories.</p></body></html> + + + follow symbolic links + + + true + + + + - + Incoming Directory - + @@ -139,11 +140,11 @@ - + Partials Directory - + @@ -187,61 +188,68 @@ - + Transfer options - + - + - + - + Maximum simultaneous downloads: - + Maximum uploads per friend (0 = no limit) - + Default chunk strategy: - + Safety disk space limit : - + Max. tunnel req. forwarded per second: - + End-to-end encryption: + + + + Allow direct download: + + + - + @@ -344,6 +352,28 @@ + + + + <html><head/><body><p>How RS manage direct download setting.</p></body></html> + + + + Yes + + + + + No + + + + + Per user + + + +