From 1de28fca33d627b6c579e7aaa685bcd21ed98f24 Mon Sep 17 00:00:00 2001 From: Pablo Martin Date: Thu, 20 Mar 2025 10:05:51 +0100 Subject: [PATCH] vitaminate speedlimit with support for setting max connections --- UserGuide.md | 2 +- contrib/docs/commands/speedlimit.md | 12 ++-- src/megacmd.cpp | 14 ++-- src/megacmdcommonutils.h | 6 ++ src/megacmdexecuter.cpp | 103 ++++++++++++++++++++++------ 5 files changed, 105 insertions(+), 32 deletions(-) diff --git a/UserGuide.md b/UserGuide.md index 30a6e2f4..e0db35e1 100644 --- a/UserGuide.md +++ b/UserGuide.md @@ -214,7 +214,7 @@ Verbosity: You can increase the amount of information given by any command by pa * [`mv`](contrib/docs/commands/mv.md)`srcremotepath [--use-pcre] [srcremotepath2 srcremotepath3 ..] dstremotepath` Moves file(s)/folder(s) into a new location (all remotes) * [`rm`](contrib/docs/commands/rm.md)`[-r] [-f] [--use-pcre] remotepath` Deletes a remote file/folder * [`transfers`](contrib/docs/commands/transfers.md)`[-c TAG|-a] | [-r TAG|-a] | [-p TAG|-a] [--only-downloads | --only-uploads] [SHOWOPTIONS]` List or operate with transfers -* [`speedlimit`](contrib/docs/commands/speedlimit.md)`[-u|-d] [-h] [NEWLIMIT]` Displays/modifies upload/download rate limits +* [`speedlimit`](contrib/docs/commands/speedlimit.md)`[-u|-d|--upload-connections|--download-connections] [-h] [NEWLIMIT]` Displays/modifies upload/download rate limits * [`sync`](contrib/docs/commands/sync.md)`[localpath dstremotepath| [-dpe] [ID|localpath]` Controls synchronizations. * [`sync-issues`](contrib/docs/commands/sync-issues.md)`[[--detail (ID|--all)] [--limit=rowcount] [--disable-path-collapse]] | [--enable-warning|--disable-warning]` Show all issues with current syncs * [`sync-ignore`](contrib/docs/commands/sync-ignore.md)`[--show|[--add|--add-exclusion|--remove|--remove-exclusion] filter1 filter2 ...] (ID|localpath|DEFAULT)` Manages ignore filters for syncs diff --git a/contrib/docs/commands/speedlimit.md b/contrib/docs/commands/speedlimit.md index 5a5e6488..3639f078 100644 --- a/contrib/docs/commands/speedlimit.md +++ b/contrib/docs/commands/speedlimit.md @@ -1,16 +1,18 @@ ### speedlimit Displays/modifies upload/download rate limits -Usage: `speedlimit [-u|-d] [-h] [NEWLIMIT]` +Usage: `speedlimit [-u|-d|--upload-connections|--download-connections] [-h] [NEWLIMIT]`
 NEWLIMIT establish the new limit in size per second (0 = no limit)
  NEWLIMIT may include (B)ytes, (K)ilobytes, (M)egabytes, (G)igabytes & (T)erabytes.
   Examples: "1m12k3B" "3M". If no units are given, bytes are assumed
 
 Options:
- -d	Download speed limit
- -u	Upload speed limit
- -h	Human readable
+ -d                       Download speed limit
+ -u                       Upload speed limit
+ --upload-connections     Max number of connections for an upload transfer
+ --download-connections   Max number of connections for a download transfer
+ -h                       Human readable
 
-Notice: this limit will be saved for the next time you execute MEGAcmd server. They will be removed if you logout.
+Notice: these limits will be saved for the next time you execute MEGAcmd server. They will be removed if you logout.
 
