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,
* 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
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)
// 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);
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()