void User::WriteCommonQuit(const std::string &normal_text, const std::string &oper_text) { char tb1[MAXBUF]; char tb2[MAXBUF]; if (this->registered != REG_ALL) return; already_sent_t uniq_id = ++LocalUser::already_sent_id; snprintf(tb1,MAXBUF,":%s QUIT :%s",this->GetFullHost().c_str(),normal_text.c_str()); snprintf(tb2,MAXBUF,":%s QUIT :%s",this->GetFullHost().c_str(),oper_text.c_str()); std::string out1 = tb1; std::string out2 = tb2; UserChanList include_c(chans); std::map<User*,bool> exceptions; FOREACH_MOD(I_OnBuildNeighborList,OnBuildNeighborList(this, include_c, exceptions)); for (std::map<User*,bool>::iterator i = exceptions.begin(); i != exceptions.end(); ++i) { LocalUser* u = IS_LOCAL(i->first); if (u && !u->quitting) { u->already_sent = uniq_id; if (i->second) u->Write(IS_OPER(u) ? out2 : out1); } } for (UCListIter v = include_c.begin(); v != include_c.end(); ++v) { const UserMembList* ulist = (*v)->GetUsers(); for (UserMembList::const_iterator i = ulist->begin(); i != ulist->end(); i++) { LocalUser* u = IS_LOCAL(i->first); if (u && !u->quitting && (u->already_sent != uniq_id)) { u->already_sent = uniq_id; u->Write(IS_OPER(u) ? out2 : out1); } } } }
void User::WriteCommonQuit(const std::string &normal_text, const std::string &oper_text) { if (this->registered != REG_ALL) return; already_sent_t uniq_id = ++LocalUser::already_sent_id; const std::string normalMessage = ":" + this->GetFullHost() + " QUIT :" + normal_text; const std::string operMessage = ":" + this->GetFullHost() + " QUIT :" + oper_text; IncludeChanList include_c(chans.begin(), chans.end()); std::map<User*,bool> exceptions; FOREACH_MOD(OnBuildNeighborList, (this, include_c, exceptions)); for (std::map<User*,bool>::iterator i = exceptions.begin(); i != exceptions.end(); ++i) { LocalUser* u = IS_LOCAL(i->first); if (u && !u->quitting) { u->already_sent = uniq_id; if (i->second) u->Write(u->IsOper() ? operMessage : normalMessage); } } 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++) { LocalUser* u = IS_LOCAL(i->first); if (u && (u->already_sent != uniq_id)) { u->already_sent = uniq_id; u->Write(u->IsOper() ? operMessage : normalMessage); } } } }
void User::WriteCommonRaw(const std::string &line, bool include_self) { if (this->registered != REG_ALL || quitting) return; LocalUser::already_sent_id++; IncludeChanList include_c(chans.begin(), chans.end()); std::map<User*,bool> exceptions; exceptions[this] = include_self; FOREACH_MOD(OnBuildNeighborList, (this, include_c, exceptions)); for (std::map<User*,bool>::iterator i = exceptions.begin(); i != exceptions.end(); ++i) { LocalUser* u = IS_LOCAL(i->first); if (u && !u->quitting) { u->already_sent = LocalUser::already_sent_id; if (i->second) u->Write(line); } } 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++) { LocalUser* u = IS_LOCAL(i->first); if (u && u->already_sent != LocalUser::already_sent_id) { u->already_sent = LocalUser::already_sent_id; u->Write(line); } } } }
/** * This function is called once a second from the mainloop. * It is intended to do background checking on all the user structs, e.g. * stuff like ping checks, registration timeouts, etc. */ void UserManager::DoBackgroundUserStuff() { /* * loop over all local users.. */ for (LocalUserList::iterator i = local_users.begin(); i != local_users.end(); ++i) { LocalUser* curr = *i; if (curr->quitting) continue; if (curr->CommandFloodPenalty || curr->eh.getSendQSize()) { unsigned int rate = curr->MyClass->GetCommandRate(); if (curr->CommandFloodPenalty > rate) curr->CommandFloodPenalty -= rate; else curr->CommandFloodPenalty = 0; curr->eh.OnDataReady(); } switch (curr->registered) { case REG_ALL: if (ServerInstance->Time() > curr->nping) { // This user didn't answer the last ping, remove them if (!curr->lastping) { time_t time = ServerInstance->Time() - (curr->nping - curr->MyClass->GetPingTime()); const std::string message = "Ping timeout: " + ConvToStr(time) + (time == 1 ? " seconds" : " second"); this->QuitUser(curr, message); continue; } curr->Write("PING :" + ServerInstance->Config->ServerName); curr->lastping = 0; curr->nping = ServerInstance->Time() + curr->MyClass->GetPingTime(); } break; case REG_NICKUSER: if (AllModulesReportReady(curr)) { /* User has sent NICK/USER, modules are okay, DNS finished. */ curr->FullConnect(); continue; } break; } if (curr->registered != REG_ALL && (ServerInstance->Time() > (curr->age + curr->MyClass->GetRegTimeout()))) { /* * registration timeout -- didnt send USER/NICK/HOST * in the time specified in their connection class. */ this->QuitUser(curr, "Registration timeout"); continue; } } }
/** * This function is called once a second from the mainloop. * It is intended to do background checking on all the user structs, e.g. * stuff like ping checks, registration timeouts, etc. */ void InspIRCd::DoBackgroundUserStuff() { /* * loop over all local users.. */ LocalUserList::reverse_iterator count2 = this->Users->local_users.rbegin(); while (count2 != this->Users->local_users.rend()) { LocalUser *curr = *count2; count2++; if (curr->quitting) continue; if (curr->CommandFloodPenalty || curr->eh.getSendQSize()) { unsigned int rate = curr->MyClass->GetCommandRate(); if (curr->CommandFloodPenalty > rate) curr->CommandFloodPenalty -= rate; else curr->CommandFloodPenalty = 0; curr->eh.OnDataReady(); } switch (curr->registered) { case REG_ALL: if (Time() > curr->nping) { // This user didn't answer the last ping, remove them if (!curr->lastping) { time_t time = this->Time() - (curr->nping - curr->MyClass->GetPingTime()); char message[MAXBUF]; snprintf(message, MAXBUF, "Ping timeout: %ld second%s", (long)time, time > 1 ? "s" : ""); curr->lastping = 1; curr->nping = Time() + curr->MyClass->GetPingTime(); this->Users->QuitUser(curr, message); continue; } curr->Write("PING :%s",this->Config->ServerName.c_str()); curr->lastping = 0; curr->nping = Time() +curr->MyClass->GetPingTime(); } break; case REG_NICKUSER: if (AllModulesReportReady(curr)) { /* User has sent NICK/USER, modules are okay, DNS finished. */ curr->FullConnect(); continue; } break; } if (curr->registered != REG_ALL && (Time() > (curr->age + curr->MyClass->GetRegTimeout()))) { /* * registration timeout -- didnt send USER/NICK/HOST * in the time specified in their connection class. */ this->Users->QuitUser(curr, "Registration timeout"); continue; } } }
void User::DoHostCycle(const std::string &quitline) { char buffer[MAXBUF]; if (!ServerInstance->Config->CycleHosts) return; already_sent_t silent_id = ++LocalUser::already_sent_id; already_sent_t seen_id = ++LocalUser::already_sent_id; UserChanList include_c(chans); std::map<User*,bool> exceptions; FOREACH_MOD(I_OnBuildNeighborList,OnBuildNeighborList(this, include_c, exceptions)); for (std::map<User*,bool>::iterator i = exceptions.begin(); i != exceptions.end(); ++i) { LocalUser* u = IS_LOCAL(i->first); if (u && !u->quitting) { if (i->second) { u->already_sent = seen_id; u->Write(quitline); } else { u->already_sent = silent_id; } } } for (UCListIter v = include_c.begin(); v != include_c.end(); ++v) { Channel* c = *v; snprintf(buffer, MAXBUF, ":%s JOIN %s", GetFullHost().c_str(), c->name.c_str()); std::string joinline(buffer); Membership* memb = c->GetUser(this); std::string modeline = memb->modes; if (modeline.length() > 0) { for(unsigned int i=0; i < memb->modes.length(); i++) modeline.append(" ").append(nick); snprintf(buffer, MAXBUF, ":%s MODE %s +%s", ServerInstance->Config->CycleHostsFromUser ? GetFullHost().c_str() : ServerInstance->Config->ServerName.c_str(), c->name.c_str(), modeline.c_str()); modeline = buffer; } const UserMembList *ulist = c->GetUsers(); for (UserMembList::const_iterator i = ulist->begin(); i != ulist->end(); i++) { LocalUser* u = IS_LOCAL(i->first); if (u == NULL || u == this) continue; if (u->already_sent == silent_id) continue; if (u->already_sent != seen_id) { u->Write(quitline); u->already_sent = seen_id; } u->Write(joinline); if (modeline.length() > 0) u->Write(modeline); } } }