diff --git a/src/megacmd.cpp b/src/megacmd.cpp index 6045cd77..32a381d7 100644 --- a/src/megacmd.cpp +++ b/src/megacmd.cpp @@ -514,6 +514,8 @@ void insertValidParamsPerCommand(set *validParams, string thecommand, se validParams->insert("u"); validParams->insert("d"); validParams->insert("h"); + validParams->insert("upload-connections"); + validParams->insert("download-connections"); } else if ("whoami" == thecommand) { @@ -1856,7 +1858,7 @@ const char * getUsageStr(const char *command, const HelpFlags& flags) } if (!strcmp(command, "speedlimit")) { - return "speedlimit [-u|-d] [-h] [NEWLIMIT]"; + return "speedlimit [-u|-d|--upload-connections|--download-connections] [-h] [NEWLIMIT]"; } if (!strcmp(command, "killsession")) { @@ -2964,11 +2966,13 @@ string getHelpStr(const char *command, const HelpFlags& flags = {}) os << " Examples: \"1m12k3B\" \"3M\". If no units are given, bytes are assumed" << endl; os << endl; os << "Options:" << endl; - os << " -d" << "\t" << "Download speed limit" << endl; - os << " -u" << "\t" << "Upload speed limit" << endl; - os << " -h" << "\t" << "Human readable" << endl; + os << " -d " << "Download speed limit" << endl; + os << " -u " << "Upload speed limit" << endl; + os << " --upload-connections " << "Max number of connections for an upload transfer" << endl; + os << " --download-connections " << "Max number of connections for a download transfer" << endl; + os << " -h " << "Human readable" << endl; os << endl; - os << "Notice: this limit will be saved for the next time you execute MEGAcmd server. They will be removed if you logout." << endl; + os << "Notice: these limits will be saved for the next time you execute MEGAcmd server. They will be removed if you logout." << endl; } else if (!strcmp(command, "killsession")) { diff --git a/src/megacmdcommonutils.h b/src/megacmdcommonutils.h index 89c671ef..a6a53e50 100644 --- a/src/megacmdcommonutils.h +++ b/src/megacmdcommonutils.h @@ -276,6 +276,12 @@ bool onlyZeroOrOneOf(Bools... args) return (args + ...) <= 1; } +template +bool onlyZeroOf(Bools... args) +{ + return (args + ...) == 0; +} + void printPercentageLineCerr(const char *title, long long completed, long long total, float percentDowloaded, bool cleanLineAfter = true); diff --git a/src/megacmdexecuter.cpp b/src/megacmdexecuter.cpp index 8583196e..f886e33b 100644 --- a/src/megacmdexecuter.cpp +++ b/src/megacmdexecuter.cpp @@ -2640,6 +2640,19 @@ int MegaCmdExecuter::actUponLogin(SynchronousRequestListener *srl, int timeout) long long maxspeedupload = ConfigurationManager::getConfigurationValue("maxspeedupload", -1); if (maxspeedupload != -1) api->setMaxUploadSpeed(maxspeedupload); + for (bool up :{true, false}) + { + auto megaCmdListener = std::make_unique(nullptr); + auto value = ConfigurationManager::getConfigurationValue(up ? "maxuploadconnections" : "maxdownloadconnections", -1); + api->setMaxConnections(up ? 1 : 0, value, megaCmdListener.get()); + megaCmdListener->wait(); + if (megaCmdListener->getError()->getErrorCode() != MegaError::API_OK) + { + LOG_err << "Failed to change max " << (up ? "upload" : "download") << " connections: " + << megaCmdListener->getError()->getErrorString(); + } + } + api->useHttpsOnly(ConfigurationManager::getConfigurationValue("https", false)); api->disableGfxFeatures(!ConfigurationManager::getConfigurationValue("graphics", true)); @@ -9187,59 +9200,107 @@ void MegaCmdExecuter::executecommand(vector words, map *clf } else if (words[0] == "speedlimit") { - if (words.size() > 2) + bool uploadSpeed = getFlag(clflags, "u"); + bool downloadSpeed = getFlag(clflags, "d"); + bool uploadCons = getFlag(clflags, "upload-connections"); + bool downloadCons = getFlag(clflags, "download-connections"); + + bool moreThanOne = !onlyZeroOrOneOf(uploadSpeed, downloadSpeed, uploadCons, downloadCons); + bool noParam = onlyZeroOf(uploadSpeed, downloadSpeed, uploadCons, downloadCons); + bool hr = getFlag(clflags,"h"); + + if (words.size() > 2 || moreThanOne) { setCurrentThreadOutCode(MCMD_EARGS); LOG_err << " " << getUsageStr("speedlimit"); return; } - if (words.size() > 1) + if (words.size() > 1) // setting { - long long maxspeed = textToSize(words[1].c_str()); - if (maxspeed == -1) + long long value = textToSize(words[1].c_str()); + if (value == -1) { string s = words[1] + "B"; - maxspeed = textToSize(s.c_str()); + value = textToSize(s.c_str()); } - if (!getFlag(clflags, "u") && !getFlag(clflags, "d")) + if (noParam) { - api->setMaxDownloadSpeed(maxspeed); - api->setMaxUploadSpeed(maxspeed); - ConfigurationManager::savePropertyValue("maxspeedupload", maxspeed); - ConfigurationManager::savePropertyValue("maxspeeddownload", maxspeed); + api->setMaxDownloadSpeed(value); + api->setMaxUploadSpeed(value); + ConfigurationManager::savePropertyValue("maxspeedupload", value); + ConfigurationManager::savePropertyValue("maxspeeddownload", value); } - else if (getFlag(clflags, "u")) + else if (uploadSpeed) { - api->setMaxUploadSpeed(maxspeed); - ConfigurationManager::savePropertyValue("maxspeedupload", maxspeed); + api->setMaxUploadSpeed(value); + ConfigurationManager::savePropertyValue("maxspeedupload", value); } - else if (getFlag(clflags, "d")) + else if (downloadSpeed) { - api->setMaxDownloadSpeed(maxspeed); - ConfigurationManager::savePropertyValue("maxspeeddownload", maxspeed); + api->setMaxDownloadSpeed(value); + ConfigurationManager::savePropertyValue("maxspeeddownload", value); + } + else if (uploadCons || downloadCons) + { + auto megaCmdListener = std::make_unique(nullptr); + api->setMaxConnections(uploadCons ? 1 : 0, value, megaCmdListener.get()); + if (!checkNoErrors(megaCmdListener.get(), uploadCons ? "change max upload connections" : "change max download connections")) + { + return; + } + + ConfigurationManager::savePropertyValue(uploadCons ? "maxuploadconnections" : "maxdownloadconnections", value); } } - bool hr = getFlag(clflags,"h"); - - if (!getFlag(clflags, "u") && !getFlag(clflags, "d")) + // listing: + if (noParam) { long long us = api->getMaxUploadSpeed(); long long ds = api->getMaxDownloadSpeed(); OUTSTREAM << "Upload speed limit = " << (us?sizeToText(us,false,hr):"unlimited") << ((us && hr)?"/s":(us?" B/s":"")) << endl; OUTSTREAM << "Download speed limit = " << (ds?sizeToText(ds,false,hr):"unlimited") << ((ds && hr)?"/s":(us?" B/s":"")) << endl; + auto upConns = ConfigurationManager::getConfigurationValue("maxuploadconnections", -1); + auto downConns = ConfigurationManager::getConfigurationValue("maxdownloadconnections", -1); + if (upConns != -1) + { + OUTSTREAM << "Upload max connections = " << upConns << std::endl; + } + if (downConns != -1) + { + OUTSTREAM << "Download max connections = " << downConns << std::endl;; + } } - else if (getFlag(clflags, "u")) + else if (uploadSpeed) { long long us = api->getMaxUploadSpeed(); OUTSTREAM << "Upload speed limit = " << (us?sizeToText(us,false,hr):"unlimited") << ((us && hr)?"/s":(us?" B/s":"")) << endl; } - else if (getFlag(clflags, "d")) + else if (downloadSpeed) { long long ds = api->getMaxDownloadSpeed(); OUTSTREAM << "Download speed limit = " << (ds?sizeToText(ds,false,hr):"unlimited") << ((ds && hr)?"/s":(ds?" B/s":"")) << endl; } + else if (uploadCons || downloadCons) + { + if (uploadCons) + { + auto upConns = ConfigurationManager::getConfigurationValue("maxuploadconnections", -1); + if (upConns != -1) + { + OUTSTREAM << "Upload max connections = " << upConns << std::endl;; + } + } + else + { + auto downConns = ConfigurationManager::getConfigurationValue("maxdownloadconnections", -1); + if (downConns != -1) + { + OUTSTREAM << "Download max connections = " << downConns << std::endl;; + } + } + } return; } else if (words[0] == "invite")