X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fusers.cpp;h=4050337c7a2e7ed6ab9b02564136d508ff044c14;hb=168ee804903e5ee10edc04e870e36a1256885e34;hp=e17c8cd79417764df5bc883231aa2b811c64e229;hpb=b2ac8cc0a6405946a388b80df3be21bc276a61f3;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/users.cpp b/src/users.cpp index e17c8cd79..4050337c7 100644 --- a/src/users.cpp +++ b/src/users.cpp @@ -97,7 +97,7 @@ LocalUser::LocalUser(int myfd, irc::sockets::sockaddrs* client, irc::sockets::so , quitting_sendq(false) , lastping(true) , exempt(false) - , nping(0) + , nextping(0) , idle_lastmsg(0) , CommandFloodPenalty(0) , already_sent(0) @@ -239,23 +239,30 @@ void UserIOHandler::OnDataReady() if (!user->HasPrivPermission("users/flood/no-fakelag")) penaltymax = user->MyClass->GetPenaltyThreshold() * 1000; - // The maximum size of an IRC message minus the terminating CR+LF. - const size_t maxmessage = ServerInstance->Config->Limits.MaxLine - 2; + // The cleaned message sent by the user or empty if not found yet. std::string line; - line.reserve(maxmessage); - bool eol_found; + // The position of the most \n character or npos if not found yet. + std::string::size_type eolpos; + + // The position within the recvq of the current character. std::string::size_type qpos; while (user->CommandFloodPenalty < penaltymax && getSendQSize() < sendqmax) { - qpos = 0; - eol_found = false; + // Check the newly received data for an EOL. + eolpos = recvq.find('\n', checked_until); + if (eolpos == std::string::npos) + { + checked_until = recvq.length(); + return; + } - const size_t qlen = recvq.length(); - while (qpos < qlen) + // We've found a line! Clean it up and move it to the line buffer. + line.reserve(eolpos); + for (qpos = 0; qpos < eolpos; ++qpos) { - char c = recvq[qpos++]; + char c = recvq[qpos]; switch (c) { case '\0': @@ -263,25 +270,14 @@ void UserIOHandler::OnDataReady() break; case '\r': continue; - case '\n': - eol_found = true; - break; } - if (eol_found) - break; - - if (line.length() < maxmessage) - line.push_back(c); + line.push_back(c); } - // if we return here, we haven't found a newline and make no modifications to recvq - // so we can wait for more data - if (!eol_found) - return; - // just found a newline. Terminate the string, and pull it out of recvq - recvq.erase(0, qpos); + recvq.erase(0, eolpos + 1); + checked_until = 0; // TODO should this be moved to when it was inserted in recvq? ServerInstance->stats.Recv += qpos; @@ -318,10 +314,11 @@ void UserIOHandler::AddWriteBuf(const std::string &data) WriteData(data); } -void UserIOHandler::OnSetEndPoint(const irc::sockets::sockaddrs& server, const irc::sockets::sockaddrs& client) +bool UserIOHandler::OnSetEndPoint(const irc::sockets::sockaddrs& server, const irc::sockets::sockaddrs& client) { memcpy(&user->server_sa, &server, sizeof(irc::sockets::sockaddrs)); user->SetClientIP(client); + return !user->quitting; } void UserIOHandler::OnError(BufferedSocketError) @@ -357,10 +354,12 @@ CullResult FakeUser::cull() void User::Oper(OperInfo* info) { ModeHandler* opermh = ServerInstance->Modes->FindMode('o', MODETYPE_USER); - if (this->IsModeSet(opermh)) - this->UnOper(); - - this->SetMode(opermh, true); + if (opermh) + { + if (this->IsModeSet(opermh)) + this->UnOper(); + this->SetMode(opermh, true); + } this->oper = info; LocalUser* localuser = IS_LOCAL(this); @@ -378,17 +377,6 @@ void User::Oper(OperInfo* info) if (info->oper_block) opername = info->oper_block->getString("name"); - if (IS_LOCAL(this)) - { - LocalUser* l = IS_LOCAL(this); - std::string vhost = oper->getConfig("vhost"); - if (!vhost.empty()) - l->ChangeDisplayedHost(vhost); - std::string opClass = oper->getConfig("class"); - if (!opClass.empty()) - l->SetClass(opClass); - } - ServerInstance->SNO->WriteToSnoMask('o',"%s (%s@%s) is now an IRC operator of type %s (using oper '%s')", nick.c_str(), ident.c_str(), GetRealHost().c_str(), oper->name.c_str(), opername.c_str()); this->WriteNumeric(RPL_YOUAREOPER, InspIRCd::Format("You are now %s %s", strchr("aeiouAEIOU", oper->name[0]) ? "an" : "a", oper->name.c_str())); @@ -474,7 +462,8 @@ void User::UnOper() stdalgo::vector::swaperase(ServerInstance->Users->all_opers, this); ModeHandler* opermh = ServerInstance->Modes->FindMode('o', MODETYPE_USER); - this->SetMode(opermh, false); + if (opermh) + this->SetMode(opermh, false); FOREACH_MOD(OnPostDeoper, (this)); } @@ -514,7 +503,7 @@ void LocalUser::CheckClass(bool clone_count) } } - this->nping = ServerInstance->Time() + a->GetPingTime(); + this->nextping = ServerInstance->Time() + a->GetPingTime(); } bool LocalUser::CheckLines(bool doZline) @@ -557,45 +546,15 @@ void LocalUser::FullConnect() if (quitting) return; - this->WriteNumeric(RPL_WELCOME, InspIRCd::Format("Welcome to the %s IRC Network %s", ServerInstance->Config->Network.c_str(), GetFullRealHost().c_str())); - this->WriteNumeric(RPL_YOURHOSTIS, InspIRCd::Format("Your host is %s, running version %s", ServerInstance->Config->ServerName.c_str(), INSPIRCD_BRANCH)); - this->WriteNumeric(RPL_SERVERCREATED, InspIRCd::TimeString(ServerInstance->startup_time, "This server was created %H:%M:%S %b %d %Y")); - - const TR1NS::array& modelist = ServerInstance->Modes->GetModeListFor004Numeric(); - this->WriteNumeric(RPL_SERVERVERSION, ServerInstance->Config->ServerName, INSPIRCD_BRANCH, modelist[0], modelist[1], modelist[2]); - - ServerInstance->ISupport.SendTo(this); - - /* Now registered */ - if (ServerInstance->Users->unregistered_count) - ServerInstance->Users->unregistered_count--; - - /* Trigger MOTD and LUSERS output, give modules a chance too */ - ModResult MOD_RESULT; - std::string command("LUSERS"); - CommandBase::Params parameters; - FIRST_MOD_RESULT(OnPreCommand, MOD_RESULT, (command, parameters, this, true)); - if (!MOD_RESULT) - ServerInstance->Parser.CallHandler(command, parameters, this); - - MOD_RESULT = MOD_RES_PASSTHRU; - command = "MOTD"; - FIRST_MOD_RESULT(OnPreCommand, MOD_RESULT, (command, parameters, this, true)); - if (!MOD_RESULT) - ServerInstance->Parser.CallHandler(command, parameters, this); - - if (ServerInstance->Config->RawLog) - { - ClientProtocol::Messages::Privmsg rawlogmsg(ServerInstance->FakeClient, this, "*** Raw I/O logging is enabled on this server. All messages, passwords, and commands are being recorded."); - this->Send(ServerInstance->GetRFCEvents().privmsg, rawlogmsg); - } - /* * We don't set REG_ALL until triggering OnUserConnect, so some module events don't spew out stuff * for a user that doesn't exist yet. */ FOREACH_MOD(OnUserConnect, (this)); + /* Now registered */ + if (ServerInstance->Users->unregistered_count) + ServerInstance->Users->unregistered_count--; this->registered = REG_ALL; FOREACH_MOD(OnPostConnect, (this)); @@ -750,39 +709,56 @@ irc::sockets::cidr_mask User::GetCIDRMask() return irc::sockets::cidr_mask(client_sa, range); } -bool User::SetClientIP(const std::string& address, bool recheck_eline) +bool User::SetClientIP(const std::string& address) { - this->InvalidateCache(); - return irc::sockets::aptosa(address, 0, client_sa); + irc::sockets::sockaddrs sa; + if (!irc::sockets::aptosa(address, client_sa.port(), sa)) + return false; + + User::SetClientIP(sa); + return true; } -void User::SetClientIP(const irc::sockets::sockaddrs& sa, bool recheck_eline) +void User::SetClientIP(const irc::sockets::sockaddrs& sa) { - this->InvalidateCache(); + const std::string oldip(GetIPString()); memcpy(&client_sa, &sa, sizeof(irc::sockets::sockaddrs)); + this->InvalidateCache(); + + // If the users hostname was their IP then update it. + if (GetRealHost() == oldip) + ChangeRealHost(GetIPString(), false); + if (GetDisplayedHost() == oldip) + ChangeDisplayedHost(GetIPString()); } -bool LocalUser::SetClientIP(const std::string& address, bool recheck_eline) +bool LocalUser::SetClientIP(const std::string& address) { irc::sockets::sockaddrs sa; - if (!irc::sockets::aptosa(address, 0, sa)) - // Invalid + if (!irc::sockets::aptosa(address, client_sa.port(), sa)) return false; - LocalUser::SetClientIP(sa, recheck_eline); + LocalUser::SetClientIP(sa); return true; } -void LocalUser::SetClientIP(const irc::sockets::sockaddrs& sa, bool recheck_eline) +void LocalUser::SetClientIP(const irc::sockets::sockaddrs& sa) { - if (sa != client_sa) - { - User::SetClientIP(sa); - if (recheck_eline) - this->exempt = (ServerInstance->XLines->MatchesLine("E", this) != NULL); + if (sa == client_sa) + return; - FOREACH_MOD(OnSetUserIP, (this)); - } + ServerInstance->Users->RemoveCloneCounts(this); + + User::SetClientIP(sa); + + FOREACH_MOD(OnSetUserIP, (this)); + + ServerInstance->Users->AddClone(this); + + // Recheck the connect class. + this->MyClass = NULL; + this->SetClass(); + this->CheckClass(); } void LocalUser::Write(const ClientProtocol::SerializedMessage& text) @@ -813,7 +789,11 @@ void LocalUser::Write(const ClientProtocol::SerializedMessage& text) void LocalUser::Send(ClientProtocol::Event& protoev) { if (!serializer) + { + ServerInstance->Logs->Log("USERS", LOG_DEBUG, "BUG: LocalUser::Send() called on %s who does not have a serializer!", + GetFullRealHost().c_str()); return; + } // In the most common case a static LocalUser field, sendmsglist, is passed to the event to be // populated. The list is cleared before returning. @@ -1022,7 +1002,7 @@ bool User::ChangeDisplayedHost(const std::string& shost) this->InvalidateCache(); - if (IS_LOCAL(this)) + if (IS_LOCAL(this) && this->registered != REG_NONE) this->WriteNumeric(RPL_YOURDISPLAYEDHOST, this->GetDisplayedHost(), "is now your displayed host"); return true; @@ -1035,7 +1015,7 @@ void User::ChangeRealHost(const std::string& host, bool resetdisplay) const bool changehost = (realhost != host); if (!changehost && !resetdisplay) return; - + // If the displayhost is not set and we are not resetting it then // we need to copy it to the displayhost field. if (displayhost.empty() && !resetdisplay) @@ -1181,8 +1161,6 @@ void User::PurgeEmptyChannels() ++i; c->DelUser(this); } - - this->UnOper(); } void User::WriteNotice(const std::string& text)