this->bound_user->dns_done = true;
strlcpy(this->bound_user->dhost, hostname.c_str(),64);
strlcpy(this->bound_user->host, hostname.c_str(),64);
+ /* Invalidate cache */
+ this->bound_user->InvalidateCache();
}
}
else
if (ServerInstance->SE->GetRef(this->bound_fd) == this->bound_user)
{
/* Error message here */
- this->bound_user->WriteServ("NOTICE Auth :*** Could not resolve your hostname, using your IP address (%s) instead.", this->bound_user->GetIPString());
+ this->bound_user->WriteServ("NOTICE Auth :*** Could not resolve your hostname: %s; using your IP address (%s) instead.", errormessage.c_str(), this->bound_user->GetIPString());
this->bound_user->dns_done = true;
}
}
return data;
}
+void userrec::DecrementModes()
+{
+ for (int n = 0; n < 64; n++)
+ {
+ if (modes[n])
+ {
+ ModeHandler* mh = ServerInstance->Modes->FindMode(n+65, MODETYPE_USER);
+ if (mh)
+ mh->ChangeCount(-1);
+ }
+ }
+}
+
userrec::userrec(InspIRCd* Instance) : ServerInstance(Instance)
{
ServerInstance->Log(DEBUG,"userrec::userrec(): Instance: %08x",ServerInstance);
invites.clear();
memset(modes,0,sizeof(modes));
memset(snomasks,0,sizeof(snomasks));
+ /* Invalidate cache */
+ cached_fullhost = cached_hostip = cached_makehost = cached_fullrealhost = NULL;
}
userrec::~userrec()
{
+ this->InvalidateCache();
+ this->DecrementModes();
if (ip)
{
clonemap::iterator x = ServerInstance->local_clones.find(this->GetIPString());
char* userrec::MakeHost()
{
- static char nhost[MAXBUF];
+ if (this->cached_makehost)
+ return this->cached_makehost;
+
+ char nhost[MAXBUF];
/* This is much faster than snprintf */
char* t = nhost;
for(char* n = ident; *n; n++)
for(char* n = host; *n; n++)
*t++ = *n;
*t = 0;
- return nhost;
+
+ this->cached_makehost = strdup(nhost);
+
+ return this->cached_makehost;
}
char* userrec::MakeHostIP()
{
- static char ihost[MAXBUF];
+ if (this->cached_hostip)
+ return this->cached_hostip;
+
+ char ihost[MAXBUF];
/* This is much faster than snprintf */
char* t = ihost;
for(char* n = ident; *n; n++)
for(const char* n = this->GetIPString(); *n; n++)
*t++ = *n;
*t = 0;
- return ihost;
+
+ this->cached_hostip = strdup(ihost);
+
+ return this->cached_hostip;
}
void userrec::CloseSocket()
char* userrec::GetFullHost()
{
- static char result[MAXBUF];
+ if (this->cached_fullhost)
+ return this->cached_fullhost;
+
+ char result[MAXBUF];
char* t = result;
for(char* n = nick; *n; n++)
*t++ = *n;
for(char* n = dhost; *n; n++)
*t++ = *n;
*t = 0;
- return result;
+
+ this->cached_fullhost = strdup(result);
+
+ return this->cached_fullhost;
}
char* userrec::MakeWildHost()
char* userrec::GetFullRealHost()
{
- static char fresult[MAXBUF];
+ if (this->cached_fullrealhost)
+ return this->cached_fullrealhost;
+
+ char fresult[MAXBUF];
char* t = fresult;
for(char* n = nick; *n; n++)
*t++ = *n;
for(char* n = host; *n; n++)
*t++ = *n;
*t = 0;
- return fresult;
+
+ this->cached_fullrealhost = strdup(fresult);
+
+ return this->cached_fullrealhost;
}
bool userrec::IsInvited(const irc::string &channel)
if (reason.length() > MAXQUIT - 1)
reason.resize(MAXQUIT - 1);
-
+
+ if (user->registered != REG_ALL)
+ if (Instance->unregistered_count)
+ Instance->unregistered_count--;
+
if (IS_LOCAL(user))
{
user->Write("ERROR :Closing link (%s@%s) [%s]",user->ident,user->host,reason.c_str());
int maxgroups = ServerInstance->Config->WhoWasMaxGroups;
int maxkeep = ServerInstance->Config->WhoWasMaxKeep;
- int groupcount = ServerInstance->whowas.size();
- /* iterate whowas_fifo oldest first */
- whowas_users_fifo::iterator iter, safeiter;
- for (iter = ServerInstance->whowas_fifo.begin(); iter != ServerInstance->whowas_fifo.end(); iter++)
+ /* first cut the list to new size (maxgroups) and also prune entries that are timed out. */
+ whowas_users::iterator iter;
+ int fifosize;
+ while ((fifosize = (int)ServerInstance->whowas_fifo.size()) > 0)
{
- /** prune all groups that has expired due to new maxkeep time and
- * also any group number higher than new maxgroups. The oldest are
- * removed first due to iteration over whowas_fifo
- */
- if (groupcount > maxgroups || iter->first < t - maxkeep)
+ if (fifosize > maxgroups || ServerInstance->whowas_fifo[0].first < t - maxkeep)
{
- whowas_set* n = (whowas_set*)ServerInstance->whowas.find(iter->second)->second;
+ iter = ServerInstance->whowas.find(ServerInstance->whowas_fifo[0].second);
+ /* hopefully redundant integrity check, but added while debugging r6216 */
+ if (iter == ServerInstance->whowas.end())
+ {
+ /* this should never happen, if it does maps are corrupt */
+ ServerInstance->Log(DEBUG, "Whowas maps got corrupted! (1)");
+ return;
+ }
+ whowas_set* n = (whowas_set*)iter->second;
if (n->size())
{
while (n->begin() != n->end())
{
WhoWasGroup *a = *(n->begin());
DELETE(a);
- n->erase(n->begin());
+ n->pop_front();
}
}
- ServerInstance->whowas.erase(iter->second);
- /* use a safe iter copy for erase and set the orig iter old valid ref by decrementing it */
- safeiter = iter;
- --iter;
- ServerInstance->whowas_fifo.erase(safeiter);
+ ServerInstance->whowas.erase(iter);
+ ServerInstance->whowas_fifo.pop_front();
}
- else {
- /* also trim individual groupsizes in case groupsize should have been lowered */
- whowas_set* n = (whowas_set*)ServerInstance->whowas.find(iter->second)->second;
- if (n->size())
+ else
+ break;
+ }
+
+ /* Then cut the whowas sets to new size (groupsize) */
+ for (int i = 0; i < fifosize; i++)
+ {
+ iter = ServerInstance->whowas.find(ServerInstance->whowas_fifo[0].second);
+ /* hopefully redundant integrity check, but added while debugging r6216 */
+ if (iter == ServerInstance->whowas.end())
+ {
+ /* this should never happen, if it does maps are corrupt */
+ ServerInstance->Log(DEBUG, "Whowas maps got corrupted! (2)");
+ return;
+ }
+ whowas_set* n = (whowas_set*)iter->second;
+ if (n->size())
+ {
+ int nickcount = n->size();
+ while (n->begin() != n->end() && nickcount > groupsize)
{
- int nickcount = n->size();
- while (n->begin() != n->end() && nickcount > groupsize)
- {
- WhoWasGroup *a = *(n->begin());
- DELETE(a);
- n->erase(n->begin());
- nickcount--;
- }
+ WhoWasGroup *a = *(n->begin());
+ DELETE(a);
+ n->pop_front();
+ nickcount--;
}
}
- groupcount--;
}
}
};
if (iter == ServerInstance->whowas.end())
{
ServerInstance->Log(DEBUG,"Adding new whowas set for %s",this->nick);
+
irc::whowas::whowas_set* n = new irc::whowas::whowas_set;
irc::whowas::WhoWasGroup *a = new irc::whowas::WhoWasGroup(this);
n->push_back(a);
ServerInstance->whowas[this->nick] = n;
- ServerInstance->whowas_fifo[ServerInstance->Time()] = this->nick;
+ ServerInstance->whowas_fifo.push_back(std::make_pair(ServerInstance->Time(),this->nick));
+
if ((int)(ServerInstance->whowas.size()) > ServerInstance->Config->WhoWasMaxGroups)
{
- ServerInstance->Log(DEBUG,"Maxgroups of %d reached deleting oldest group '%s'",ServerInstance->Config->WhoWasMaxGroups, ServerInstance->whowas_fifo.begin()->second.c_str());
- ServerInstance->whowas.erase(ServerInstance->whowas_fifo.begin()->second);
- ServerInstance->whowas_fifo.erase(ServerInstance->whowas_fifo.begin());
+ ServerInstance->Log(DEBUG,"Maxgroups of %d reached deleting oldest group '%s'",ServerInstance->Config->WhoWasMaxGroups, ServerInstance->whowas_fifo[0].second.c_str());
+
+ irc::whowas::whowas_users::iterator iter = ServerInstance->whowas.find(ServerInstance->whowas_fifo[0].second);
+ if (iter != ServerInstance->whowas.end())
+ {
+ irc::whowas::whowas_set* n = (irc::whowas::whowas_set*)iter->second;
+ if (n->size())
+ {
+ while (n->begin() != n->end())
+ {
+ irc::whowas::WhoWasGroup *a = *(n->begin());
+ DELETE(a);
+ n->pop_front();
+ }
+ }
+ ServerInstance->whowas.erase(iter);
+ }
+ ServerInstance->whowas_fifo.pop_front();
}
}
else
ServerInstance->Log(DEBUG,"Using existing whowas group for %s",this->nick);
- if ((int)(group->size()) >= ServerInstance->Config->WhoWasGroupSize)
+ irc::whowas::WhoWasGroup *a = new irc::whowas::WhoWasGroup(this);
+ group->push_back(a);
+
+ if ((int)(group->size()) > ServerInstance->Config->WhoWasGroupSize)
{
ServerInstance->Log(DEBUG,"Trimming existing group '%s' to %d entries",this->nick, ServerInstance->Config->WhoWasGroupSize);
irc::whowas::WhoWasGroup *a = (irc::whowas::WhoWasGroup*)*(group->begin());
DELETE(a);
group->pop_front();
}
-
- irc::whowas::WhoWasGroup *a = new irc::whowas::WhoWasGroup(this);
- group->push_back(a);
}
}
userrec* New;
int j = 0;
+ Instance->unregistered_count++;
+
/*
* fix by brain.
* as these nicknames are 'RFC impossible', we can be sure nobody is going to be
Goners->AddItem(this, reason);
return;
}
- }
+ }
this->WriteServ("NOTICE Auth :Welcome to \002%s\002!",ServerInstance->Config->Network);
this->WriteServ("001 %s :Welcome to the %s IRC Network %s!%s@%s",this->nick, ServerInstance->Config->Network, this->nick, this->ident, this->host);
this->ShowMOTD();
+ /* Now registered */
+ if (ServerInstance->unregistered_count)
+ ServerInstance->unregistered_count--;
+
/*
* fix 3 by brain, move registered = 7 below these so that spurious modes and host
* changes dont go out onto the network and produce 'fake direction'.
}
}
+void userrec::InvalidateCache()
+{
+ /* Invalidate cache */
+ if (cached_fullhost)
+ free(cached_fullhost);
+ if (cached_hostip)
+ free(cached_hostip);
+ if (cached_makehost)
+ free(cached_makehost);
+ if (cached_fullrealhost)
+ free(cached_fullrealhost);
+ cached_fullhost = cached_hostip = cached_makehost = cached_fullrealhost = NULL;
+}
+
bool userrec::ForceNickChange(const char* newnick)
{
try
{
int MOD_RESULT = 0;
+
+ this->InvalidateCache();
FOREACH_RESULT(I_OnUserPreNick,OnUserPreNick(this, newnick));
try
{
bool sent_to_at_least_one = false;
+ char tb[MAXBUF];
if (this->registered != REG_ALL)
return;
uniq_id++;
+
+ /* We dont want to be doing this n times, just once */
+ snprintf(tb,MAXBUF,":%s %s",this->GetFullHost(),text.c_str());
+ std::string out = tb;
for (UCListIter v = this->chans.begin(); v != this->chans.end(); v++)
{
if ((IS_LOCAL(i->second)) && (already_sent[i->second->fd] != uniq_id))
{
already_sent[i->second->fd] = uniq_id;
- i->second->WriteFrom(this, std::string(text));
+ i->second->Write(out);
sent_to_at_least_one = true;
}
}
*/
if (!sent_to_at_least_one)
{
- this->WriteFrom(this,std::string(text));
+ this->Write(std::string(tb));
}
}
bool quit_munge = false;
char oper_quit[MAXBUF];
char textbuffer[MAXBUF];
+ char tb1[MAXBUF];
+ char tb2[MAXBUF];
+ std::string out1;
+ std::string out2;
strlcpy(textbuffer, text.c_str(), MAXBUF);
uniq_id++;
+ snprintf(tb1,MAXBUF,":%s %s",this->GetFullHost(),textbuffer);
+
/* TODO: We need some form of WriteCommonExcept that will send two lines, one line to
* opers and the other line to non-opers, then all this hidebans and hidesplits gunk
* can go byebye.
strlcpy(oper_quit,textbuffer,MAXQUIT);
strlcpy(check,"*.net *.split",MAXQUIT);
quit_munge = true;
+ snprintf(tb2,MAXBUF,":%s %s",this->GetFullHost(),oper_quit);
+ out2 = tb2;
}
}
}
strlcpy(oper_quit,textbuffer,MAXQUIT);
*check = 0; // We don't need to strlcpy, we just chop it from the :
quit_munge = true;
+ snprintf(tb2,MAXBUF,":%s %s",this->GetFullHost(),oper_quit);
+ out2 = tb2;
}
}
+ out1 = tb1;
+
for (UCListIter v = this->chans.begin(); v != this->chans.end(); v++)
{
CUList *ulist = v->first->GetUsers();
{
already_sent[i->second->fd] = uniq_id;
if (quit_munge)
- i->second->WriteFrom(this, *i->second->oper ? std::string(oper_quit) : std::string(textbuffer));
+ i->second->Write(*i->second->oper ? out2 : out1);
else
- i->second->WriteFrom(this, std::string(textbuffer));
+ i->second->Write(out1);
}
}
}
FOREACH_MOD(I_OnChangeName,OnChangeName(this,gecos));
}
strlcpy(this->fullname,gecos,MAXGECOS+1);
+
return true;
}
/* Fix by Om: userrec::dhost is 65 long, this was truncating some long hosts */
strlcpy(this->dhost,host,64);
+ this->InvalidateCache();
+
if (this->ServerInstance->Config->CycleHosts)
{
for (UCListIter i = this->chans.begin(); i != this->chans.end(); i++)
strlcpy(this->ident, newident, IDENTMAX+2);
+ this->InvalidateCache();
+
if (this->ServerInstance->Config->CycleHosts)
{
for (UCListIter i = this->chans.begin(); i != this->chans.end(); i++)
vsnprintf(textbuffer, MAXBUF, text, argsPtr);
va_end(argsPtr);
- snprintf(formatbuffer,MAXBUF,"NOTICE $* :%s",textbuffer);
+ snprintf(formatbuffer,MAXBUF,":%s NOTICE $* :%s", this->GetFullHost(), textbuffer);
+ std::string fmt = formatbuffer;
for (std::vector<userrec*>::const_iterator i = ServerInstance->local_users.begin(); i != ServerInstance->local_users.end(); i++)
{
- userrec* t = *i;
- t->WriteFrom(this, std::string(formatbuffer));
+ (*i)->Write(fmt);
}
}
void userrec::HandleEvent(EventType et, int errornum)
{
/* WARNING: May delete this user! */
+ int thisfd = this->GetFd();
+
try
{
switch (et)
{
case EVENT_READ:
ServerInstance->ProcessUser(this);
- return;
break;
case EVENT_WRITE:
this->FlushWriteBuf();
}
/* If the user has raised an error whilst being processed, quit them now we're safe to */
- if (!WriteError.empty())
+ if ((ServerInstance->SE->GetRef(thisfd) == this))
{
- userrec::QuitUser(ServerInstance, this, GetWriteError());
+ if (!WriteError.empty())
+ {
+ userrec::QuitUser(ServerInstance, this, GetWriteError());
+ }
}
}