X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fusers.cpp;h=ed979e337a29db2f5fa2183f6c26572604451b5d;hb=ed105d7fef72b5bb5f23e72fae40d6b4ffdcb5b8;hp=72b2d79a5a0e0d3674c682dcdf5d53ab3314d8ef;hpb=869f115d7f427847ab85b7738905aa3bcccd57d2;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/users.cpp b/src/users.cpp index 72b2d79a5..ed979e337 100644 --- a/src/users.cpp +++ b/src/users.cpp @@ -24,58 +24,59 @@ #include "xline.h" #include "cull_list.h" -irc::whowas::whowas_users whowas; static unsigned long already_sent[MAX_DESCRIPTORS] = {0}; -typedef std::map opertype_t; -typedef opertype_t operclass_t; - -opertype_t opertypes; -operclass_t operclass; - /* XXX: Used for speeding up WriteCommon operations */ unsigned long uniq_id = 0; bool InitTypes(ServerConfig* conf, const char* tag) { - for (opertype_t::iterator n = opertypes.begin(); n != opertypes.end(); n++) + if (conf->opertypes.size()) { - if (n->second) - delete[] n->second; + conf->GetInstance()->Log(DEBUG,"Currently %d items to clear",conf->opertypes.size()); + for (opertype_t::iterator n = conf->opertypes.begin(); n != conf->opertypes.end(); n++) + { + conf->GetInstance()->Log(DEBUG,"Clear item"); + if (n->second) + delete[] n->second; + } } - opertypes.clear(); + conf->opertypes.clear(); return true; } bool InitClasses(ServerConfig* conf, const char* tag) { - for (operclass_t::iterator n = operclass.begin(); n != operclass.end(); n++) + if (conf->operclass.size()) { - if (n->second) - delete[] n->second; + for (operclass_t::iterator n = conf->operclass.begin(); n != conf->operclass.end(); n++) + { + if (n->second) + delete[] n->second; + } } - operclass.clear(); + conf->operclass.clear(); return true; } -bool DoType(ServerConfig* conf, const char* tag, char** entries, void** values, int* types) +bool DoType(ServerConfig* conf, const char* tag, char** entries, ValueList &values, int* types) { - char* TypeName = (char*)values[0]; - char* Classes = (char*)values[1]; + const char* TypeName = values[0].GetString(); + const char* Classes = values[1].GetString(); - opertypes[TypeName] = strdup(Classes); + conf->opertypes[TypeName] = strdup(Classes); conf->GetInstance()->Log(DEBUG,"Read oper TYPE '%s' with classes '%s'",TypeName,Classes); return true; } -bool DoClass(ServerConfig* conf, const char* tag, char** entries, void** values, int* types) +bool DoClass(ServerConfig* conf, const char* tag, char** entries, ValueList &values, int* types) { - char* ClassName = (char*)values[0]; - char* CommandList = (char*)values[1]; + const char* ClassName = values[0].GetString(); + const char* CommandList = values[1].GetString(); - operclass[ClassName] = strdup(CommandList); + conf->operclass[ClassName] = strdup(CommandList); conf->GetInstance()->Log(DEBUG,"Read oper CLASS '%s' with commands '%s'",ClassName,CommandList); return true; } @@ -105,6 +106,24 @@ std::string userrec::ProcessNoticeMasks(const char *sm) case '-': adding = false; break; + case '*': + for (unsigned char d = 'A'; d <= 'z'; d++) + { + if (ServerInstance->SNO->IsEnabled(d)) + { + if ((!IsNoticeMaskSet(d) && adding) || (IsNoticeMaskSet(d) && !adding)) + { + if ((oldadding != adding) || (!output.length())) + output += (adding ? '+' : '-'); + + this->SetNoticeMask(d, adding); + + output += d; + } + } + oldadding = adding; + } + break; default: if ((*c >= 'A') && (*c <= 'z') && (ServerInstance->SNO->IsEnabled(*c))) { @@ -134,7 +153,7 @@ void userrec::StartDNSLookup() try { ServerInstance->Log(DEBUG,"Passing instance: %08x",this->ServerInstance); - res_reverse = new UserResolver(this->ServerInstance, this, this->GetIPString(), false); + res_reverse = new UserResolver(this->ServerInstance, this, this->GetIPString(), DNS_QUERY_REVERSE); this->ServerInstance->AddResolver(res_reverse); } catch (ModuleException& e) @@ -143,10 +162,10 @@ void userrec::StartDNSLookup() } } -UserResolver::UserResolver(InspIRCd* Instance, userrec* user, std::string to_resolve, bool forward) : - Resolver(Instance, to_resolve, forward ? DNS_QUERY_FORWARD : DNS_QUERY_REVERSE), bound_user(user) +UserResolver::UserResolver(InspIRCd* Instance, userrec* user, std::string to_resolve, QueryType qt) : + Resolver(Instance, to_resolve, qt), bound_user(user) { - this->fwd = forward; + this->fwd = (qt == DNS_QUERY_A || qt == DNS_QUERY_AAAA); this->bound_fd = user->GetFd(); } @@ -161,7 +180,12 @@ void UserResolver::OnLookupComplete(const std::string &result) /* Check we didnt time out */ if (this->bound_user->registered != REG_ALL) { - bound_user->res_forward = new UserResolver(this->ServerInstance, this->bound_user, result, true); +#ifdef IPV6 + const char *ip = this->bound_user->GetIPString(); + bound_user->res_forward = new UserResolver(this->ServerInstance, this->bound_user, result, (strstr(ip,"0::ffff:") == ip ? DNS_QUERY_A : DNS_QUERY_AAAA)); +#else + bound_user->res_forward = new UserResolver(this->ServerInstance, this->bound_user, result, DNS_QUERY_A); +#endif this->ServerInstance->AddResolver(bound_user->res_forward); } } @@ -173,7 +197,9 @@ void UserResolver::OnLookupComplete(const std::string &result) else if ((this->fwd) && (ServerInstance->SE->GetRef(this->bound_fd) == this->bound_user)) { /* Both lookups completed */ - if (this->bound_user->GetIPString() == result) + std::string result2 = "0::ffff:"; + result2.append(result); + if (this->bound_user->GetIPString() == result || this->bound_user->GetIPString() == result2) { std::string hostname = this->bound_user->stored_host; if (hostname.length() < 65) @@ -271,9 +297,10 @@ userrec::userrec(InspIRCd* Instance) : ServerInstance(Instance) *password = *nick = *ident = *host = *dhost = *fullname = *awaymsg = *oper = 0; server = (char*)Instance->FindServerNamePtr(Instance->Config->ServerName); reset_due = ServerInstance->Time(); + age = ServerInstance->Time(true); lines_in = lastping = signon = idle_lastmsg = nping = registered = 0; ChannelCount = timeout = flood = bytes_in = bytes_out = cmds_in = cmds_out = 0; - haspassed = dns_done = false; + exempt = haspassed = dns_done = false; fd = -1; recvq = ""; sendq = ""; @@ -288,10 +315,9 @@ userrec::userrec(InspIRCd* Instance) : ServerInstance(Instance) for (unsigned int n = 0; n < MAXCHANS; n++) { - ucrec* x = new ucrec(); - chans[n] = x; - x->channel = NULL; - x->uc_modes = 0; + chans[n] = new ucrec(); + chans[n]->channel = NULL; + chans[n]->uc_modes = 0; } } @@ -305,6 +331,26 @@ userrec::~userrec() if (ip) { + clonemap::iterator x = ServerInstance->local_clones.find(this->GetIPString()); + if (x != ServerInstance->local_clones.end()) + { + x->second--; + if (!x->second) + { + ServerInstance->local_clones.erase(x); + } + } + + clonemap::iterator y = ServerInstance->global_clones.find(this->GetIPString()); + if (y != ServerInstance->global_clones.end()) + { + y->second--; + if (!y->second) + { + ServerInstance->global_clones.erase(y); + } + } + if (this->GetProtocolFamily() == AF_INET) { delete (sockaddr_in*)ip; @@ -318,9 +364,9 @@ userrec::~userrec() } } -/* XXX - minor point, other *Host functions return a char *, this one creates it. Might be nice to be consistant? */ -void userrec::MakeHost(char* nhost) +char* userrec::MakeHost() { + static char nhost[MAXBUF]; /* This is much faster than snprintf */ char* t = nhost; for(char* n = ident; *n; n++) @@ -329,6 +375,21 @@ void userrec::MakeHost(char* nhost) for(char* n = host; *n; n++) *t++ = *n; *t = 0; + return nhost; +} + +char* userrec::MakeHostIP() +{ + static char ihost[MAXBUF]; + /* This is much faster than snprintf */ + char* t = ihost; + for(char* n = ident; *n; n++) + *t++ = *n; + *t++ = '@'; + for(const char* n = this->GetIPString(); *n; n++) + *t++ = *n; + *t = 0; + return ihost; } void userrec::CloseSocket() @@ -456,15 +517,15 @@ bool userrec::HasPermission(const std::string &command) // are they even an oper at all? if (*this->oper) { - opertype_t::iterator iter_opertype = opertypes.find(this->oper); - if (iter_opertype != opertypes.end()) + opertype_t::iterator iter_opertype = ServerInstance->Config->opertypes.find(this->oper); + if (iter_opertype != ServerInstance->Config->opertypes.end()) { char* Classes = strdup(iter_opertype->second); char* myclass = strtok_r(Classes," ",&savept); while (myclass) { - operclass_t::iterator iter_operclass = operclass.find(myclass); - if (iter_operclass != operclass.end()) + operclass_t::iterator iter_operclass = ServerInstance->Config->operclass.find(myclass); + if (iter_operclass != ServerInstance->Config->operclass.end()) { char* CommandList = strdup(iter_operclass->second); mycmd = strtok_r(CommandList," ",&savept2); @@ -615,27 +676,42 @@ void userrec::FlushWriteBuf() { try { - if (this->fd == FD_MAGIC_NUMBER) + if ((this->fd == FD_MAGIC_NUMBER) || (*this->GetWriteError())) { sendq = ""; } if ((sendq.length()) && (this->fd != FD_MAGIC_NUMBER)) { + int old_sendq_length = sendq.length(); const char* tb = this->sendq.c_str(); int n_sent = write(this->fd,tb,this->sendq.length()); if (n_sent == -1) { - if (errno != EAGAIN) - this->SetWriteError(strerror(errno)); + if (errno == EAGAIN) + { + ServerInstance->Log(DEBUG,"EAGAIN, want write"); + this->ServerInstance->SE->WantWrite(this); + } + else + { + this->QuitUser(ServerInstance, this, strerror(errno)); + return; + } } else { + /*ServerInstance->Log(DEBUG,"Wrote: %d of %d: %s", n_sent, old_sendq_length, sendq.substr(0, n_sent).c_str());*/ // advance the queue tb += n_sent; this->sendq = tb; // update the user's stats counters this->bytes_out += n_sent; this->cmds_out++; + if (n_sent != old_sendq_length) + { + ServerInstance->Log(DEBUG,"Not all written, want write"); + this->ServerInstance->SE->WantWrite(this); + } } } } @@ -733,9 +809,6 @@ void userrec::QuitUser(InspIRCd* Instance, userrec *user, const std::string &qui user->WriteCommonExcept("QUIT :%s",reason.c_str()); } - if (IS_LOCAL(user)) - user->FlushWriteBuf(); - FOREACH_MOD_I(Instance,I_OnUserDisconnect,OnUserDisconnect(user)); if (IS_LOCAL(user)) @@ -808,15 +881,15 @@ namespace irc free(gecos); } - /* every hour, run this function which removes all entries over 3 days */ - void MaintainWhoWas(time_t t) + /* every hour, run this function which removes all entries older than Config->WhoWasMaxKeep */ + void MaintainWhoWas(InspIRCd* ServerInstance, time_t t) { - for (whowas_users::iterator iter = ::whowas.begin(); iter != ::whowas.end(); iter++) + for (whowas_users::iterator iter = ServerInstance->whowas.begin(); iter != ServerInstance->whowas.end(); iter++) { whowas_set* n = (whowas_set*)iter->second; if (n->size()) { - while ((n->begin() != n->end()) && ((*n->begin())->signon < t - 259200)) // 3 days + while ((n->begin() != n->end()) && ((*n->begin())->signon < t - ServerInstance->Config->WhoWasMaxKeep)) { WhoWasGroup *a = *(n->begin()); DELETE(a); @@ -825,27 +898,99 @@ namespace irc } } } + /* on rehash, refactor maps according to new conf values */ + void PruneWhoWas(InspIRCd* ServerInstance, time_t t) + { + /* config values */ + int groupsize = ServerInstance->Config->WhoWasGroupSize; + 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++) + { + /** 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) + { + whowas_set* n = (whowas_set*)ServerInstance->whowas.find(iter->second)->second; + if (n->size()) + { + while (n->begin() != n->end()) + { + WhoWasGroup *a = *(n->begin()); + DELETE(a); + n->erase(n->begin()); + } + } + 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); + } + 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()) + { + int nickcount = n->size(); + while (n->begin() != n->end() && nickcount > groupsize) + { + WhoWasGroup *a = *(n->begin()); + DELETE(a); + n->erase(n->begin()); + nickcount--; + } + } + } + groupcount--; + } + } }; }; /* adds or updates an entry in the whowas list */ void userrec::AddToWhoWas() { - irc::whowas::whowas_users::iterator iter = whowas.find(this->nick); + /* if whowas disabled */ + if (ServerInstance->Config->WhoWasGroupSize == 0 || ServerInstance->Config->WhoWasMaxGroups == 0) + { + return; + } + + irc::whowas::whowas_users::iterator iter = ServerInstance->whowas.find(this->nick); - if (iter == whowas.end()) + ServerInstance->Log(DEBUG,"Add to whowas lists"); + + 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); - whowas[this->nick] = n; + ServerInstance->whowas[this->nick] = n; + ServerInstance->whowas_fifo[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()); + } } else { irc::whowas::whowas_set* group = (irc::whowas::whowas_set*)iter->second; - if (group->size() > 10) + ServerInstance->Log(DEBUG,"Using existing whowas group for %s",this->nick); + + 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(); @@ -882,7 +1027,7 @@ void userrec::AddClient(InspIRCd* Instance, int socket, int port, bool iscached, } Instance->Log(DEBUG,"AddClient: %d %d %s",socket,port,ipaddr); - + New = new userrec(Instance); Instance->clientlist[tempnick] = New; New->fd = socket; @@ -896,15 +1041,16 @@ void userrec::AddClient(InspIRCd* Instance, int socket, int port, bool iscached, New->signon = Instance->Time() + Instance->Config->dns_timeout; New->lastping = 1; - Instance->Log(DEBUG,"Setting socket addresses"); New->SetSockAddr(AF_FAMILY, ipaddr, port); - Instance->Log(DEBUG,"Socket addresses set."); /* Smarter than your average bear^H^H^H^Hset of strlcpys. */ for (const char* temp = New->GetIPString(); *temp && j < 64; temp++, j++) New->dhost[j] = New->host[j] = *temp; New->dhost[j] = New->host[j] = 0; - + + Instance->AddLocalClone(New); + Instance->AddGlobalClone(New); + // set the registration timeout for this user unsigned long class_regtimeout = 90; int class_flood = 0; @@ -937,6 +1083,7 @@ void userrec::AddClient(InspIRCd* Instance, int socket, int port, bool iscached, if ((Instance->local_users.size() > Instance->Config->SoftLimit) || (Instance->local_users.size() >= MAXCLIENTS)) { + Instance->WriteOpers("*** Warning: softlimit value has been reached: %d clients", Instance->Config->SoftLimit); userrec::QuitUser(Instance, New,"No more connections allowed"); return; } @@ -951,79 +1098,56 @@ void userrec::AddClient(InspIRCd* Instance, int socket, int port, bool iscached, * which for the time being is a physical impossibility (even the largest networks dont have more * than about 10,000 users on ONE server!) */ - if ((unsigned)socket >= MAX_DESCRIPTORS) + if ((unsigned int)socket >= MAX_DESCRIPTORS) { userrec::QuitUser(Instance, New, "Server is full"); return; } - /* - * XXX really really fixme! QuitUser doesn't like having a null entry in the ref table it seems, moving this up so - * zlines dont crash ircd. we need a better solution, as this is obviously inefficient (and probably wrong) -- w00t - */ - if (socket > -1) + New->exempt = (Instance->XLines->matches_exception(New) != NULL); + if (!New->exempt) { - if (!Instance->SE->AddFd(New)) + ZLine* r = Instance->XLines->matches_zline(ipaddr); + if (r) { - userrec::QuitUser(Instance, New, "Internal error handling connection"); + char reason[MAXBUF]; + snprintf(reason,MAXBUF,"Z-Lined: %s",r->reason); + userrec::QuitUser(Instance, New, reason); return; } } - ELine* e = Instance->XLines->matches_exception(New); - if (!e) + if (socket > -1) { - ZLine* r = Instance->XLines->matches_zline(ipaddr); - if (r) + if (!Instance->SE->AddFd(New)) { - char reason[MAXBUF]; - snprintf(reason,MAXBUF,"Z-Lined: %s",r->reason); - userrec::QuitUser(Instance, New, reason); + userrec::QuitUser(Instance, New, "Internal error handling connection"); return; } } + /* NOTE: even if dns lookups are *off*, we still need to display this. + * BOPM and other stuff requires it. + */ New->WriteServ("NOTICE Auth :*** Looking up your hostname..."); } long userrec::GlobalCloneCount() { - char u1[128]; - char u2[128]; - long x = 0; - - for (user_hash::const_iterator a = ServerInstance->clientlist.begin(); a != ServerInstance->clientlist.end(); a++) - { - /* We have to match ip's as strings - we don't know what protocol - * a remote user may be using - */ - if (strcmp(a->second->GetIPString(u1), this->GetIPString(u2)) == 0) - x++; - } - - return x; + clonemap::iterator x = ServerInstance->global_clones.find(this->GetIPString()); + if (x != ServerInstance->global_clones.end()) + return x->second; + else + return 0; } long userrec::LocalCloneCount() { - long x = 0; - for (std::vector::const_iterator a = ServerInstance->local_users.begin(); a != ServerInstance->local_users.end(); a++) - { - userrec* comp = *a; -#ifdef IPV6 - /* I dont think theres any faster way of matching two ipv6 addresses than memcmp */ - in6_addr* s1 = &(((sockaddr_in6*)comp->ip)->sin6_addr); - in6_addr* s2 = &(((sockaddr_in6*)this->ip)->sin6_addr); - if (!memcmp(s1->s6_addr, s2->s6_addr, sizeof(in6_addr))) - x++; -#else - in_addr* s1 = &((sockaddr_in*)comp->ip)->sin_addr; - in_addr* s2 = &((sockaddr_in*)this->ip)->sin_addr; - if (s1->s_addr == s2->s_addr) - x++; -#endif - } - return x; + clonemap::iterator x = ServerInstance->local_clones.find(this->GetIPString()); + if (x != ServerInstance->local_clones.end()) + return x->second; + else + return 0; } void userrec::FullConnect(CullList* Goners) @@ -1058,9 +1182,7 @@ void userrec::FullConnect(CullList* Goners) return; } - ELine* e = ServerInstance->XLines->matches_exception(this); - - if (!e) + if (!this->exempt) { GLine* r = ServerInstance->XLines->matches_gline(this); @@ -1118,8 +1240,11 @@ void userrec::FullConnect(CullList* Goners) * changes dont go out onto the network and produce 'fake direction'. */ FOREACH_MOD(I_OnUserConnect,OnUserConnect(this)); - FOREACH_MOD(I_OnPostConnect,OnPostConnect(this)); + this->registered = REG_ALL; + + FOREACH_MOD(I_OnPostConnect,OnPostConnect(this)); + ServerInstance->SNO->WriteToSnoMask('c',"Client connecting on port %d: %s!%s@%s [%s]", this->GetPort(), this->nick, this->ident, this->host, this->GetIPString()); } @@ -1278,7 +1403,7 @@ const char* userrec::GetIPString() /* IP addresses starting with a : on irc are a Bad Thing (tm) */ if (*buf == ':') { - strlcpy(&temp[1], buf, sizeof(temp)); + strlcpy(&temp[1], buf, sizeof(temp) - 1); *temp = '0'; return temp; } @@ -1320,7 +1445,7 @@ const char* userrec::GetIPString(char* buf) /* IP addresses starting with a : on irc are a Bad Thing (tm) */ if (*buf == ':') { - strlcpy(&temp[1], buf, sizeof(temp)); + strlcpy(&temp[1], buf, sizeof(temp) - 1); *temp = '0'; strlcpy(buf, temp, sizeof(temp)); } @@ -1380,6 +1505,7 @@ void userrec::Write(std::string text) this->AddWriteBuf(text); } ServerInstance->stats->statsSent += text.length(); + this->ServerInstance->SE->WantWrite(this); } /** Write() @@ -1734,9 +1860,10 @@ bool userrec::ChangeDisplayedHost(const char* host) FOREACH_MOD(I_OnChangeHost,OnChangeHost(this,host)); } if (this->ServerInstance->Config->CycleHosts) - this->WriteCommonExcept("%s","QUIT :Changing hosts"); + this->WriteCommonExcept("QUIT :Changing hosts"); - strlcpy(this->dhost,host,63); + /* Fix by Om: userrec::dhost is 65 long, this was truncating some long hosts */ + strlcpy(this->dhost,host,64); if (this->ServerInstance->Config->CycleHosts) { @@ -1843,16 +1970,17 @@ void userrec::SplitChanList(userrec* dest, const std::string &cl) try { - prefix << ":" << ServerInstance->Config->ServerName << " 319 " << this->nick << " " << dest->nick << " :"; + prefix << this->nick << " " << dest->nick << " :"; line = prefix.str(); + int namelen = strlen(ServerInstance->Config->ServerName) + 6; for (start = 0; (pos = cl.find(' ', start)) != std::string::npos; start = pos+1) { length = (pos == std::string::npos) ? cl.length() : pos; - if (line.length() + length - start > 510) + if (line.length() + namelen + length - start > 510) { - this->Write(line); + ServerInstance->SendWhoisLine(this, dest, 319, "%s", line.c_str()); line = prefix.str(); } @@ -1869,7 +1997,7 @@ void userrec::SplitChanList(userrec* dest, const std::string &cl) if (line.length()) { - this->Write(line); + ServerInstance->SendWhoisLine(this, dest, 319, "%s", line.c_str()); } } @@ -1968,16 +2096,27 @@ void userrec::ShowRULES() this->WriteServ("NOTICE %s :End of %s rules.",this->nick,ServerInstance->Config->ServerName); } -void userrec::HandleEvent(EventType et) +void userrec::HandleEvent(EventType et, int errornum) { /* WARNING: May delete this user! */ try { - ServerInstance->ProcessUser(this); + switch (et) + { + case EVENT_READ: + ServerInstance->ProcessUser(this); + break; + case EVENT_WRITE: + this->FlushWriteBuf(); + break; + case EVENT_ERROR: + /** This should be safe, but dont DARE do anything after it -- Brain */ + userrec::QuitUser(ServerInstance, this, errornum ? strerror(errornum) : "EOF from client"); + break; + } } catch (...) { ServerInstance->Log(DEBUG,"Exception in userrec::HandleEvent intercepted"); } } -