X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fmodules%2Fm_spanningtree.cpp;h=fa22f80a1555bd523e0328078845a33f21e23990;hb=8b126657e79754e1d843da6c48d770937b589dab;hp=adc4a2a3807fc914ebb66d69370bde4cf844ef08;hpb=2b84d86113a183d56fd2471bf72ce6068bb969cb;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/modules/m_spanningtree.cpp b/src/modules/m_spanningtree.cpp index adc4a2a38..fa22f80a1 100644 --- a/src/modules/m_spanningtree.cpp +++ b/src/modules/m_spanningtree.cpp @@ -45,7 +45,10 @@ using namespace std; enum ServerState { LISTENER, CONNECTING, WAIT_AUTH_1, WAIT_AUTH_2, CONNECTED }; typedef nspace::hash_map, irc::StrHashComp> user_hash; +typedef nspace::hash_map, irc::StrHashComp> chan_hash; + extern user_hash clientlist; +extern chan_hash chanlist; class TreeServer; class TreeSocket; @@ -219,6 +222,11 @@ TreeServer* RouteEnumerate(TreeServer* Current, std::string ServerName) TreeServer* BestRouteTo(std::string ServerName) { log(DEBUG,"Finding best route to %s",ServerName.c_str()); + if (ServerName.c_str() == TreeRoot->GetName()) + { + log(DEBUG,"Cant route to myself!!!"); + return NULL; + } // first, find the server by recursively walking the tree TreeServer* Found = RouteEnumerate(TreeRoot,ServerName); // did we find it? If not, they did something wrong, abort. @@ -429,6 +437,53 @@ class TreeSocket : public InspSocket } } + bool ForceMode(std::string source, std::deque params) + { + userrec* who = new userrec; + who->fd = FD_MAGIC_NUMBER; + if (params.size() < 2) + return true; + char* modelist[255]; + for (unsigned int q = 0; q < params.size(); q++) + { + modelist[q] = (char*)params[q].c_str(); + } + Srv->SendMode(modelist,params.size(),who); + DoOneToAllButSender(source,"FMODE",params,source); + delete who; + return true; + } + + bool ForceTopic(std::string source, std::deque params) + { + // FTOPIC %s %lu %s :%s + if (params.size() != 4) + return true; + std::string channel = params[0]; + time_t ts = atoi(params[1].c_str()); + std::string setby = params[2]; + std::string topic = params[3]; + + chanrec* c = Srv->FindChannel(channel); + if (c) + { + if ((ts >= c->topicset) || (!*c->topic)) + { + strlcpy(c->topic,topic.c_str(),MAXTOPIC); + strlcpy(c->setby,setby.c_str(),NICKMAX); + c->topicset = ts; + WriteChannelWithServ((char*)source.c_str(), c, "TOPIC %s :%s", c->name, c->topic); + } + + } + + // all done, send it on its way + params[3] = ":" + params[3]; + DoOneToAllButSender(source,"FTOPIC",params,source); + + return true; + } + bool ForceJoin(std::string source, std::deque params) { if (params.size() < 1) @@ -506,10 +561,11 @@ class TreeSocket : public InspSocket if (iter != clientlist.end()) { // nick collision - log(DEBUG,"Nick collision on %s!%s@%s",tempnick,ident.c_str(),host.c_str()); + log(DEBUG,"Nick collision on %s!%s@%s: %lu %lu",tempnick,ident.c_str(),host.c_str(),(unsigned long)age,(unsigned long)iter->second->age); + this->WriteLine(":"+Srv->GetServerName()+" KILL "+tempnick+" :Nickname collision"); return true; } - + clientlist[tempnick] = new userrec(); clientlist[tempnick]->fd = FD_MAGIC_NUMBER; strlcpy(clientlist[tempnick]->nick, tempnick,NICKMAX); @@ -526,10 +582,31 @@ class TreeSocket : public InspSocket clientlist[tempnick]->chans[i].channel = NULL; clientlist[tempnick]->chans[i].uc_modes = 0; } + params[7] = ":" + params[7]; DoOneToAllButSender(source,"NICK",params,source); return true; } + void SendChannelModes(TreeServer* Current) + { + char data[MAXBUF]; + for (chan_hash::iterator c = chanlist.begin(); c != chanlist.end(); c++) + { + snprintf(data,MAXBUF,":%s FMODE %s +%s",Srv->GetServerName().c_str(),c->second->name,chanmodes(c->second)); + this->WriteLine(data); + if (*c->second->topic) + { + snprintf(data,MAXBUF,":%s FTOPIC %s %lu %s :%s",Srv->GetServerName().c_str(),c->second->name,(unsigned long)c->second->topicset,c->second->setby,c->second->topic); + this->WriteLine(data); + } + for (BanList::iterator b = c->second->bans.begin(); b != c->second->bans.end(); b++) + { + snprintf(data,MAXBUF,":%s FMODE %s +b %s",Srv->GetServerName().c_str(),c->second->name,b->data); + this->WriteLine(data); + } + } + } + // send all users and their channels void SendUsers(TreeServer* Current) { @@ -560,6 +637,7 @@ class TreeSocket : public InspSocket // Send users and their channels this->SendUsers(s); // TODO: Send everything else (channel modes etc) + this->SendChannelModes(s); this->WriteLine("ENDBURST"); } @@ -628,6 +706,41 @@ class TreeSocket : public InspSocket return true; } + bool RemoteRehash(std::string prefix, std::deque params) + { + if (params.size() < 1) + return true; + std::string servermask = params[0]; + if (Srv->MatchText(Srv->GetServerName(),servermask)) + { + Srv->RehashServer(); + } + DoOneToAllButSender(prefix,"REHASH",params,prefix); + return; + } + + bool RemoteKill(std::string prefix, std::deque params) + { + if (params.size() != 2) + return true; + std::string nick = params[0]; + std::string reason = params[1]; + userrec* u = Srv->FindNick(prefix); + userrec* who = Srv->FindNick(nick); + if (who) + { + std::string sourceserv = prefix; + if (u) + { + sourceserv = u->server; + } + params[1] = ":" + params[1]; + DoOneToAllButSender(prefix,"KILL",params,sourceserv); + Srv->QuitUser(who,reason); + } + return true; + } + bool RemoteServer(std::string prefix, std::deque params) { if (params.size() < 4) @@ -682,6 +795,7 @@ class TreeSocket : public InspSocket // node. TreeServer* Node = new TreeServer(servername,description,TreeRoot,this); TreeRoot->AddChild(Node); + params[3] = ":" + params[3]; DoOneToAllButSender(TreeRoot->GetName(),"SERVER",params,servername); this->DoBurst(Node); return true; @@ -733,30 +847,39 @@ class TreeSocket : public InspSocket while (!s.eof()) { s >> param; - if ((param.c_str()[0] == ':') && (item)) + if ((param != "") && (param != "\n")) { - char* str = (char*)param.c_str(); - str++; - param = str; - std::string append; - while (!s.eof()) + if ((param.c_str()[0] == ':') && (item)) { - append = ""; - s >> append; - if (append != "") + char* str = (char*)param.c_str(); + str++; + param = str; + std::string append; + while (!s.eof()) { - param = param + " " + append; + append = ""; + s >> append; + if (append != "") + { + param = param + " " + append; + } } } + item++; + n.push_back(param); } - item++; - n.push_back(param); } return n; } bool ProcessLine(std::string line) { + char* l = (char*)line.c_str(); + while ((strlen(l)) && (l[strlen(l)-1] == '\r') || (l[strlen(l)-1] == '\n')) + l[strlen(l)-1] = '\0'; + line = l; + if (line == "") + return true; Srv->Log(DEBUG,"inbound-line: '"+line+"'"); std::deque params = this->Split(line,true); std::string command = ""; @@ -860,6 +983,22 @@ class TreeSocket : public InspSocket { return this->OperType(prefix,params); } + else if (command == "FMODE") + { + return this->ForceMode(prefix,params); + } + else if (command == "KILL") + { + return this->RemoteKill(prefix,params); + } + else if (command == "FTOPIC") + { + return this->ForceTopic(prefix,params); + } + else if (command == "REHASH") + { + return this->RemoteRehash(prefix,params); + } else if (command == "SQUIT") { if (params.size() == 2) @@ -934,10 +1073,6 @@ class TreeSocket : public InspSocket TreeServer* s = FindServer(quitserver); if (s) { - std::deque params; - params.push_back(quitserver); - params.push_back(":Remote host closed the connection"); - DoOneToAllButSender(Srv->GetServerName(),"SQUIT",params,quitserver); Squit(s,"Remote host closed the connection"); } } @@ -1253,6 +1388,34 @@ class ModuleSpanningTree : public Module return 0; } + virtual void OnGetServerDescription(std::string servername,std::string &description) + { + TreeServer* s = FindServer(servername); + if (s) + { + description = s->GetDesc(); + } + } + + virtual void OnUserInvite(userrec* source,userrec* dest,chanrec* channel) + { + if (std::string(source->server) == Srv->GetServerName()) + { + std::deque params; + params.push_back(dest->nick); + params.push_back(channel->name); + DoOneToMany(source->nick,"INVITE",params); + } + } + + virtual void OnPostLocalTopicChange(userrec* user, chanrec* chan, std::string topic) + { + std::deque params; + params.push_back(chan->name); + params.push_back(":"+topic); + DoOneToMany(user->nick,"TOPIC",params); + } + virtual void OnUserNotice(userrec* user, void* dest, int target_type, std::string text) { if (target_type == TYPE_USER) @@ -1383,6 +1546,42 @@ class ModuleSpanningTree : public Module } } + virtual void OnUserKick(userrec* source, userrec* user, chanrec* chan, std::string reason) + { + if (std::string(source->server) == Srv->GetServerName()) + { + log(DEBUG,"**** User on %s KICKs: %s %s",source->server,source->nick,user->nick); + std::deque params; + params.push_back(chan->name); + params.push_back(user->nick); + params.push_back(":"+reason); + DoOneToMany(source->nick,"KICK",params); + } + } + + virtual void OnRemoteKill(userrec* source, userrec* dest, std::string reason) + { + std::deque params; + params.push_back(dest->nick); + params.push_back(":"+reason); + DoOneToMany(source->nick,"KILL",params); + } + + virtual void OnRehash(std::string parameter) + { + if (parameter != "") + { + std::deque params; + params.push_back(parameter); + DoOneToMany(Srv->GetServerName(),"REHASH",params); + // check for self + if (Srv->MatchText(Srv->GetServerName(),parameter)) + { + Srv->RehashServer(); + } + } + } + // note: the protocol does not allow direct umode +o except // via NICK with 8 params. sending OPERTYPE infers +o modechange // locally.