diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/configreader.cpp | 20 | ||||
-rw-r--r-- | src/modules.cpp | 1 | ||||
-rw-r--r-- | src/modules/m_password_hash.cpp | 4 | ||||
-rw-r--r-- | src/modules/m_safelist.cpp | 236 | ||||
-rw-r--r-- | src/stats.cpp | 2 | ||||
-rw-r--r-- | src/userprocess.cpp | 5 | ||||
-rw-r--r-- | src/users.cpp | 30 |
7 files changed, 41 insertions, 257 deletions
diff --git a/src/configreader.cpp b/src/configreader.cpp index 3fb60034d..21bfce3db 100644 --- a/src/configreader.cpp +++ b/src/configreader.cpp @@ -338,8 +338,8 @@ static bool ValidateMaxWho(ServerConfig* conf, const char*, const char*, ValueIt { if ((data.GetInteger() > 65535) || (data.GetInteger() < 1)) { - ServerInstance->Logs->Log("CONFIG",DEFAULT,"<performance:maxwho> size out of range, setting to default of 128."); - data.Set(128); + ServerInstance->Logs->Log("CONFIG",DEFAULT,"<performance:maxwho> size out of range, setting to default of 1024."); + data.Set(1024); } return true; } @@ -688,7 +688,19 @@ void ServerConfig::CrossCheckConnectBlocks(ServerConfig* current) if (ConfValue("connect", "pingfreq", i, tmpv, false)) me->pingtime = atol(tmpv.c_str()); if (ConfValue("connect", "sendq", i, tmpv, false)) - me->sendqmax = atol(tmpv.c_str()); + { + // attempt to guess a good hard/soft sendq from a single value + long value = atol(tmpv.c_str()); + if (value > 16384) + me->softsendqmax = value / 16; + else + me->softsendqmax = value; + me->hardsendqmax = value * 8; + } + if (ConfValue("connect", "softsendq", i, tmpv, false)) + me->softsendqmax = atol(tmpv.c_str()); + if (ConfValue("connect", "hardsendq", i, tmpv, false)) + me->hardsendqmax = atol(tmpv.c_str()); if (ConfValue("connect", "recvq", i, tmpv, false)) me->recvqmax = atol(tmpv.c_str()); if (ConfValue("connect", "localmax", i, tmpv, false)) @@ -770,7 +782,7 @@ static const InitialConfig Values[] = { {"options", "suffixpart", "", new ValueContainerChar (&ServerConfig::SuffixPart), DT_CHARPTR, NULL}, {"options", "fixedpart", "", new ValueContainerChar (&ServerConfig::FixedPart), DT_CHARPTR, NULL}, {"performance", "netbuffersize","10240", new ValueContainerInt (&ServerConfig::NetBufferSize), DT_INTEGER, ValidateNetBufferSize}, - {"performance", "maxwho", "128", new ValueContainerInt (&ServerConfig::MaxWhoResults), DT_INTEGER, ValidateMaxWho}, + {"performance", "maxwho", "1024", new ValueContainerInt (&ServerConfig::MaxWhoResults), DT_INTEGER, ValidateMaxWho}, {"options", "allowhalfop", "0", new ValueContainerBool (&ServerConfig::AllowHalfop), DT_BOOLEAN, ValidateHalfOp}, {"dns", "server", "", new ValueContainerChar (&ServerConfig::DNSServer), DT_IPADDRESS,ValidateDnsServer}, {"dns", "timeout", "5", new ValueContainerInt (&ServerConfig::dns_timeout), DT_INTEGER, NULL}, diff --git a/src/modules.cpp b/src/modules.cpp index 9e775ed1e..67c90b128 100644 --- a/src/modules.cpp +++ b/src/modules.cpp @@ -190,7 +190,6 @@ ModResult Module::OnUserList(User*, Channel*) { return MOD_RES_PASSTHRU; } ModResult Module::OnWhoisLine(User*, User*, int&, std::string&) { return MOD_RES_PASSTHRU; } void Module::OnBuildExemptList(MessageType, Channel*, User*, char, CUList&, const std::string&) { } void Module::OnGarbageCollect() { } -void Module::OnBufferFlushed(User*) { } void Module::OnText(User*, void*, int, const std::string&, char, CUList&) { } void Module::OnRunTestSuite() { } void Module::OnNamesListItem(User*, Membership*, std::string&, std::string&) { } diff --git a/src/modules/m_password_hash.cpp b/src/modules/m_password_hash.cpp index 011a592e7..12769acd4 100644 --- a/src/modules/m_password_hash.cpp +++ b/src/modules/m_password_hash.cpp @@ -29,6 +29,7 @@ class CommandMkpasswd : public Command CommandMkpasswd(Module* Creator, hashymodules &h, std::deque<std::string> &n) : Command(Creator, "MKPASSWD", 2), hashers(h), names(n) { syntax = "<hashtype> <any-text>"; + Penalty = 5; } void MakeHash(User* user, const char* algo, const char* stuff) @@ -57,9 +58,6 @@ class CommandMkpasswd : public Command CmdResult Handle (const std::vector<std::string>& parameters, User *user) { MakeHash(user, parameters[0].c_str(), parameters[1].c_str()); - // this hashing could take some time, increasing server load. - // Slow down the user if they are trying to flood mkpasswd requests - user->IncreasePenalty(5); return CMD_SUCCESS; } diff --git a/src/modules/m_safelist.cpp b/src/modules/m_safelist.cpp deleted file mode 100644 index 0160de7c2..000000000 --- a/src/modules/m_safelist.cpp +++ /dev/null @@ -1,236 +0,0 @@ -/* +------------------------------------+ - * | Inspire Internet Relay Chat Daemon | - * +------------------------------------+ - * - * InspIRCd: (C) 2002-2009 InspIRCd Development Team - * See: http://wiki.inspircd.org/Credits - * - * This program is free but copyrighted software; see - * the file COPYING for details. - * - * --------------------------------------------------- - */ - -#include "inspircd.h" - -/** Holds a users m_safelist state - */ -class ListData : public classbase -{ - public: - long list_start; - long list_position; - bool list_ended; - const std::string glob; - int minusers; - int maxusers; - - ListData() : list_start(0), list_position(0), list_ended(false) {}; - ListData(long pos, time_t t, const std::string &pattern, int mi, int ma) : list_start(t), list_position(pos), list_ended(false), glob(pattern), minusers(mi), maxusers(ma) {}; -}; - -/* $ModDesc: A module overriding /list, and making it safe - stop those sendq problems. */ - -class ModuleSafeList : public Module -{ - time_t ThrottleSecs; - size_t ServerNameSize; - int global_listing; - int LimitList; - SimpleExtItem<ListData> listData; - LocalIntExt listTime; - public: - ModuleSafeList() : listData("safelist_data", this), listTime("safelist_last", this) - { - OnRehash(NULL); - Extensible::Register(&listData); - Extensible::Register(&listTime); - Implementation eventlist[] = { I_OnBufferFlushed, I_OnPreCommand, I_On005Numeric, I_OnRehash }; - ServerInstance->Modules->Attach(eventlist, this, 4); - } - - ~ModuleSafeList() - { - } - - void OnRehash(User* user) - { - ConfigReader MyConf; - ThrottleSecs = MyConf.ReadInteger("safelist", "throttle", "60", 0, true); - LimitList = MyConf.ReadInteger("safelist", "maxlisters", "50", 0, true); - ServerNameSize = strlen(ServerInstance->Config->ServerName) + 4; - global_listing = 0; - } - - Version GetVersion() - { - return Version("A module overriding /list, and making it safe - stop those sendq problems.",VF_VENDOR,API_VERSION); - } - - - /* - * OnPreCommand() - * Intercept the LIST command. - */ - ModResult OnPreCommand(std::string &command, std::vector<std::string> ¶meters, User *user, bool validated, const std::string &original_line) - { - /* If the command doesnt appear to be valid, we dont want to mess with it. */ - if (!validated) - return MOD_RES_PASSTHRU; - - if (command == "LIST") - { - return this->HandleList(parameters, user); - } - return MOD_RES_PASSTHRU; - } - - /* - * HandleList() - * Handle (override) the LIST command. - */ - ModResult HandleList(const std::vector<std::string> ¶meters, User* user) - { - int pcnt = parameters.size(); - int minusers = 0, maxusers = 0; - - if (global_listing >= LimitList && !IS_OPER(user)) - { - user->WriteServ("NOTICE %s :*** Server load is currently too heavy. Please try again later.", user->nick.c_str()); - user->WriteNumeric(321, "%s Channel :Users Name",user->nick.c_str()); - user->WriteNumeric(323, "%s :End of channel list.",user->nick.c_str()); - return MOD_RES_DENY; - } - - /* First, let's check if the user is currently /list'ing */ - ListData *ld = listData.get(user); - - if (ld) - { - /* user is already /list'ing, we don't want to do shit. */ - return MOD_RES_DENY; - } - - /* Work around mIRC suckyness. YOU SUCK, KHALED! */ - if (pcnt == 1) - { - if (parameters[0][0] == '<') - { - maxusers = atoi(parameters[0].c_str()+1); - ServerInstance->Logs->Log("m_safelist",DEBUG,"Max users: %d", maxusers); - pcnt = 0; - } - else if (parameters[0][0] == '>') - { - minusers = atoi(parameters[0].c_str()+1); - ServerInstance->Logs->Log("m_safelist",DEBUG,"Min users: %d", minusers); - pcnt = 0; - } - } - - time_t last_list_time = listTime.get(user); - if (last_list_time && ServerInstance->Time() < last_list_time + ThrottleSecs) - { - user->WriteServ("NOTICE %s :*** Woah there, slow down a little, you can't /LIST so often!",user->nick.c_str()); - user->WriteNumeric(321, "%s Channel :Users Name",user->nick.c_str()); - user->WriteNumeric(323, "%s :End of channel list.",user->nick.c_str()); - return MOD_RES_DENY; - } - - /* - * start at channel 0! ;) - */ - ld = new ListData(0,ServerInstance->Time(), (pcnt && (parameters[0][0] != '<' && parameters[0][0] != '>')) ? parameters[0] : "*", minusers, maxusers); - listData.set(user, ld); - listTime.set(user, ServerInstance->Time()); - - user->WriteNumeric(321, "%s Channel :Users Name",user->nick.c_str()); - - global_listing++; - - return MOD_RES_DENY; - } - - void OnBufferFlushed(User* user) - { - char buffer[MAXBUF]; - ListData* ld = listData.get(user); - if (ld) - { - Channel* chan = NULL; - unsigned long amount_sent = 0; - do - { - chan = ServerInstance->GetChannelIndex(ld->list_position); - bool is_special = (chan && (chan->HasUser(user) || user->HasPrivPermission("channels/auspex"))); - long users = chan ? chan->GetUserCounter() : 0; - - bool too_few = (ld->minusers && (users <= ld->minusers)); - bool too_many = (ld->maxusers && (users >= ld->maxusers)); - - if (chan && (too_many || too_few)) - { - ld->list_position++; - continue; - } - - if (chan) - { - bool display = (InspIRCd::Match(chan->name, ld->glob) || (!chan->topic.empty() && InspIRCd::Match(chan->topic, ld->glob))); - - if (!users || !display) - { - ld->list_position++; - continue; - } - - /* +s, not in chan / not got channels/auspex */ - if (chan->IsModeSet('s') && !is_special) - { - ld->list_position++; - continue; - } - - if (chan->IsModeSet('p') && !is_special) - { - /* Channel is +p and user is outside/not privileged */ - int counter = snprintf(buffer, MAXBUF, "322 %s * %ld :", user->nick.c_str(), users); - amount_sent += counter + ServerNameSize; - user->WriteServ(std::string(buffer)); - } - else - { - /* User is in the channel/privileged, channel is not +s */ - int counter = snprintf(buffer, MAXBUF, "322 %s %s %ld :[+%s] %s", user->nick.c_str(), chan->name.c_str(), users, chan->ChanModes(is_special), chan->topic.c_str()); - amount_sent += counter + ServerNameSize; - user->WriteServ(std::string(buffer)); - } - } - else - { - if (!ld->list_ended) - { - ld->list_ended = true; - user->WriteNumeric(323, "%s :End of channel list.",user->nick.c_str()); - } - } - - ld->list_position++; - } - while ((chan != NULL) && (amount_sent < (user->MyClass->GetSendqMax() / 4))); - if (ld->list_ended) - { - listData.unset(user); - global_listing--; - } - } - } - - void On005Numeric(std::string &output) - { - output.append(" SAFELIST"); - } - -}; - -MODULE_INIT(ModuleSafeList) diff --git a/src/stats.cpp b/src/stats.cpp index ba1b19e9a..b7b92d9a6 100644 --- a/src/stats.cpp +++ b/src/stats.cpp @@ -79,7 +79,7 @@ void InspIRCd::DoStats(char statschar, User* user, string_list &results) for (ClassVector::iterator i = this->Config->Classes.begin(); i != this->Config->Classes.end(); i++) { ConnectClass* c = *i; - results.push_back(sn+" 218 "+user->nick+" Y "+ConvToStr(idx)+" "+ConvToStr(c->GetPingTime())+" 0 "+ConvToStr(c->GetSendqMax())+" :"+ + results.push_back(sn+" 218 "+user->nick+" Y "+ConvToStr(idx)+" "+ConvToStr(c->GetPingTime())+" 0 "+ConvToStr(c->GetSendqHardMax())+" :"+ ConvToStr(c->GetRecvqMax())+" "+ConvToStr(c->GetRegTimeout())); idx++; } diff --git a/src/userprocess.cpp b/src/userprocess.cpp index bc354fa6d..4da623590 100644 --- a/src/userprocess.cpp +++ b/src/userprocess.cpp @@ -61,11 +61,6 @@ void InspIRCd::DoBackgroundUserStuff() curr->OnDataReady(); } - if (curr->getSendQSize() == 0) - { - FOREACH_MOD(I_OnBufferFlushed,OnBufferFlushed(curr)); - } - switch (curr->registered) { case REG_ALL: diff --git a/src/users.cpp b/src/users.cpp index f5165edfa..1f38dfada 100644 --- a/src/users.cpp +++ b/src/users.cpp @@ -518,14 +518,17 @@ void User::OnDataReady() if (quitting) return; - if (MyClass && !HasPrivPermission("users/flood/increased-buffers") && recvq.length() > MyClass->GetRecvqMax()) + if (MyClass && recvq.length() > MyClass->GetRecvqMax() && !HasPrivPermission("users/flood/increased-buffers")) { ServerInstance->Users->QuitUser(this, "RecvQ exceeded"); ServerInstance->SNO->WriteToSnoMask('a', "User %s RecvQ of %lu exceeds connect class maximum of %lu", nick.c_str(), (unsigned long)recvq.length(), MyClass->GetRecvqMax()); } + unsigned long sendqmax = ULONG_MAX; + if (MyClass && !HasPrivPermission("users/flood/increased-buffers")) + sendqmax = MyClass->GetSendqSoftMax(); - while (this->Penalty < 10) + while (Penalty < 10 && getSendQSize() < sendqmax) { std::string line; line.reserve(MAXBUF); @@ -559,6 +562,9 @@ eol_found: ServerInstance->Parser->ProcessBuffer(line, this); } + // Add pseudo-penalty so that we continue processing after sendq recedes + if (Penalty == 0 && getSendQSize() >= sendqmax) + Penalty++; } void User::AddWriteBuf(const std::string &data) @@ -566,7 +572,7 @@ void User::AddWriteBuf(const std::string &data) // Don't bother sending text to remote users! if (IS_REMOTE(this)) return; - if (!quitting && MyClass && getSendQSize() + data.length() > MyClass->GetSendqMax() && !HasPrivPermission("users/flood/increased-buffers")) + if (!quitting && MyClass && getSendQSize() + data.length() > MyClass->GetSendqHardMax() && !HasPrivPermission("users/flood/increased-buffers")) { /* * Fix by brain - Set the error text BEFORE calling, because @@ -575,7 +581,7 @@ void User::AddWriteBuf(const std::string &data) */ ServerInstance->Users->QuitUser(this, "SendQ exceeded"); ServerInstance->SNO->WriteToSnoMask('a', "User %s SendQ of %lu exceeds connect class maximum of %lu", - nick.c_str(), (unsigned long)getSendQSize() + data.length(), MyClass->GetSendqMax()); + nick.c_str(), (unsigned long)getSendQSize() + data.length(), MyClass->GetSendqHardMax()); return; } @@ -1809,12 +1815,21 @@ const std::string FakeUser::GetFullRealHost() } ConnectClass::ConnectClass(char t, const std::string& mask) - : type(t), name("unnamed"), registration_timeout(0), host(mask), pingtime(0), pass(""), hash(""), sendqmax(0), recvqmax(0), maxlocal(0), maxglobal(0), maxchans(0), port(0), limit(0), RefCount(1) + : type(t), name("unnamed"), registration_timeout(0), host(mask), + pingtime(0), pass(""), hash(""), softsendqmax(0), hardsendqmax(0), + recvqmax(0), maxlocal(0), maxglobal(0), maxchans(0), port(0), limit(0), + RefCount(1) { } ConnectClass::ConnectClass(char t, const std::string& mask, const ConnectClass& parent) - : type(t), name("unnamed"), registration_timeout(parent.registration_timeout), host(mask), pingtime(parent.pingtime), pass(parent.pass), hash(parent.hash), sendqmax(parent.sendqmax), recvqmax(parent.recvqmax), maxlocal(parent.maxlocal), maxglobal(parent.maxglobal), maxchans(parent.maxchans), port(parent.port), limit(parent.limit), RefCount(1) + : type(t), name("unnamed"), + registration_timeout(parent.registration_timeout), host(mask), + pingtime(parent.pingtime), pass(parent.pass), hash(parent.hash), + softsendqmax(parent.softsendqmax), hardsendqmax(parent.hardsendqmax), + recvqmax(parent.recvqmax), maxlocal(parent.maxlocal), + maxglobal(parent.maxglobal), maxchans(parent.maxchans), + port(parent.port), limit(parent.limit), RefCount(1) { } @@ -1826,7 +1841,8 @@ void ConnectClass::Update(const ConnectClass* src) pingtime = src->pingtime; pass = src->pass; hash = src->hash; - sendqmax = src->sendqmax; + softsendqmax = src->softsendqmax; + hardsendqmax = src->hardsendqmax; recvqmax = src->recvqmax; maxlocal = src->maxlocal; maxglobal = src->maxglobal; |