summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordanieldg <danieldg@e03df62e-2008-0410-955e-edbf42e46eb7>2009-10-25 15:21:45 +0000
committerdanieldg <danieldg@e03df62e-2008-0410-955e-edbf42e46eb7>2009-10-25 15:21:45 +0000
commit6fe52cbb3ba72a5ecdded3f51c8515bf75e6801f (patch)
tree19b755377e2d830c78346930b8df27bca7d522f6
parent5d73e8928826340aaca9e78205ffb093a6b4f95c (diff)
Fixes found by removing User inheritance from StreamSocket
git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@11975 e03df62e-2008-0410-955e-edbf42e46eb7
-rw-r--r--include/configreader.h25
-rw-r--r--include/inspircd.h27
-rw-r--r--include/socketengine.h3
-rw-r--r--include/users.h36
-rw-r--r--src/command_parse.cpp6
-rw-r--r--src/commands.cpp2
-rw-r--r--src/modules/extra/m_ssl_gnutls.cpp16
-rw-r--r--src/modules/extra/m_ssl_openssl.cpp15
-rw-r--r--src/modules/m_cgiirc.cpp4
-rw-r--r--src/modules/m_spanningtree/main.cpp4
-rw-r--r--src/modules/m_spanningtree/override_whois.cpp2
-rw-r--r--src/modules/m_testnet.cpp4
-rw-r--r--src/modules/ssl.h6
-rw-r--r--src/usermanager.cpp15
-rw-r--r--src/users.cpp52
15 files changed, 101 insertions, 116 deletions
diff --git a/include/configreader.h b/include/configreader.h
index 4b42bcd43..4b425e03b 100644
--- a/include/configreader.h
+++ b/include/configreader.h
@@ -598,4 +598,29 @@ class CoreExport ServerConfig
};
+/** The background thread for config reading, so that reading from executable includes
+ * does not block.
+ */
+class CoreExport ConfigReaderThread : public Thread
+{
+ ServerConfig* Config;
+ volatile bool done;
+ public:
+ const std::string TheUserUID;
+ ConfigReaderThread(const std::string &useruid)
+ : Config(new ServerConfig), done(false), TheUserUID(useruid)
+ {
+ }
+
+ virtual ~ConfigReaderThread()
+ {
+ delete Config;
+ }
+
+ void Run();
+ /** Run in the main thread to apply the configuration */
+ void Finish();
+ bool IsDone() { return done; }
+};
+
#endif
diff --git a/include/inspircd.h b/include/inspircd.h
index a183e1ded..2b6fc579a 100644
--- a/include/inspircd.h
+++ b/include/inspircd.h
@@ -79,10 +79,10 @@ CoreExport extern InspIRCd* ServerInstance;
#include "filelogger.h"
#include "caller.h"
#include "modules.h"
+#include "threadengine.h"
#include "configreader.h"
#include "inspstring.h"
#include "protocol.h"
-#include "threadengine.h"
#ifndef PATH_MAX
#warning Potentially broken system, PATH_MAX undefined
@@ -240,31 +240,6 @@ DEFINE_HANDLER2(IsChannelHandler, bool, const char*, size_t);
DEFINE_HANDLER1(IsSIDHandler, bool, const std::string&);
DEFINE_HANDLER1(RehashHandler, void, const std::string&);
-/** The background thread for config reading, so that reading from executable includes
- * does not block.
- */
-class CoreExport ConfigReaderThread : public Thread
-{
- ServerConfig* Config;
- volatile bool done;
- public:
- const std::string TheUserUID;
- ConfigReaderThread(const std::string &useruid)
- : Config(new ServerConfig), done(false), TheUserUID(useruid)
- {
- }
-
- virtual ~ConfigReaderThread()
- {
- delete Config;
- }
-
- void Run();
- /** Run in the main thread to apply the configuration */
- void Finish();
- bool IsDone() { return done; }
-};
-
/** The main class of the irc server.
* This class contains instances of all the other classes in this software.
* Amongst other things, it contains a ModeParser, a DNS object, a CommandParser
diff --git a/include/socketengine.h b/include/socketengine.h
index e0512b3aa..01f66ef21 100644
--- a/include/socketengine.h
+++ b/include/socketengine.h
@@ -133,9 +133,6 @@ enum EventMask
FD_TRIAL_NOTE_MASK = 0x5000
};
-class InspIRCd;
-class Module;
-
/** This class is a basic I/O handler class.
* Any object which wishes to receive basic I/O events
* from the socketengine must derive from this class and
diff --git a/include/users.h b/include/users.h
index 0fc6e3723..48f2b470c 100644
--- a/include/users.h
+++ b/include/users.h
@@ -56,6 +56,12 @@ enum RegistrationState {
REG_ALL = 7 /* REG_NICKUSER plus next bit along */
};
+enum UserType {
+ USERTYPE_LOCAL = 1,
+ USERTYPE_REMOTE = 2,
+ USERTYPE_SERVER = 3
+};
+
/** Holds information relevent to &lt;connect allow&gt; and &lt;connect deny&gt; tags in the config file.
*/
struct CoreExport ConnectClass : public refcountbase
@@ -357,6 +363,9 @@ class CoreExport User : public StreamSocket
*/
unsigned int lastping:1;
+ /** What type of user is this? */
+ const unsigned int usertype:2;
+
/** Get client IP string from sockaddr, using static internal buffer
* @return The IP string
*/
@@ -371,13 +380,10 @@ class CoreExport User : public StreamSocket
*/
bool SetClientIP(const char* sip);
- /** Default constructor
+ /** Constructor
* @throw CoreException if the UID allocated to the user already exists
- * @param Instance Creator instance
- * @param uid User UUID, or empty to allocate one automatically
- * @param srv Server that this user is from
*/
- User(const std::string &uid, const std::string& srv);
+ User(const std::string &uid, const std::string& srv, int objtype);
/** Check if the user matches a G or K line, and disconnect them if they do.
* @param doZline True if ZLines should be checked (if IP has changed since initial connect)
@@ -708,14 +714,6 @@ class CoreExport User : public StreamSocket
virtual CullResult cull();
};
-/** Represents a non-local user.
- * (in fact, any FD less than -1 does)
- */
-#define FD_MAGIC_NUMBER -42
-/** Represents a fake user (i.e. a server)
- */
-#define FD_FAKEUSER_NUMBER -7
-
class CoreExport LocalUser : public User
{
/** A list of channels the user has a pending invite to.
@@ -866,9 +864,8 @@ class CoreExport LocalUser : public User
class CoreExport RemoteUser : public User
{
public:
- RemoteUser(const std::string& uid, const std::string& srv) : User(uid, srv)
+ RemoteUser(const std::string& uid, const std::string& srv) : User(uid, srv, USERTYPE_REMOTE)
{
- SetFd(FD_MAGIC_NUMBER);
}
virtual void SendText(const std::string& line);
};
@@ -876,9 +873,8 @@ class CoreExport RemoteUser : public User
class CoreExport FakeUser : public User
{
public:
- FakeUser(const std::string &uid, const std::string& srv) : User(uid, srv)
+ FakeUser(const std::string &uid, const std::string& srv) : User(uid, srv, USERTYPE_SERVER)
{
- SetFd(FD_FAKEUSER_NUMBER);
nick = srv;
}
@@ -892,17 +888,17 @@ class CoreExport FakeUser : public User
/** Is a local user */
inline LocalUser* IS_LOCAL(User* u)
{
- return u->GetFd() > -1 ? static_cast<LocalUser*>(u) : NULL;
+ return u->usertype == USERTYPE_LOCAL ? static_cast<LocalUser*>(u) : NULL;
}
/** Is a remote user */
inline RemoteUser* IS_REMOTE(User* u)
{
- return u->GetFd() == FD_MAGIC_NUMBER ? static_cast<RemoteUser*>(u) : NULL;
+ return u->usertype == USERTYPE_REMOTE ? static_cast<RemoteUser*>(u) : NULL;
}
/** Is a server fakeuser */
inline FakeUser* IS_SERVER(User* u)
{
- return u->GetFd() == FD_FAKEUSER_NUMBER ? static_cast<FakeUser*>(u) : NULL;
+ return u->usertype == USERTYPE_SERVER ? static_cast<FakeUser*>(u) : NULL;
}
/** Is an oper */
#define IS_OPER(x) (x->oper)
diff --git a/src/command_parse.cpp b/src/command_parse.cpp
index 883507058..772b23117 100644
--- a/src/command_parse.cpp
+++ b/src/command_parse.cpp
@@ -412,8 +412,8 @@ bool CommandParser::ProcessBuffer(std::string &buffer,User *user)
if (!user || buffer.empty())
return true;
- ServerInstance->Logs->Log("USERINPUT", DEBUG, "C[%d] I :%s %s",
- user->GetFd(), user->nick.c_str(), buffer.c_str());
+ ServerInstance->Logs->Log("USERINPUT", DEBUG, "C[%s] I :%s %s",
+ user->uuid.c_str(), user->nick.c_str(), buffer.c_str());
return ProcessCommand(user,buffer);
}
@@ -428,7 +428,7 @@ bool CommandParser::AddCommand(Command *f)
return false;
}
-CommandParser::CommandParser()
+CommandParser::CommandParser()
{
para.resize(128);
}
diff --git a/src/commands.cpp b/src/commands.cpp
index a1a190502..9de3bbead 100644
--- a/src/commands.cpp
+++ b/src/commands.cpp
@@ -117,7 +117,7 @@ CmdResult SplitCommand::Handle(const std::vector<std::string>& parms, User* u)
return HandleRemote(parms, IS_REMOTE(u));
if (IS_SERVER(u))
return HandleServer(parms, IS_SERVER(u));
- ServerInstance->Logs->Log("COMMAND", ERROR, "Unknown user type in command (fd=%d)!", u->GetFd());
+ ServerInstance->Logs->Log("COMMAND", ERROR, "Unknown user type in command (uuid=%s)!", u->uuid.c_str());
return CMD_INVALID;
}
diff --git a/src/modules/extra/m_ssl_gnutls.cpp b/src/modules/extra/m_ssl_gnutls.cpp
index 25b47c2fe..95beff3aa 100644
--- a/src/modules/extra/m_ssl_gnutls.cpp
+++ b/src/modules/extra/m_ssl_gnutls.cpp
@@ -86,15 +86,15 @@ public:
issl_status status;
};
-class CommandStartTLS : public Command
+class CommandStartTLS : public SplitCommand
{
public:
- CommandStartTLS (Module* mod) : Command(mod, "STARTTLS")
+ CommandStartTLS (Module* mod) : SplitCommand(mod, "STARTTLS")
{
works_before_reg = true;
}
- CmdResult Handle (const std::vector<std::string> &parameters, User *user)
+ CmdResult HandleLocal(const std::vector<std::string> &parameters, LocalUser *user)
{
/* changed from == REG_ALL to catch clients sending STARTTLS
* after NICK and USER but before OnUserConnect completes and
@@ -158,7 +158,7 @@ class ModuleSSLGnuTLS : public Module
// Void return, guess we assume success
gnutls_certificate_set_dh_params(x509_cred, dh_params);
- Implementation eventlist[] = { I_On005Numeric, I_OnRehash, I_OnModuleRehash, I_OnPostConnect,
+ Implementation eventlist[] = { I_On005Numeric, I_OnRehash, I_OnModuleRehash, I_OnUserConnect,
I_OnEvent, I_OnHookIO };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
@@ -296,9 +296,9 @@ class ModuleSSLGnuTLS : public Module
{
if(target_type == TYPE_USER)
{
- User* user = static_cast<User*>(item);
+ LocalUser* user = IS_LOCAL(static_cast<User*>(item));
- if (user->GetIOHook() == this)
+ if (user && user->GetIOHook() == this)
{
// User is using SSL, they're a local user, and they're using one of *our* SSL ports.
// Potentially there could be multiple SSL modules loaded at once on different ports.
@@ -547,10 +547,8 @@ class ModuleSSLGnuTLS : public Module
}
}
- void OnPostConnect(User* user)
+ void OnUserConnect(LocalUser* user)
{
- // This occurs AFTER OnUserConnect so we can be sure the
- // protocol module has propagated the NICK message.
if (user->GetIOHook() == this)
{
if (sessions[user->GetFd()].sess)
diff --git a/src/modules/extra/m_ssl_openssl.cpp b/src/modules/extra/m_ssl_openssl.cpp
index 25d1cd9dd..61b54eceb 100644
--- a/src/modules/extra/m_ssl_openssl.cpp
+++ b/src/modules/extra/m_ssl_openssl.cpp
@@ -125,9 +125,7 @@ class ModuleSSLOpenSSL : public Module
// Needs the flag as it ignores a plain /rehash
OnModuleRehash(NULL,"ssl");
- Implementation eventlist[] = {
- I_On005Numeric, I_OnRehash, I_OnModuleRehash, I_OnPostConnect,
- I_OnHookIO };
+ Implementation eventlist[] = { I_On005Numeric, I_OnRehash, I_OnModuleRehash, I_OnHookIO };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
@@ -250,9 +248,9 @@ class ModuleSSLOpenSSL : public Module
{
if (target_type == TYPE_USER)
{
- User* user = (User*)item;
+ LocalUser* user = IS_LOCAL((User*)item);
- if (user->GetIOHook() == this)
+ if (user && user->GetIOHook() == this)
{
// User is using SSL, they're a local user, and they're using one of *our* SSL ports.
// Potentially there could be multiple SSL modules loaded at once on different ports.
@@ -597,13 +595,6 @@ class ModuleSSLOpenSSL : public Module
X509_free(cert);
SSLCertSubmission(user, this, sslinfo, certinfo);
}
-
- void Prioritize()
- {
- Module* server = ServerInstance->Modules->Find("m_spanningtree.so");
- ServerInstance->Modules->SetPriority(this, I_OnPostConnect, PRIORITY_AFTER, &server);
- }
-
};
static int error_callback(const char *str, size_t len, void *u)
diff --git a/src/modules/m_cgiirc.cpp b/src/modules/m_cgiirc.cpp
index 5f8cfeca7..49a96c42d 100644
--- a/src/modules/m_cgiirc.cpp
+++ b/src/modules/m_cgiirc.cpp
@@ -103,10 +103,10 @@ class CGIResolver : public Resolver
{
std::string typ;
int theirfd;
- User* them;
+ LocalUser* them;
bool notify;
public:
- CGIResolver(Module* me, bool NotifyOpers, const std::string &source, bool forward, User* u, int userfd, const std::string &type, bool &cached)
+ CGIResolver(Module* me, bool NotifyOpers, const std::string &source, bool forward, LocalUser* u, int userfd, const std::string &type, bool &cached)
: Resolver(source, forward ? DNS_QUERY_A : DNS_QUERY_PTR4, cached, me), typ(type), theirfd(userfd), them(u), notify(NotifyOpers) { }
virtual void OnLookupComplete(const std::string &result, unsigned int ttl, bool cached)
diff --git a/src/modules/m_spanningtree/main.cpp b/src/modules/m_spanningtree/main.cpp
index d14f0ebe4..8da34af53 100644
--- a/src/modules/m_spanningtree/main.cpp
+++ b/src/modules/m_spanningtree/main.cpp
@@ -490,7 +490,7 @@ void ModuleSpanningTree::OnUserNotice(User* user, void* dest, int target_type, c
if (target_type == TYPE_USER)
{
User* d = (User*)dest;
- if ((d->GetFd() < 0) && (IS_LOCAL(user)))
+ if (!IS_LOCAL(d) && IS_LOCAL(user))
{
parameterlist params;
params.push_back(d->uuid);
@@ -543,7 +543,7 @@ void ModuleSpanningTree::OnUserMessage(User* user, void* dest, int target_type,
// route private messages which are targetted at clients only to the server
// which needs to receive them
User* d = (User*)dest;
- if ((d->GetFd() < 0) && (IS_LOCAL(user)))
+ if (!IS_LOCAL(d) && (IS_LOCAL(user)))
{
parameterlist params;
params.push_back(d->uuid);
diff --git a/src/modules/m_spanningtree/override_whois.cpp b/src/modules/m_spanningtree/override_whois.cpp
index ee3be53fd..db75973d1 100644
--- a/src/modules/m_spanningtree/override_whois.cpp
+++ b/src/modules/m_spanningtree/override_whois.cpp
@@ -29,7 +29,7 @@ ModResult ModuleSpanningTree::HandleRemoteWhois(const std::vector<std::string>&
if ((IS_LOCAL(user)) && (parameters.size() > 1))
{
User* remote = ServerInstance->FindNick(parameters[1]);
- if ((remote) && (remote->GetFd() < 0))
+ if (remote && !IS_LOCAL(remote))
{
parameterlist params;
params.push_back(remote->uuid);
diff --git a/src/modules/m_testnet.cpp b/src/modules/m_testnet.cpp
index 7f825a728..e467923c9 100644
--- a/src/modules/m_testnet.cpp
+++ b/src/modules/m_testnet.cpp
@@ -36,10 +36,10 @@ class CommandTest : public Command
{
IS_LOCAL(user)->Penalty += 100;
}
- else if (parameters[0] == "shutdown")
+ else if (parameters[0] == "shutdown" && IS_LOCAL(user))
{
int i = parameters.size() > 1 ? atoi(parameters[1].c_str()) : 2;
- ServerInstance->SE->Shutdown(user->GetFd(), i);
+ ServerInstance->SE->Shutdown(IS_LOCAL(user)->GetFd(), i);
}
return CMD_SUCCESS;
}
diff --git a/src/modules/ssl.h b/src/modules/ssl.h
index 39a7ef5f6..3bc78cf98 100644
--- a/src/modules/ssl.h
+++ b/src/modules/ssl.h
@@ -128,6 +128,12 @@ struct SSLCertificateRequest : public Request
Send();
}
+ SSLCertificateRequest(Extensible* e, Module* Me, Module* info = ServerInstance->Modules->Find("m_sslinfo.so"))
+ : Request(Me, info, "GET_CERT"), item(e), cert(NULL)
+ {
+ Send();
+ }
+
std::string GetFingerprint()
{
if (cert)
diff --git a/src/usermanager.cpp b/src/usermanager.cpp
index 06d6ad1cd..f620a264d 100644
--- a/src/usermanager.cpp
+++ b/src/usermanager.cpp
@@ -195,13 +195,14 @@ void UserManager::QuitUser(User *user, const std::string &quitreason, const char
if (IS_LOCAL(user))
{
- FOREACH_MOD(I_OnUserDisconnect,OnUserDisconnect(IS_LOCAL(user)));
- user->DoWrite();
- if (user->GetIOHook())
+ LocalUser* lu = IS_LOCAL(user);
+ FOREACH_MOD(I_OnUserDisconnect,OnUserDisconnect(lu));
+ lu->DoWrite();
+ if (lu->GetIOHook())
{
try
{
- user->GetIOHook()->OnStreamSocketClose(user);
+ lu->GetIOHook()->OnStreamSocketClose(lu);
}
catch (CoreException& modexcept)
{
@@ -209,10 +210,8 @@ void UserManager::QuitUser(User *user, const std::string &quitreason, const char
}
}
- ServerInstance->SE->DelFd(user);
- user->Close();
- // user->Close() will set fd to -1; this breaks IS_LOCAL. Fix
- user->SetFd(INT_MAX);
+ ServerInstance->SE->DelFd(lu);
+ lu->Close();
}
/*
diff --git a/src/users.cpp b/src/users.cpp
index cf2d11a0a..58c105047 100644
--- a/src/users.cpp
+++ b/src/users.cpp
@@ -221,14 +221,13 @@ void User::DecrementModes()
}
}
-User::User(const std::string &uid, const std::string& sid)
- : uuid(uid), server(sid)
+User::User(const std::string &uid, const std::string& sid, int type)
+ : uuid(uid), server(sid), usertype(type)
{
age = ServerInstance->Time();
signon = idle_lastmsg = 0;
registered = 0;
quietquit = quitting = exempt = dns_done = false;
- fd = -1;
client_sa.sa.sa_family = AF_UNSPEC;
ServerInstance->Logs->Log("USERS", DEBUG, "New UUID for user: %s", uuid.c_str());
@@ -240,7 +239,7 @@ User::User(const std::string &uid, const std::string& sid)
throw CoreException("Duplicate UUID "+std::string(uuid)+" in User constructor");
}
-LocalUser::LocalUser() : User(ServerInstance->GetUID(), ServerInstance->Config->ServerName)
+LocalUser::LocalUser() : User(ServerInstance->GetUID(), ServerInstance->Config->ServerName, USERTYPE_LOCAL)
{
bytes_in = bytes_out = cmds_in = cmds_out = 0;
server_sa.sa.sa_family = AF_UNSPEC;
@@ -585,8 +584,6 @@ CullResult User::cull()
if (!quitting)
ServerInstance->Users->QuitUser(this, "Culled without QuitUser");
PurgeEmptyChannels();
- if (IS_LOCAL(this) && fd != INT_MAX)
- Close();
this->InvalidateCache();
this->DecrementModes();
@@ -605,6 +602,7 @@ CullResult LocalUser::cull()
if (client_sa.sa.sa_family != AF_UNSPEC)
ServerInstance->Users->RemoveCloneCounts(this);
+ Close();
return User::cull();
}
@@ -1174,10 +1172,10 @@ void User::WriteCommonRaw(const std::string &line, bool include_self)
for (std::map<User*,bool>::iterator i = exceptions.begin(); i != exceptions.end(); ++i)
{
- User* u = i->first;
- if (IS_LOCAL(u) && !u->quitting)
+ LocalUser* u = IS_LOCAL(i->first);
+ if (u && !u->quitting)
{
- already_sent[u->fd] = uniq_id;
+ already_sent[u->GetFd()] = uniq_id;
if (i->second)
u->Write(line);
}
@@ -1188,10 +1186,10 @@ void User::WriteCommonRaw(const std::string &line, bool include_self)
const UserMembList* ulist = c->GetUsers();
for (UserMembList::const_iterator i = ulist->begin(); i != ulist->end(); i++)
{
- User* u = i->first;
- if (IS_LOCAL(u) && !u->quitting && already_sent[u->fd] != uniq_id)
+ LocalUser* u = IS_LOCAL(i->first);
+ if (u && !u->quitting && already_sent[u->GetFd()] != uniq_id)
{
- already_sent[u->fd] = uniq_id;
+ already_sent[u->GetFd()] = uniq_id;
u->Write(line);
}
}
@@ -1220,10 +1218,10 @@ void User::WriteCommonQuit(const std::string &normal_text, const std::string &op
for (std::map<User*,bool>::iterator i = exceptions.begin(); i != exceptions.end(); ++i)
{
- User* u = i->first;
- if (IS_LOCAL(u) && !u->quitting)
+ LocalUser* u = IS_LOCAL(i->first);
+ if (u && !u->quitting)
{
- already_sent[u->fd] = uniq_id;
+ already_sent[u->GetFd()] = uniq_id;
if (i->second)
u->Write(IS_OPER(u) ? out2 : out1);
}
@@ -1233,10 +1231,10 @@ void User::WriteCommonQuit(const std::string &normal_text, const std::string &op
const UserMembList* ulist = (*v)->GetUsers();
for (UserMembList::const_iterator i = ulist->begin(); i != ulist->end(); i++)
{
- User* u = i->first;
- if (IS_LOCAL(u) && !u->quitting && (already_sent[u->fd] != uniq_id))
+ LocalUser* u = IS_LOCAL(i->first);
+ if (u && !u->quitting && (already_sent[u->GetFd()] != uniq_id))
{
- already_sent[u->fd] = uniq_id;
+ already_sent[u->GetFd()] = uniq_id;
u->Write(IS_OPER(u) ? out2 : out1);
}
}
@@ -1357,17 +1355,17 @@ void User::DoHostCycle(const std::string &quitline)
for (std::map<User*,bool>::iterator i = exceptions.begin(); i != exceptions.end(); ++i)
{
- User* u = i->first;
- if (IS_LOCAL(u) && !u->quitting)
+ LocalUser* u = IS_LOCAL(i->first);
+ if (u && !u->quitting)
{
if (i->second)
{
- already_sent[u->fd] = seen_id;
+ already_sent[u->GetFd()] = seen_id;
u->Write(quitline);
}
else
{
- already_sent[u->fd] = silent_id;
+ already_sent[u->GetFd()] = silent_id;
}
}
}
@@ -1389,16 +1387,16 @@ void User::DoHostCycle(const std::string &quitline)
const UserMembList *ulist = c->GetUsers();
for (UserMembList::const_iterator i = ulist->begin(); i != ulist->end(); i++)
{
- User* u = i->first;
- if (u == this || !IS_LOCAL(u))
+ LocalUser* u = IS_LOCAL(i->first);
+ if (u == NULL || u == this)
continue;
- if (already_sent[u->fd] == silent_id)
+ if (already_sent[u->GetFd()] == silent_id)
continue;
- if (already_sent[u->fd] != seen_id)
+ if (already_sent[u->GetFd()] != seen_id)
{
u->Write(quitline);
- already_sent[i->first->fd] = seen_id;
+ already_sent[u->GetFd()] = seen_id;
}
u->Write(joinline);
if (modeline.length() > 0)