]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_spanningtree/postcommand.cpp
Minor spelling errors in m_spanningtree.so
[user/henk/code/inspircd.git] / src / modules / m_spanningtree / postcommand.cpp
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  *   Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org>
5  *   Copyright (C) 2007 Craig Edwards <craigedwards@brainbox.cc>
6  *
7  * This file is part of InspIRCd.  InspIRCd is free software: you can
8  * redistribute it and/or modify it under the terms of the GNU General Public
9  * License as published by the Free Software Foundation, version 2.
10  *
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
14  * details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20
21 /* $ModDesc: Provides a spanning tree server link protocol */
22
23 #include "inspircd.h"
24 #include "socket.h"
25 #include "xline.h"
26
27 #include "main.h"
28 #include "utils.h"
29 #include "treeserver.h"
30 #include "treesocket.h"
31
32 /* $ModDep: m_spanningtree/main.h m_spanningtree/utils.h m_spanningtree/treeserver.h m_spanningtree/treesocket.h */
33
34 void ModuleSpanningTree::OnPostCommand(const std::string &command, const std::vector<std::string>& parameters, LocalUser *user, CmdResult result, const std::string &original_line)
35 {
36         if (result == CMD_SUCCESS)
37                 Utils->RouteCommand(NULL, command, parameters, user);
38 }
39
40 void SpanningTreeUtilities::RouteCommand(TreeServer* origin, const std::string &command, const parameterlist& parameters, User *user)
41 {
42         if (!ServerInstance->Parser->IsValidCommand(command, parameters.size(), user))
43                 return;
44
45         /* We know it's non-null because IsValidCommand returned true */
46         Command* thiscmd = ServerInstance->Parser->GetHandler(command);
47
48         RouteDescriptor routing = thiscmd->GetRouting(user, parameters);
49
50         std::string sent_cmd = command;
51         parameterlist params;
52
53         if (routing.type == ROUTE_TYPE_LOCALONLY)
54         {
55                 /* Broadcast when it's a core command with the default route descriptor and the source is a
56                  * remote user or a remote server
57                  */
58
59                 Version ver = thiscmd->creator->GetVersion();
60                 if ((!(ver.Flags & VF_CORE)) || (IS_LOCAL(user)) || (IS_SERVER(user) == ServerInstance->FakeClient))
61                         return;
62
63                 routing = ROUTE_BROADCAST;
64         }
65         else if (routing.type == ROUTE_TYPE_OPT_BCAST)
66         {
67                 params.push_back("*");
68                 params.push_back(command);
69                 sent_cmd = "ENCAP";
70         }
71         else if (routing.type == ROUTE_TYPE_OPT_UCAST)
72         {
73                 TreeServer* sdest = FindServer(routing.serverdest);
74                 if (!sdest)
75                 {
76                         ServerInstance->Logs->Log("m_spanningtree",DEFAULT,"Trying to route ENCAP to nonexistent server %s",
77                                 routing.serverdest.c_str());
78                         return;
79                 }
80                 params.push_back(sdest->GetID());
81                 params.push_back(command);
82                 sent_cmd = "ENCAP";
83         }
84         else
85         {
86                 Module* srcmodule = thiscmd->creator;
87                 Version ver = srcmodule->GetVersion();
88
89                 if (!(ver.Flags & (VF_COMMON | VF_CORE)) && srcmodule != Creator)
90                 {
91                         ServerInstance->Logs->Log("m_spanningtree",DEFAULT,"Routed command %s from non-VF_COMMON module %s",
92                                 command.c_str(), srcmodule->ModuleSourceFile.c_str());
93                         return;
94                 }
95         }
96
97         std::string output_text;
98         ServerInstance->Parser->TranslateUIDs(thiscmd->translation, parameters, output_text, true, thiscmd);
99
100         params.push_back(output_text);
101
102         if (routing.type == ROUTE_TYPE_MESSAGE)
103         {
104                 char pfx = 0;
105                 std::string dest = routing.serverdest;
106                 if (ServerInstance->Modes->FindPrefix(dest[0]))
107                 {
108                         pfx = dest[0];
109                         dest = dest.substr(1);
110                 }
111                 if (dest[0] == '#')
112                 {
113                         Channel* c = ServerInstance->FindChan(dest);
114                         if (!c)
115                                 return;
116                         TreeServerList list;
117                         // TODO OnBuildExemptList hook was here
118                         GetListOfServersForChannel(c,list,pfx, CUList());
119                         std::string data = ":" + user->uuid + " " + sent_cmd;
120                         for (unsigned int x = 0; x < params.size(); x++)
121                                 data += " " + params[x];
122                         for (TreeServerList::iterator i = list.begin(); i != list.end(); i++)
123                         {
124                                 TreeSocket* Sock = i->second->GetSocket();
125                                 if (origin && origin->GetSocket() == Sock)
126                                         continue;
127                                 if (Sock)
128                                         Sock->WriteLine(data);
129                         }
130                 }
131                 else if (dest[0] == '$')
132                 {
133                         if (origin)
134                                 DoOneToAllButSender(user->uuid, sent_cmd, params, origin->GetName());
135                         else
136                                 DoOneToMany(user->uuid, sent_cmd, params);
137                 }
138                 else
139                 {
140                         // user target?
141                         User* d = ServerInstance->FindNick(dest);
142                         if (!d)
143                                 return;
144                         TreeServer* tsd = BestRouteTo(d->server);
145                         if (tsd == origin)
146                                 // huh? no routing stuff around in a circle, please.
147                                 return;
148                         DoOneToOne(user->uuid, sent_cmd, params, d->server);
149                 }
150         }
151         else if (routing.type == ROUTE_TYPE_BROADCAST || routing.type == ROUTE_TYPE_OPT_BCAST)
152         {
153                 if (origin)
154                         DoOneToAllButSender(user->uuid, sent_cmd, params, origin->GetName());
155                 else
156                         DoOneToMany(user->uuid, sent_cmd, params);
157         }
158         else if (routing.type == ROUTE_TYPE_UNICAST || routing.type == ROUTE_TYPE_OPT_UCAST)
159         {
160                 if (origin && routing.serverdest == origin->GetName())
161                         return;
162                 DoOneToOne(user->uuid, sent_cmd, params, routing.serverdest);
163         }
164 }