const char* sip = this->GetIPString();
UserResolver *res_reverse;
- QueryType resolvtype = this->ip.sa.sa_family == AF_INET6 ? DNS_QUERY_PTR6 : DNS_QUERY_PTR4;
+ QueryType resolvtype = this->client_sa.sa.sa_family == AF_INET6 ? DNS_QUERY_PTR6 : DNS_QUERY_PTR4;
res_reverse = new UserResolver(this->ServerInstance, this, sip, resolvtype, cached);
this->ServerInstance->AddResolver(res_reverse, cached);
User::User(InspIRCd* Instance, const std::string &uid) : ServerInstance(Instance)
{
- server = (char*)Instance->FindServerNamePtr(Instance->Config->ServerName);
+ server = Instance->FindServerNamePtr(Instance->Config->ServerName);
age = ServerInstance->Time();
Penalty = 0;
lastping = signon = idle_lastmsg = nping = registered = 0;
bytes_in = bytes_out = cmds_in = cmds_out = 0;
quietquit = quitting = exempt = haspassed = dns_done = false;
fd = -1;
- ip.sa.sa_family = AF_UNSPEC;
+ server_sa.sa.sa_family = AF_UNSPEC;
+ client_sa.sa.sa_family = AF_UNSPEC;
recvq.clear();
sendq.clear();
Visibility = NULL;
this->InvalidateCache();
this->DecrementModes();
- if (ip.sa.sa_family != AF_UNSPEC)
+ if (client_sa.sa.sa_family != AF_UNSPEC)
ServerInstance->Users->RemoveCloneCounts(this);
ServerInstance->Users->uuidlist->erase(uuid);
this->registered = REG_ALL;
- ServerInstance->PI->Introduce(this);
-
FOREACH_MOD(I_OnPostConnect,OnPostConnect(this));
ServerInstance->SNO->WriteToSnoMask('c',"Client connecting on port %d: %s!%s@%s [%s] [%s]",
return false;
}
-void User::SetSockAddr(const char* sip, int port)
-{
- this->cachedip = "";
-
- if (inet_pton(AF_INET, sip, &ip.in4.sin_addr))
- {
- ip.in4.sin_family = AF_INET;
- ip.in4.sin_port = port;
- return;
- }
- else if (inet_pton(AF_INET6, sip, &ip.in6.sin6_addr))
- {
- ip.in6.sin6_family = AF_INET6;
- ip.in6.sin6_port = port;
- }
- else
- {
- ServerInstance->Logs->Log("USERS",DEBUG,"Uh oh, I dont know how to read IP '%s' on '%s'!",
- sip, this->nick.c_str());
- }
-}
-
int User::GetServerPort()
{
- switch (this->ip.sa.sa_family)
+ switch (this->server_sa.sa.sa_family)
{
case AF_INET6:
- return this->ip.in6.sin6_port;
+ return htons(this->server_sa.in6.sin6_port);
case AF_INET:
- return this->ip.in4.sin_port;
+ return htons(this->server_sa.in4.sin_port);
}
return 0;
}
* Original code written by Oliver Lupton (Om).
* Integrated by me. Thanks. :) -- w00t
*/
- switch (this->ip.sa.sa_family)
+ switch (this->client_sa.sa.sa_family)
{
case AF_INET6:
{
*/
for(i = 0; i < (16 - bytestozero); i++)
{
- v6.s6_addr[i] = ip.in6.sin6_addr.s6_addr[i];
+ v6.s6_addr[i] = client_sa.in6.sin6_addr.s6_addr[i];
}
/* And zero all the remaining bytes in the IP. */
throw "CIDR mask width greater than address width (IPv4, 32 bit)";
/* Users already have a sockaddr* pointer (User::ip) which contains either a v4 or v6 structure */
- v4.s_addr = ip.in4.sin_addr.s_addr;
+ v4.s_addr = client_sa.in4.sin_addr.s_addr;
/* To create the CIDR mask we want to set all the bits after 'range' bits of the address
* to zero. This means the last (32 - range) bits of the address must be set to zero.
return ""; // unused, but oh well
}
-const char* User::GetIPString()
+std::string User::GetServerIP()
{
- static char buf[40];
-
- if (!this->cachedip.empty())
- return this->cachedip.c_str();
+ int port;
+ std::string ip;
+ irc::sockets::satoap(&server_sa, ip, port);
+ return ip;
+}
- switch (this->ip.sa.sa_family)
+const char* User::GetIPString()
+{
+ int port;
+ if (cachedip.empty())
{
- case AF_INET6:
- {
- static char temp[41];
-
- inet_ntop(ip.in6.sin6_family, &ip.in6.sin6_addr, buf, sizeof(buf));
- /* IP addresses starting with a : on irc are a Bad Thing (tm) */
- if (*buf == ':')
- {
- strlcpy(&temp[1], buf, sizeof(temp) - 1);
- *temp = '0';
- this->cachedip = temp;
- return temp;
- }
-
- this->cachedip = buf;
- return buf;
- }
- break;
- case AF_INET:
- {
- inet_ntop(ip.in4.sin_family, &ip.in4.sin_addr, buf, sizeof(buf));
- this->cachedip = buf;
- return buf;
- }
- break;
- default:
- break;
+ irc::sockets::satoap(&client_sa, cachedip, port);
+ /* IP addresses starting with a : on irc are a Bad Thing (tm) */
+ if (cachedip.c_str()[0] == ':')
+ cachedip.insert(0,1,'0');
}
- // Unreachable, probably
- return "";
+ return cachedip.c_str();
}
-/** NOTE: We cannot pass a const reference to this method.
- * The string is changed by the workings of the method,
- * so that if we pass const ref, we end up copying it to
- * something we can change anyway. Makes sense to just let
- * the compiler do that copy for us.
- */
-void User::Write(std::string text)
+bool User::SetClientIP(const char* sip)
+{
+ this->cachedip = "";
+ return irc::sockets::aptosa(sip, 0, &client_sa);
+}
+
+void User::Write(const std::string& text)
{
if (!ServerInstance->SE->BoundsCheckFd(this))
return;
- try
- {
- ServerInstance->Logs->Log("USEROUTPUT", DEBUG,"C[%d] O %s", this->GetFd(), text.c_str());
- text.append("\r\n");
- }
- catch (...)
- {
- ServerInstance->Logs->Log("USEROUTPUT", DEBUG,"Exception in User::Write() std::string::append");
- return;
- }
+ ServerInstance->Logs->Log("USEROUTPUT", DEBUG,"C[%d] O %s", this->GetFd(), text.c_str());
if (this->GetIOHook())
{
try
{
this->GetIOHook()->OnRawSocketWrite(this->fd, text.data(), text.length());
+ this->GetIOHook()->OnRawSocketWrite(this->fd, "\r\n", 2);
}
catch (CoreException& modexcept)
{
else
{
this->AddWriteBuf(text);
+ this->AddWriteBuf("\r\n");
}
- ServerInstance->stats->statsSent += text.length();
+ ServerInstance->stats->statsSent += text.length() + 2;
this->ServerInstance->SE->WantWrite(this);
}
void User::WriteServ(const std::string& text)
{
- char textbuffer[MAXBUF];
-
- snprintf(textbuffer,MAXBUF,":%s %s",ServerInstance->Config->ServerName,text.c_str());
- this->Write(std::string(textbuffer));
+ this->Write(":%s %s",ServerInstance->Config->ServerName,text.c_str());
}
/** WriteServ()
return true;
}
+void User::DoHostCycle(const std::string &quitline)
+{
+ char buffer[MAXBUF];
+
+ int MOD_RESULT = 0;
+ FOREACH_RESULT(I_OnHostCycle, OnHostCycle(this));
+
+ if (!ServerInstance->Config->CycleHosts || MOD_RESULT)
+ return;
+
+ uniq_id++;
+
+ if (!already_sent)
+ InitializeAlreadySent(ServerInstance->SE);
+
+ for (UCListIter v = this->chans.begin(); v != this->chans.end(); v++)
+ {
+ Channel* c = v->first;
+ snprintf(buffer, MAXBUF, ":%s JOIN %s", GetFullHost().c_str(), c->name.c_str());
+ std::string joinline(buffer);
+ std::string modeline = this->ServerInstance->Modes->ModeString(this, c);
+ if (modeline.length() > 0)
+ {
+ snprintf(buffer, MAXBUF, ":%s MODE %s +%s", GetFullHost().c_str(), c->name.c_str(), modeline.c_str());
+ modeline = buffer;
+ }
+
+ CUList *ulist = c->GetUsers();
+ for (CUList::iterator i = ulist->begin(); i != ulist->end(); i++)
+ {
+ User* u = i->first;
+ if (u == this || !IS_LOCAL(u))
+ continue;
+
+ if (already_sent[i->first->fd] != uniq_id)
+ {
+ u->Write(quitline);
+ already_sent[i->first->fd] = uniq_id;
+ }
+ u->Write(joinline);
+ if (modeline.length() > 0)
+ u->Write(modeline);
+ }
+ }
+}
+
bool User::ChangeDisplayedHost(const char* shost)
{
if (dhost == shost)
FOREACH_MOD(I_OnChangeHost, OnChangeHost(this,shost));
- int MOD_RESULT = 0;
- FOREACH_RESULT(I_OnHostCycle, OnHostCycle(this));
-
- if (this->ServerInstance->Config->CycleHosts && !MOD_RESULT)
- this->WriteCommonExcept("QUIT :Changing hosts");
+ std::string quitstr = ":" + GetFullHost() + " QUIT :Changing host";
/* Fix by Om: User::dhost is 65 long, this was truncating some long hosts */
this->dhost.assign(shost, 0, 64);
this->InvalidateCache();
- if (this->ServerInstance->Config->CycleHosts && !MOD_RESULT)
- {
- for (UCListIter i = this->chans.begin(); i != this->chans.end(); i++)
- {
- i->first->WriteAllExceptSender(this, false, 0, "JOIN %s", i->first->name.c_str());
- std::string n = this->ServerInstance->Modes->ModeString(this, i->first);
- if (n.length() > 0)
- i->first->WriteAllExceptSender(this, true, 0, "MODE %s +%s", i->first->name.c_str(), n.c_str());
- }
- }
+ this->DoHostCycle(quitstr);
if (IS_LOCAL(this))
this->WriteNumeric(RPL_YOURDISPLAYEDHOST, "%s %s :is now your displayed host",this->nick.c_str(),this->dhost.c_str());
if (this->ident == newident)
return true;
- int MOD_RESULT = 0;
- FOREACH_RESULT(I_OnHostCycle, OnHostCycle(this));
-
- if (this->ServerInstance->Config->CycleHosts && !MOD_RESULT)
- this->WriteCommonExcept("%s","QUIT :Changing ident");
+ std::string quitstr = ":" + GetFullHost() + " QUIT :Changing ident";
this->ident.assign(newident, 0, ServerInstance->Config->Limits.IdentMax + 1);
this->InvalidateCache();
- if (this->ServerInstance->Config->CycleHosts && !MOD_RESULT)
- {
- for (UCListIter i = this->chans.begin(); i != this->chans.end(); i++)
- {
- i->first->WriteAllExceptSender(this, false, 0, "JOIN %s", i->first->name.c_str());
- std::string n = this->ServerInstance->Modes->ModeString(this, i->first);
- if (n.length() > 0)
- i->first->WriteAllExceptSender(this, true, 0, "MODE %s +%s", i->first->name.c_str(), n.c_str());
- }
- }
+ this->DoHostCycle(quitstr);
return true;
}