]> git.netwichtig.de Git - user/henk/code/inspircd.git/commitdiff
Allow modules to prevent a failed connection from being closed.
authorPeter Powell <petpow@saberuk.com>
Sun, 21 Jul 2019 12:44:32 +0000 (13:44 +0100)
committerPeter Powell <petpow@saberuk.com>
Sun, 21 Jul 2019 12:50:01 +0000 (13:50 +0100)
include/modules.h
src/modules.cpp
src/usermanager.cpp
src/users.cpp

index 81664d3640c8ece744979e58e195ae6628a4461a..f5af969de8dc31b8f2cd922157ef9582c520a941 100644 (file)
@@ -223,7 +223,7 @@ enum Implementation
        I_OnUserPostNick, I_OnPreMode, I_On005Numeric, I_OnKill, I_OnLoadModule,
        I_OnUnloadModule, I_OnBackgroundTimer, I_OnPreCommand, I_OnCheckReady, I_OnCheckInvite,
        I_OnRawMode, I_OnCheckKey, I_OnCheckLimit, I_OnCheckBan, I_OnCheckChannelBan, I_OnExtBanCheck,
-       I_OnPreChangeHost, I_OnPreTopicChange,
+       I_OnPreChangeHost, I_OnPreTopicChange, I_OnConnectionFail,
        I_OnPostTopicChange, I_OnPostConnect, I_OnPostDeoper,
        I_OnPreChangeRealName, I_OnUserRegister, I_OnChannelPreDelete, I_OnChannelDelete,
        I_OnPostOper, I_OnPostCommand, I_OnPostJoin,
@@ -942,6 +942,14 @@ class CoreExport Module : public classbase, public usecountbase
         * deny the message from being sent, or MOD_RES_PASSTHRU to let another module handle the event.
         */
        virtual ModResult OnUserWrite(LocalUser* user, ClientProtocol::Message& msg);
+
+       /** Called when a user connection has been unexpectedly disconnected.
+        * @param user The user who has been unexpectedly disconnected.
+        * @param error The type of error which caused this connection failure.
+        * @return MOD_RES_ALLOW to explicitly retain the user as a zombie, MOD_RES_DENY to explicitly
+        * disconnect the user, or MOD_RES_PASSTHRU to let another module handle the event.
+        */
+       virtual ModResult OnConnectionFail(LocalUser* user, BufferedSocketError error);
 };
 
 /** ModuleManager takes care of all things module-related
index 3e268dae6ede33ca420e784cfe8940bab3a95aef..6f7ca2694b454239e6aa8078990807baf8c2bc30 100644 (file)
@@ -140,6 +140,7 @@ void                Module::OnSetUserIP(LocalUser*) { DetachEvent(I_OnSetUserIP); }
 void           Module::OnServiceAdd(ServiceProvider&) { DetachEvent(I_OnServiceAdd); }
 void           Module::OnServiceDel(ServiceProvider&) { DetachEvent(I_OnServiceDel); }
 ModResult      Module::OnUserWrite(LocalUser*, ClientProtocol::Message&) { DetachEvent(I_OnUserWrite); return MOD_RES_PASSTHRU; }
+ModResult      Module::OnConnectionFail(LocalUser*, BufferedSocketError) { DetachEvent(I_OnConnectionFail); return MOD_RES_PASSTHRU; }
 
 ServiceProvider::ServiceProvider(Module* Creator, const std::string& Name, ServiceType Type)
        : creator(Creator), name(Name), service(Type)
index 6acd25ac5200eeb2860abc4969a63e5522dcb09a..4f65994aa29be6399964f51869c5b5546e30d627 100644 (file)
@@ -58,6 +58,16 @@ namespace
                // This user didn't answer the last ping, remove them.
                if (!user->lastping)
                {
+                       ModResult res;
+                       FIRST_MOD_RESULT(OnConnectionFail, res, (user, I_ERR_TIMEOUT));
+                       if (res == MOD_RES_ALLOW)
+                       {
+                               // A module is preventing this user from being timed out.
+                               user->lastping = 1;
+                               user->nextping = ServerInstance->Time() + user->MyClass->GetPingTime();
+                               return;
+                       }
+
                        time_t secs = ServerInstance->Time() - (user->nextping - user->MyClass->GetPingTime());
                        const std::string message = "Ping timeout: " + ConvToStr(secs) + (secs != 1 ? " seconds" : " second");
                        ServerInstance->Users.QuitUser(user, message);
index a3807bd751fd8cac69dd3deed2824eeba31975a0..c0dc69ff4fc3b2dff5048ab9924d1579c83b5a18 100644 (file)
@@ -308,9 +308,12 @@ bool UserIOHandler::OnSetEndPoint(const irc::sockets::sockaddrs& server, const i
        return !user->quitting;
 }
 
-void UserIOHandler::OnError(BufferedSocketError)
+void UserIOHandler::OnError(BufferedSocketError error)
 {
-       ServerInstance->Users->QuitUser(user, getError());
+       ModResult res;
+       FIRST_MOD_RESULT(OnConnectionFail, res, (user, error));
+       if (res != MOD_RES_ALLOW)
+               ServerInstance->Users->QuitUser(user, getError());
 }
 
 CullResult User::cull()