#include "inspircd.h"
-#include <stdarg.h>
-#include "socketengine.h"
#include "xline.h"
-#include "bancache.h"
already_sent_t LocalUser::already_sent_id = 0;
ServerInstance->Logs->Log("USERS", LOG_DEBUG, "New UUID for user: %s", uuid.c_str());
- if (!ServerInstance->Users->uuidlist->insert(std::make_pair(uuid, this)).second)
+ if (!ServerInstance->Users->uuidlist.insert(std::make_pair(uuid, this)).second)
throw CoreException("Duplicate UUID "+std::string(uuid)+" in User constructor");
}
User::~User()
{
- if (ServerInstance->Users->uuidlist->find(uuid) != ServerInstance->Users->uuidlist->end())
- ServerInstance->Logs->Log("USERS", LOG_DEFAULT, "User destructor for %s called without cull", uuid.c_str());
}
const std::string& User::MakeHost()
recvq = recvq.substr(qpos);
// TODO should this be moved to when it was inserted in recvq?
- ServerInstance->stats->statsRecv += qpos;
+ ServerInstance->stats.Recv += qpos;
user->bytes_in += qpos;
user->cmds_in++;
- ServerInstance->Parser->ProcessBuffer(line, user);
+ ServerInstance->Parser.ProcessBuffer(line, user);
if (user->quitting)
return;
}
CullResult LocalUser::cull()
{
- ServerInstance->Users->local_users.erase(this);
ClearInvites();
eh.cull();
return User::cull();
// Fake users don't quit, they just get culled.
quitting = true;
// Fake users are not inserted into UserManager::clientlist, they're only in the uuidlist
- ServerInstance->Users->uuidlist->erase(uuid);
+ // and they are removed from there by the linking mod when the server splits
return User::cull();
}
{
this->AllowedUserModes.set();
}
- else if (*c >= 'A' && *c < 'z')
+ else if (*c >= 'A' && *c <= 'z')
{
this->AllowedUserModes[*c - 'A'] = true;
}
{
this->AllowedChanModes.set();
}
- else if (*c >= 'A' && *c < 'z')
+ else if (*c >= 'A' && *c <= 'z')
{
this->AllowedChanModes[*c - 'A'] = true;
}
ServerInstance->Modes->Process(parameters, this);
- /* remove the user from the oper list. Will remove multiple entries as a safeguard against bug #404 */
- ServerInstance->Users->all_opers.remove(this);
+ // Remove the user from the oper list
+ stdalgo::vector::swaperase(ServerInstance->Users->all_opers, this);
ModeHandler* opermh = ServerInstance->Modes->FindMode('o', MODETYPE_USER);
this->SetMode(opermh, false);
}
else if (clone_count)
{
- if ((a->GetMaxLocal()) && (ServerInstance->Users->LocalCloneCount(this) > a->GetMaxLocal()))
+ const UserManager::CloneCounts& clonecounts = ServerInstance->Users->GetCloneCounts(this);
+ if ((a->GetMaxLocal()) && (clonecounts.local > a->GetMaxLocal()))
{
ServerInstance->Users->QuitUser(this, "No more connections allowed from your host via this connect class (local)");
if (a->maxconnwarn)
ServerInstance->SNO->WriteToSnoMask('a', "WARNING: maximum LOCAL connections (%ld) exceeded for IP %s", a->GetMaxLocal(), this->GetIPString().c_str());
return;
}
- else if ((a->GetMaxGlobal()) && (ServerInstance->Users->GlobalCloneCount(this) > a->GetMaxGlobal()))
+ else if ((a->GetMaxGlobal()) && (clonecounts.global > a->GetMaxGlobal()))
{
ServerInstance->Users->QuitUser(this, "No more connections allowed from your host via this connect class (global)");
if (a->maxconnwarn)
void LocalUser::FullConnect()
{
- ServerInstance->stats->statsConnects++;
+ ServerInstance->stats.Connects++;
this->idle_lastmsg = ServerInstance->Time();
/*
return;
this->WriteNumeric(RPL_WELCOME, ":Welcome to the %s IRC Network %s", ServerInstance->Config->Network.c_str(), GetFullRealHost().c_str());
- this->WriteNumeric(RPL_YOURHOSTIS, ":Your host is %s, running version %s", ServerInstance->Config->ServerName.c_str(), BRANCH);
+ this->WriteNumeric(RPL_YOURHOSTIS, ":Your host is %s, running version %s", ServerInstance->Config->ServerName.c_str(), INSPIRCD_BRANCH);
this->WriteNumeric(RPL_SERVERCREATED, ":This server was created %s %s", __TIME__, __DATE__);
const std::string& modelist = ServerInstance->Modes->GetModeListFor004Numeric();
- this->WriteNumeric(RPL_SERVERVERSION, "%s %s %s", ServerInstance->Config->ServerName.c_str(), BRANCH, modelist.c_str());
+ this->WriteNumeric(RPL_SERVERVERSION, "%s %s %s", ServerInstance->Config->ServerName.c_str(), INSPIRCD_BRANCH, modelist.c_str());
ServerInstance->ISupport.SendTo(this);
std::vector<std::string> parameters;
FIRST_MOD_RESULT(OnPreCommand, MOD_RESULT, (command, parameters, this, true, command));
if (!MOD_RESULT)
- ServerInstance->Parser->CallHandler(command, parameters, this);
+ ServerInstance->Parser.CallHandler(command, parameters, this);
MOD_RESULT = MOD_RES_PASSTHRU;
command = "MOTD";
FIRST_MOD_RESULT(OnPreCommand, MOD_RESULT, (command, parameters, this, true, command));
if (!MOD_RESULT)
- ServerInstance->Parser->CallHandler(command, parameters, this);
+ ServerInstance->Parser.CallHandler(command, parameters, this);
if (ServerInstance->Config->RawLog)
WriteServ("PRIVMSG %s :*** Raw I/O logging is enabled on this server. All messages, passwords, and commands are being recorded.", nick.c_str());
ServerInstance->SNO->WriteToSnoMask('c',"Client connecting on port %d (class %s): %s (%s) [%s]",
this->GetServerPort(), this->MyClass->name.c_str(), GetFullRealHost().c_str(), this->GetIPString().c_str(), this->fullname.c_str());
ServerInstance->Logs->Log("BANCACHE", LOG_DEBUG, "BanCache: Adding NEGATIVE hit for " + this->GetIPString());
- ServerInstance->BanCache->AddHit(this->GetIPString(), "", "");
+ ServerInstance->BanCache.AddHit(this->GetIPString(), "", "");
// reset the flood penalty (which could have been raised due to things like auto +x)
CommandFloodPenalty = 0;
}
cached_fullrealhost.clear();
}
-bool User::ChangeNick(const std::string& newnick, bool force)
+bool User::ChangeNick(const std::string& newnick, time_t newts)
{
if (quitting)
{
return false;
}
- if (!force)
+ User* const InUse = ServerInstance->FindNickOnly(newnick);
+ if (InUse == this)
{
- ModResult MOD_RESULT;
- FIRST_MOD_RESULT(OnUserPreNick, MOD_RESULT, (this, newnick));
-
- if (MOD_RESULT == MOD_RES_DENY)
- {
- ServerInstance->stats->statsCollisions++;
- return false;
- }
- }
-
- if (assign(newnick) == assign(nick))
- {
- // case change, don't need to check Q:lines and such
+ // case change, don't need to check campers
// and, if it's identical including case, we can leave right now
+ // We also don't update the nick TS if it's a case change, either
if (newnick == nick)
return true;
}
else
{
- /*
- * Don't check Q:Lines if it's a server-enforced change, just on the off-chance some fucking *moron*
- * tries to Q:Line SIDs, also, this means we just get our way period, as it really should be.
- * Thanks Kein for finding this. -- w00t
- *
- * Also don't check Q:Lines for remote nickchanges, they should have our Q:Lines anyway to enforce themselves.
- * -- w00t
- */
- if (IS_LOCAL(this) && !force)
- {
- XLine* mq = ServerInstance->XLines->MatchesLine("Q",newnick);
- if (mq)
- {
- if (this->registered == REG_ALL)
- {
- ServerInstance->SNO->WriteGlobalSno('a', "Q-Lined nickname %s from %s: %s",
- newnick.c_str(), GetFullRealHost().c_str(), mq->reason.c_str());
- }
- this->WriteNumeric(ERR_ERRONEUSNICKNAME, "%s :Invalid nickname: %s", newnick.c_str(), mq->reason.c_str());
- return false;
- }
-
- if (ServerInstance->Config->RestrictBannedUsers)
- {
- for (UCListIter i = this->chans.begin(); i != this->chans.end(); i++)
- {
- Channel* chan = (*i)->chan;
- if (chan->GetPrefixValue(this) < VOICE_VALUE && chan->IsBanned(this))
- {
- this->WriteNumeric(ERR_CANNOTSENDTOCHAN, "%s :Cannot send to channel (you're banned)", chan->name.c_str());
- return false;
- }
- }
- }
- }
-
/*
* Uh oh.. if the nickname is in use, and it's not in use by the person using it (doh) --
* then we have a potential collide. Check whether someone else is camping on the nick
* If the guy using the nick is already using it, tell the incoming nick change to gtfo,
* because the nick is already (rightfully) in use. -- w00t
*/
- User* InUse = ServerInstance->FindNickOnly(newnick);
- if (InUse && (InUse != this))
+ if (InUse)
{
if (InUse->registered != REG_ALL)
{
/* force the camper to their UUID, and ask them to re-send a NICK. */
- InUse->WriteTo(InUse, "NICK %s", InUse->uuid.c_str());
+ InUse->WriteFrom(InUse, "NICK %s", InUse->uuid.c_str());
InUse->WriteNumeric(ERR_NICKNAMEINUSE, "%s :Nickname overruled.", InUse->nick.c_str());
- ServerInstance->Users->clientlist->erase(InUse->nick);
- (*(ServerInstance->Users->clientlist))[InUse->uuid] = InUse;
-
- InUse->nick = InUse->uuid;
- InUse->InvalidateCache();
InUse->registered &= ~REG_NICK;
+ InUse->ChangeNick(InUse->uuid);
}
else
{
return false;
}
}
+
+ age = newts ? newts : ServerInstance->Time();
}
if (this->registered == REG_ALL)
nick = newnick;
InvalidateCache();
- ServerInstance->Users->clientlist->erase(oldnick);
- (*(ServerInstance->Users->clientlist))[newnick] = this;
+ ServerInstance->Users->clientlist.erase(oldnick);
+ ServerInstance->Users->clientlist[newnick] = this;
if (registered == REG_ALL)
FOREACH_MOD(OnUserPostNick, (this,oldnick));
eh.AddWriteBuf(text);
eh.AddWriteBuf(wide_newline);
- ServerInstance->stats->statsSent += text.length() + 2;
+ ServerInstance->stats.Sent += text.length() + 2;
this->bytes_out += text.length() + 2;
this->cmds_out++;
}
this->WriteFrom(user, textbuffer);
}
-
-/* write text to an destination user from a source user (e.g. user privmsg) */
-
-void User::WriteTo(User *dest, const char *data, ...)
-{
- std::string textbuffer;
- VAFORMAT(textbuffer, data, data);
- this->WriteTo(dest, textbuffer);
-}
-
-void User::WriteTo(User *dest, const std::string &data)
-{
- dest->WriteFrom(this, data);
-}
-
void User::WriteCommon(const char* text, ...)
{
if (this->registered != REG_ALL || quitting)
this->WriteCommonRaw(textbuffer, true);
}
-void User::WriteCommonExcept(const char* text, ...)
-{
- if (this->registered != REG_ALL || quitting)
- return;
-
- std::string textbuffer;
- VAFORMAT(textbuffer, text, text);
- textbuffer = ":" + this->GetFullHost() + " " + textbuffer;
- this->WriteCommonRaw(textbuffer, false);
-}
-
void User::WriteCommonRaw(const std::string &line, bool include_self)
{
if (this->registered != REG_ALL || quitting)
for (IncludeChanList::const_iterator v = include_c.begin(); v != include_c.end(); ++v)
{
Channel* c = (*v)->chan;
- const UserMembList* ulist = c->GetUsers();
- for (UserMembList::const_iterator i = ulist->begin(); i != ulist->end(); i++)
+ const Channel::MemberMap& ulist = c->GetUsers();
+ for (Channel::MemberMap::const_iterator i = ulist.begin(); i != ulist.end(); ++i)
{
LocalUser* u = IS_LOCAL(i->first);
if (u && u->already_sent != LocalUser::already_sent_id)
}
for (IncludeChanList::const_iterator v = include_c.begin(); v != include_c.end(); ++v)
{
- const UserMembList* ulist = (*v)->chan->GetUsers();
- for (UserMembList::const_iterator i = ulist->begin(); i != ulist->end(); i++)
+ const Channel::MemberMap& ulist = (*v)->chan->GetUsers();
+ for (Channel::MemberMap::const_iterator i = ulist.begin(); i != ulist.end(); i++)
{
LocalUser* u = IS_LOCAL(i->first);
if (u && (u->already_sent != uniq_id))
bool User::SharesChannelWith(User *other)
{
/* Outer loop */
- for (UCListIter i = this->chans.begin(); i != this->chans.end(); i++)
+ for (User::ChanList::iterator i = this->chans.begin(); i != this->chans.end(); ++i)
{
/* Eliminate the inner loop (which used to be ~equal in size to the outer loop)
* by replacing it with a map::find which *should* be more efficient
FOREACH_MOD(OnChangeHost, (this,shost));
- this->dhost.assign(shost, 0, 64);
+ this->dhost.assign(shost, 0, ServerInstance->Config->Limits.MaxHost);
this->InvalidateCache();
if (IS_LOCAL(this))
return true;
}
-void User::SendAll(const char* command, const char* text, ...)
-{
- std::string textbuffer;
- VAFORMAT(textbuffer, text, text);
- const std::string message = ":" + this->GetFullHost() + " " + command + " $* :" + textbuffer;
-
- for (LocalUserList::const_iterator i = ServerInstance->Users->local_users.begin(); i != ServerInstance->Users->local_users.end(); i++)
- {
- if ((*i)->registered == REG_ALL)
- (*i)->Write(message);
- }
-}
-
/*
* Sets a user's connection class.
* If the class name is provided, it will be used. Otherwise, the class will be guessed using host/ip/ident/etc.
if (!explicit_name.empty())
{
- for (ClassVector::iterator i = ServerInstance->Config->Classes.begin(); i != ServerInstance->Config->Classes.end(); i++)
+ for (ServerConfig::ClassVector::const_iterator i = ServerInstance->Config->Classes.begin(); i != ServerInstance->Config->Classes.end(); ++i)
{
ConnectClass* c = *i;
}
else
{
- for (ClassVector::iterator i = ServerInstance->Config->Classes.begin(); i != ServerInstance->Config->Classes.end(); i++)
+ for (ServerConfig::ClassVector::const_iterator i = ServerInstance->Config->Classes.begin(); i != ServerInstance->Config->Classes.end(); ++i)
{
ConnectClass* c = *i;
ServerInstance->Logs->Log("CONNECTCLASS", LOG_DEBUG, "Checking %s", c->GetName().c_str());
void User::PurgeEmptyChannels()
{
// firstly decrement the count on each channel
- for (UCListIter i = this->chans.begin(); i != this->chans.end(); )
+ for (User::ChanList::iterator i = this->chans.begin(); i != this->chans.end(); )
{
Channel* c = (*i)->chan;
++i;
ConnectClass::ConnectClass(ConfigTag* tag, char t, const std::string& mask)
: config(tag), type(t), fakelag(true), name("unnamed"), registration_timeout(0), host(mask),
pingtime(0), softsendqmax(0), hardsendqmax(0), recvqmax(0),
- penaltythreshold(0), commandrate(0), maxlocal(0), maxglobal(0), maxconnwarn(true), maxchans(0),
+ penaltythreshold(0), commandrate(0), maxlocal(0), maxglobal(0), maxconnwarn(true), maxchans(ServerInstance->Config->MaxChans),
limit(0), resolvehostnames(true)
{
}