#include <errno.h>
#include <deque>
#include <errno.h>
+#include <unistd.h>
+#include <sched.h>
#include "connection.h"
#include "users.h"
#include "servers.h"
}
+
+std::string GetServerDescription(char* servername)
+{
+ for (int j = 0; j < 32; j++)
+ {
+ if (me[j] != NULL)
+ {
+ for (int k = 0; k < me[j]->connectors.size(); k++)
+ {
+ if (!strcasecmp(me[j]->connectors[k].GetServerName().c_str(),servername))
+ {
+ return me[j]->connectors[k].GetDescription();
+ }
+ }
+ }
+ return "";
+ }
+}
+
+
/* return 0 or 1 depending if users u and u2 share one or more common channels
* (used by QUIT, NICK etc which arent channel specific notices) */
{
WriteServ(user->fd,"319 %s %s :%s",user->nick, dest->nick, chlist(dest));
}
- WriteServ(user->fd,"312 %s %s %s :%s",user->nick, dest->nick, dest->server, ServerDesc);
+ WriteServ(user->fd,"312 %s %s %s :%s",user->nick, dest->nick, dest->server, GetServerDescription(dest->server));
if (strcmp(dest->awaymsg,""))
{
WriteServ(user->fd,"301 %s %s :%s",user->nick, dest->nick, dest->awaymsg);
}
}
+void DoSplitEveryone()
+{
+ bool go_again = true;
+ while (go_again)
+ {
+ go_again = false;
+ for (int i = 0; i < 32; i++)
+ {
+ if (me[i] != NULL)
+ {
+ for (vector<ircd_connector>::iterator j = me[i]->connectors.begin(); j != me[i]->connectors.end(); j++)
+ {
+ if (strcasecmp(j->GetServerName().c_str(),ServerName))
+ {
+ j->routes.clear();
+ j->CloseConnection();
+ me[i]->connectors.erase(j);
+ go_again = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ log(DEBUG,"Removed server. Will remove clients...");
+ // iterate through the userlist and remove all users on this server.
+ // because we're dealing with a mesh, we dont have to deal with anything
+ // "down-route" from this server (nice huh)
+ go_again = true;
+ char reason[MAXBUF];
+ while (go_again)
+ {
+ go_again = false;
+ for (user_hash::const_iterator u = clientlist.begin(); u != clientlist.end(); u++)
+ {
+ if (strcasecmp(u->second->server,ServerName))
+ {
+ snprintf(reason,MAXBUF,"%s %s",ServerName,u->second->server);
+ kill_link(u->second,reason);
+ go_again = true;
+ break;
+ }
+ }
+ }
+}
+
+
+
void handle_squit(char **parameters, int pcnt, userrec *user)
{
// send out an squit across the mesh and then clear the server list (for local squit)
+ if (!pcnt)
+ {
+ WriteOpers("SQUIT command issued by %s",user->nick);
+ char buffer[MAXBUF];
+ snprintf(buffer,MAXBUF,"& %s",ServerName);
+ NetSendToAll(buffer);
+ DoSplitEveryone();
+ }
+ else
+ {
+ WriteServ(user->fd,"NOTICE :*** Remote SQUIT not supported yet.");
+ }
}
char islast(const char* s)
{
if (((command[x] < '0') || (command[x]> '9')) && (command[x] != '-'))
{
- if (strchr("@!\"$%^&*(){}[]_-=+;:'#~,.<>/?\\|`",command[x]))
+ if (!strchr("@!\"$%^&*(){}[]_-=+;:'#~,.<>/?\\|`",command[x]))
{
kill_link(user,"Protocol violation (3)");
return;
createcommand("TRACE",handle_trace,'o',0);
createcommand("WHOWAS",handle_whowas,0,1);
createcommand("CONNECT",handle_connect,'o',1);
- createcommand("SQUIT",handle_squit,'o',1);
+ createcommand("SQUIT",handle_squit,'o',0);
createcommand("MODULES",handle_modules,'o',0);
createcommand("LINKS",handle_links,0,0);
createcommand("MAP",handle_map,0,0);
}
}
+long authcookie;
+
void process_restricted_commands(char token,char* params,serverrec* source,serverrec* reply, char* udp_host,char* ipaddr,int port)
{
- long authcookie = rand()*rand();
char buffer[MAXBUF];
switch(token)
case 'Y':
nb_start = time(NULL);
WriteOpers("Server %s is starting netburst.",udp_host);
+ // now broadcast this new servers address out to all servers that are linked to us,
+ // except the newcomer. They'll all attempt to connect back to it.
+ authcookie = rand()*rand();
+ snprintf(buffer,MAXBUF,"~ %d",authcookie);
+ NetSendToAll(buffer);
break;
// ~
// Store authcookie
WriteOpers("Server %s has completed netburst. (%d secs)",udp_host,time(NULL)-nb_start);
handle_F(token,params,source,reply,udp_host);
nb_start = 0;
- // now broadcast this new servers address out to all servers that are linked to us,
- // except the newcomer. They'll all attempt to connect back to it.
- snprintf(buffer,MAXBUF,"~ %d",authcookie);
- source->SendPacket(buffer,udp_host);
// tell all the other servers to use this authcookie to connect back again
// got '+ test3.chatspike.net 7010 -2016508415' from test.chatspike.net
snprintf(buffer,MAXBUF,"+ %s %s %d %d",udp_host,ipaddr,port,authcookie);
char* params = udp_msg + 2;
char finalparam[1024];
strcpy(finalparam," :xxxx");
- if (strstr(params," :")) {
- strncpy(finalparam,strstr(params," :"),1024);
+ if (strstr(udp_msg," :")) {
+ strncpy(finalparam,strstr(udp_msg," :"),1024);
}
if (token == '-') {
char* cookie = strtok(params," ");
if (!strcasecmp(me[j]->connectors[k].GetServerName().c_str(),udp_host))
{
me[j]->connectors[k].SetServerName(servername);
+ me[j]->connectors[k].SetDescription(serverdesc);
+ me[j]->connectors[k].SetState(STATE_CONNECTED);
NetSendMyRoutingTable();
return;
}
if (!strcasecmp(serv->connectors[j].GetServerName().c_str(),udp_host))
{
serv->connectors[j].SetServerName(servername);
+ serv->connectors[j].SetDescription(serverdesc);
serv->connectors[j].SetServerPort(atoi(myport));
}
}
// send a 'diminutive' server message back...
snprintf(response,10240,"s %s %s :%s",ServerName,Link_SendPass,ServerDesc);
serv->SendPacket(response,servername);
+
+ for (int t = 0; t < serv->connectors.size(); t++)
+ {
+ if (!strcasecmp(serv->connectors[t].GetServerName().c_str(),servername))
+ {
+ serv->connectors[t].SetState(STATE_CONNECTED);
+ }
+ }
+
return;
}
}
// to an 'S' command. If we didn't recently send an 'S' to this server, theyre trying to spoof
// a connect, so put out an oper alert!
-
-
-
// for now, just accept all, we'll fix that later.
WriteOpers("%s accepted our link credentials ",servername);
// at this point we must begin key exchange and insert this
// server into our 'active' table.
for (int j = 0; j < 32; j++)
- {
+ {
if (me[j] != NULL)
{
for (int k = 0; k < me[j]->connectors.size(); k++)
if (!strcasecmp(me[j]->connectors[k].GetServerName().c_str(),udp_host))
{
char buffer[MAXBUF];
+ me[j]->connectors[k].SetDescription(serverdesc);
+ me[j]->connectors[k].SetState(STATE_CONNECTED);
sprintf(buffer,"X 0");
serv->SendPacket(buffer,udp_host);
DoSync(me[j],udp_host);
log(DEBUG,"Servers are: '%s' '%s'",udp_host,me[j]->connectors[x].GetServerName().c_str());
if (!strcasecmp(me[j]->connectors[x].GetServerName().c_str(),udp_host))
{
- log(DEBUG,"match! process restricted stuff here");
- // found a valid ircd_connector.
- // TODO: Fix this so it only lets servers in that are in the
- // STATE_CONNECTED state!!!
- process_restricted_commands(token,params,me[j],serv,udp_host,me[j]->connectors[x].GetServerIP(),me[j]->connectors[x].GetServerPort());
- return;
+ if (me[j]->connectors[x].GetState() == STATE_CONNECTED)
+ {
+ // found a valid ircd_connector.
+ process_restricted_commands(token,params,me[j],serv,udp_host,me[j]->connectors[x].GetServerIP(),me[j]->connectors[x].GetServerPort());
+ return;
+ }
}
}
}
/* main loop, this never returns */
for (;;)
{
+#ifdef _POSIX_PRIORITY_SCHEDULING
+ sched_yield();
+#endif
fd_set sfd;
timeval tval;
// *FIX* Instead of closing sockets in kill_link when they receive the ERROR :blah line, we should queue
// them in a list, then reap the list every second or so.
- if (reap_counter>2500)
+ if (reap_counter>300)
{
if (fd_reap.size() > 0)
{
//if (selectResult2 > 0)
for (user_hash::iterator count2a = xcount; count2a != endingiter; count2a++)
{
+
+#ifdef _POSIX_PRIORITY_SCHEDULING
+ sched_yield();
+#endif
+
result = EAGAIN;
if ((count2a->second->fd != -1) && (FD_ISSET (count2a->second->fd, &sfd)))
{
if (result)
{
- log(DEBUG,"Read %d characters from socket",result);
+ if (result > 0)
+ log(DEBUG,"Read %d characters from socket",result);
userrec* current = count2a->second;
int currfd = current->fd;
char* l = strtok(data,"\n");