* | Inspire Internet Relay Chat Daemon |
* +------------------------------------+
*
- * Inspire is copyright (C) 2002-2005 ChatSpike-Dev.
+ * InspIRCd is copyright (C) 2002-2006 ChatSpike-Dev.
* E-mail:
* <brain@chatspike.net>
* <Craig@chatspike.net>
{
VersionString = "";
UserCount = OperCount = 0;
- this->SetNextPingTime(time(NULL) + 60);
+ this->SetNextPingTime(time(NULL) + 120);
this->SetPingFlag();
/* find the 'route' for this server (e.g. the one directly connected
{
/* process one channel at a time, applying modes. */
char* usr = (char*)params[usernum].c_str();
- char permissions = *usr;
- switch (permissions)
- {
- case '@':
- usr++;
- mode_users[modectr++] = usr;
- strlcat(modestring,"o",MAXBUF);
- break;
- case '%':
- usr++;
- mode_users[modectr++] = usr;
- strlcat(modestring,"h",MAXBUF);
- break;
- case '+':
- usr++;
- mode_users[modectr++] = usr;
- strlcat(modestring,"v",MAXBUF);
- break;
- }
- who = Srv->FindNick(usr);
- if (who)
- {
- Srv->JoinUserToChannel(who,channel,key);
- if (modectr >= (MAXMODES-1))
- {
- /* theres a mode for this user. push them onto the mode queue, and flush it
- * if there are more than MAXMODES to go.
- */
- if ((ourTS >= TS) || (Srv->IsUlined(who->server)))
- {
- /* We also always let u-lined clients win, no matter what the TS value */
- log(DEBUG,"Our our channel newer than theirs, accepting their modes");
- Srv->SendMode(mode_users,modectr,who);
- }
- else
+ /* Safety check just to make sure someones not sent us an FJOIN full of spaces
+ * (is this even possible?) */
+ if (usr && *usr)
+ {
+ char permissions = *usr;
+ switch (permissions)
+ {
+ case '@':
+ usr++;
+ mode_users[modectr++] = usr;
+ strlcat(modestring,"o",MAXBUF);
+ break;
+ case '%':
+ usr++;
+ mode_users[modectr++] = usr;
+ strlcat(modestring,"h",MAXBUF);
+ break;
+ case '+':
+ usr++;
+ mode_users[modectr++] = usr;
+ strlcat(modestring,"v",MAXBUF);
+ break;
+ }
+ who = Srv->FindNick(usr);
+ if (who)
+ {
+ Srv->JoinUserToChannel(who,channel,key);
+ if (modectr >= (MAXMODES-1))
{
- log(DEBUG,"Their channel newer than ours, bouncing their modes");
- /* bouncy bouncy! */
- std::deque<std::string> params;
- /* modes are now being UNSET... */
- *mode_users[1] = '-';
- for (unsigned int x = 0; x < modectr; x++)
+ /* theres a mode for this user. push them onto the mode queue, and flush it
+ * if there are more than MAXMODES to go.
+ */
+ if ((ourTS >= TS) || (Srv->IsUlined(who->server)))
{
- params.push_back(mode_users[x]);
+ /* We also always let u-lined clients win, no matter what the TS value */
+ log(DEBUG,"Our our channel newer than theirs, accepting their modes");
+ Srv->SendMode(mode_users,modectr,who);
}
- // tell everyone to bounce the modes. bad modes, bad!
- DoOneToMany(Srv->GetServerName(),"FMODE",params);
+ else
+ {
+ log(DEBUG,"Their channel newer than ours, bouncing their modes");
+ /* bouncy bouncy! */
+ std::deque<std::string> params;
+ /* modes are now being UNSET... */
+ *mode_users[1] = '-';
+ for (unsigned int x = 0; x < modectr; x++)
+ {
+ params.push_back(mode_users[x]);
+ }
+ // tell everyone to bounce the modes. bad modes, bad!
+ DoOneToMany(Srv->GetServerName(),"FMODE",params);
+ }
+ strcpy(mode_users[1],"+");
+ modectr = 2;
}
- strcpy(mode_users[1],"+");
- modectr = 2;
}
}
}
log(DEBUG,"Sending FJOINs to other server for %s",c->name);
char list[MAXBUF];
snprintf(list,MAXBUF,":%s FJOIN %s %lu",Srv->GetServerName().c_str(),c->name,(unsigned long)c->age);
- std::vector<char*> *ulist = c->GetUsers();
- for (unsigned int i = 0; i < ulist->size(); i++)
+ std::map<char*,char*> *ulist = c->GetUsers();
+ for (std::map<char*,char*>::iterator i = ulist->begin(); i != ulist->end(); i++)
{
- char* o = (*ulist)[i];
+ char* o = i->second;
userrec* otheruser = (userrec*)o;
strlcat(list," ",MAXBUF);
strlcat(list,cmode(otheruser,c),MAXBUF);
virtual bool OnDataReady()
{
char* data = this->Read();
- if (data)
+ /* Check that the data read is a valid pointer and it has some content */
+ if (data && *data)
{
this->in_buffer += data;
/* While there is at least one new line in the buffer,
}
}
}
+ /* EAGAIN returns an empty but non-NULL string, so this
+ * evaluates to TRUE for EAGAIN but to FALSE for EOF.
+ */
return (data != NULL);
}
if (params.size() == 1)
{
userrec* x = Srv->FindNick(params[0]);
- if (x->fd > -1)
+ if ((x) && (x->fd > -1))
{
userrec* x = Srv->FindNick(params[0]);
log(DEBUG,"Got IDLE");
{
std::string who_did_the_whois = params[0];
userrec* who_to_send_to = Srv->FindNick(who_did_the_whois);
- if (who_to_send_to->fd > -1)
+ if ((who_to_send_to) && (who_to_send_to->fd > -1))
{
log(DEBUG,"Got final IDLE");
// an incoming reply to a whois we sent out
if (line == "")
return true;
Srv->Log(DEBUG,"IN: "+line);
+
std::deque<std::string> params;
this->Split(line,true,params);
std::string command = "";
{
return this->Capab(params);
}
+ else if ((command == "U") || (command == "S"))
+ {
+ this->WriteLine("ERROR :Cannot use the old-style mesh linking protocol with m_spanningtree.so!");
+ return false;
+ }
else
{
this->WriteLine("ERROR :Invalid command in negotiation phase.");
// silently ignore.
return true;
}
+ else if ((command == "U") || (command == "S"))
+ {
+ this->WriteLine("ERROR :Cannot use the old-style mesh linking protocol with m_spanningtree.so!");
+ return false;
+ }
else if (command == "BURST")
{
this->LinkState = CONNECTED;
log(DEBUG,"Protocol violation: Fake direction in command '%s' from connection '%s'",line.c_str(),this->GetName().c_str());
return true;
}
+
+ /* Fix by brain:
+ * When there is activity on the socket, reset the ping counter so
+ * that we're not wasting bandwidth pinging an active server.
+ */
+ route_back_again->SetNextPingTime(time(NULL) + 120);
+ route_back_again->SetPingFlag();
}
if (command == "SVSMODE")
// returns a list of DIRECT servernames for a specific channel
void GetListOfServersForChannel(chanrec* c, std::deque<TreeServer*> &list)
{
- std::vector<char*> *ulist = c->GetUsers();
- unsigned int ucount = ulist->size();
- for (unsigned int i = 0; i < ucount; i++)
+ std::map<char*,char*> *ulist = c->GetUsers();
+ for (std::map<char*,char*>::iterator i = ulist->begin(); i != ulist->end(); i++)
{
- char* o = (*ulist)[i];
+ char* o = i->second;
userrec* otheruser = (userrec*)o;
if (otheruser->fd < 0)
{
memset(spacer,' ',40);
if ((40 - Current->GetName().length() - depth) > 1) {
spacer[40 - Current->GetName().length() - depth] = '\0';
- } else {
+ }
+ else
+ {
spacer[5] = '\0';
}
if (clientlist.size() == 0) {
// If there are no users, WHO THE HELL DID THE /MAP?!?!?!
percent = 0;
- } else {
+ }
+ else
+ {
percent = ((float)Current->GetUserCount() / (float)clientlist.size()) * 100;
}
- snprintf(text, 80, "%s %s%d [%.2f%%]", Current->GetName().c_str(), spacer, Current->GetUserCount(), percent);
+ snprintf(text, 80, "%s %s%5d [%5.2f%%]", Current->GetName().c_str(), spacer, Current->GetUserCount(), percent);
strlcpy(&matrix[line][depth],text,80);
line++;
for (unsigned int q = 0; q < Current->ChildCount(); q++)
log(DEBUG,"Splitting server %s",s->GetName().c_str());
WriteOpers("*** SQUIT: Server \002%s\002 removed from network by %s",parameters[0],user->nick);
sock->Squit(s,"Server quit by "+std::string(user->nick)+"!"+std::string(user->ident)+"@"+std::string(user->host));
- sock->Close();
+ Srv->RemoveSocket(sock);
}
else
{
TreeSocket* sock = serv->GetSocket();
if (sock)
{
- if (curtime >= serv->NextPingTime())
- {
- if (serv->AnsweredLastPing())
- {
- sock->WriteLine(":"+Srv->GetServerName()+" PING "+serv->GetName());
- serv->SetNextPingTime(curtime + 60);
- }
- else
- {
- // they didnt answer, boot them
- WriteOpers("*** Server \002%s\002 pinged out",serv->GetName().c_str());
- sock->Squit(serv,"Ping timeout");
- sock->Close();
- return;
- }
- }
+ if (curtime >= serv->NextPingTime())
+ {
+ if (serv->AnsweredLastPing())
+ {
+ sock->WriteLine(":"+Srv->GetServerName()+" PING "+serv->GetName());
+ serv->SetNextPingTime(curtime + 120);
+ }
+ else
+ {
+ // they didnt answer, boot them
+ WriteOpers("*** Server \002%s\002 pinged out",serv->GetName().c_str());
+ sock->Squit(serv,"Ping timeout");
+ Srv->RemoveSocket(sock);
+ return;
+ }
+ }
+
}
}
}
{
std::string Version = found->GetVersion();
WriteServ(user->fd,"351 %s :%s",user->nick,Version.c_str());
+ if (found == TreeRoot)
+ {
+ std::stringstream out(Config->data005);
+ std::string token = "";
+ std::string line5 = "";
+ int token_counter = 0;
+ while (!out.eof())
+ {
+ out >> token;
+ line5 = line5 + token + " ";
+ token_counter++;
+ if ((token_counter >= 13) || (out.eof() == true))
+ {
+ WriteServ(user->fd,"005 %s %s:are supported by this server",user->nick,line5.c_str());
+ line5 = "";
+ token_counter = 0;
+ }
+ }
+ }
}
else
{
return 1;
}
- virtual bool HandleStats(char ** parameters, int pcnt, userrec* user)
+ virtual int OnStats(char statschar, userrec* user)
{
- if (*parameters[0] == 'c')
+ if (statschar == 'c')
{
for (unsigned int i = 0; i < LinkBlocks.size(); i++)
{
- WriteServ(user->fd,"213 %s C *@%s * %s %d 0 %s",user->nick,LinkBlocks[i].IPAddr.c_str(),LinkBlocks[i].Name.c_str(),LinkBlocks[i].Port,(LinkBlocks[i].EncryptionKey != "" ? "es" : " s"));
+ WriteServ(user->fd,"213 %s C *@%s * %s %d 0 %c%c%c",user->nick,LinkBlocks[i].IPAddr.c_str(),LinkBlocks[i].Name.c_str(),LinkBlocks[i].Port,(LinkBlocks[i].EncryptionKey != "" ? 'e' : '-'),(LinkBlocks[i].AutoConnect ? 'a' : '-'),'s');
WriteServ(user->fd,"244 %s H * * %s",user->nick,LinkBlocks[i].Name.c_str());
}
- WriteServ(user->fd,"219 %s %s :End of /STATS report",user->nick,parameters[0]);
- WriteOpers("*** Notice: Stats '%s' requested by %s (%s@%s)",parameters[0],user->nick,user->ident,user->host);
- return true;
+ WriteServ(user->fd,"219 %s %c :End of /STATS report",user->nick,statschar);
+ WriteOpers("*** Notice: Stats '%c' requested by %s (%s@%s)",statschar,user->nick,user->ident,user->host);
+ return 1;
}
- return false;
+ return 0;
}
virtual int OnPreCommand(std::string command, char **parameters, int pcnt, userrec *user, bool validated)
{
return this->HandleSquit(parameters,pcnt,user);
}
- else if (command == "STATS")
- {
- return this->HandleStats(parameters,pcnt,user);
- }
else if (command == "MAP")
{
this->HandleMap(parameters,pcnt,user);
List[I_OnUserQuit] = List[I_OnUserPostNick] = List[I_OnUserKick] = List[I_OnRemoteKill] = List[I_OnRehash] = 1;
List[I_OnOper] = List[I_OnAddGLine] = List[I_OnAddZLine] = List[I_OnAddQLine] = List[I_OnAddELine] = 1;
List[I_OnDelGLine] = List[I_OnDelZLine] = List[I_OnDelQLine] = List[I_OnDelELine] = List[I_ProtoSendMode] = List[I_OnMode] = 1;
- List[I_ProtoSendMetaData] = 1;
+ List[I_OnStats] = List[I_ProtoSendMetaData] = 1;
+ }
+
+ /* It is IMPORTANT that m_spanningtree is the last module in the chain
+ * so that any activity it sees is FINAL, e.g. we arent going to send out
+ * a NICK message before m_cloaking has finished putting the +x on the user,
+ * etc etc.
+ * Therefore, we return PRIORITY_LAST to make sure we end up at the END of
+ * the module call queue.
+ */
+ Priority Prioritize()
+ {
+ return PRIORITY_LAST;
}
};