]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_spanningtree/postcommand.cpp
PreCommand/PostCommand are local-only hooks
[user/henk/code/inspircd.git] / src / modules / m_spanningtree / postcommand.cpp
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  InspIRCd: (C) 2002-2010 InspIRCd Development Team
6  * See: http://wiki.inspircd.org/Credits
7  *
8  * This program is free but copyrighted software; see
9  *        the file COPYING for details.
10  *
11  * ---------------------------------------------------
12  */
13
14 /* $ModDesc: Provides a spanning tree server link protocol */
15
16 #include "inspircd.h"
17 #include "socket.h"
18 #include "xline.h"
19
20 #include "main.h"
21 #include "utils.h"
22 #include "treeserver.h"
23 #include "treesocket.h"
24
25 /* $ModDep: m_spanningtree/main.h m_spanningtree/utils.h m_spanningtree/treeserver.h m_spanningtree/treesocket.h */
26
27 void ModuleSpanningTree::OnPostCommand(const std::string &command, const std::vector<std::string>& parameters, LocalUser *user, CmdResult result, const std::string &original_line)
28 {
29         if (result == CMD_SUCCESS)
30                 Utils->RouteCommand(NULL, command, parameters, user);
31 }
32
33 void SpanningTreeUtilities::RouteCommand(TreeServer* origin, const std::string &command, const parameterlist& parameters, User *user)
34 {
35         if (!ServerInstance->IsValidModuleCommand(command, parameters.size(), user))
36                 return;
37
38         /* We know it's non-null because IsValidModuleCommand returned true */
39         Command* thiscmd = ServerInstance->Parser->GetHandler(command);
40
41         RouteDescriptor routing = thiscmd->GetRouting(user, parameters);
42
43         std::string sent_cmd = command;
44         parameterlist params;
45
46         if (routing.type == ROUTE_TYPE_LOCALONLY)
47         {
48                 Module* srcmodule = thiscmd->creator;
49                 Version ver = srcmodule->GetVersion();
50
51                 if ((ver.Flags & VF_CORE) && !IS_LOCAL(user))
52                         routing = ROUTE_BROADCAST;
53                 else
54                         return;
55                 if (IS_SERVER(user) && user != ServerInstance->FakeClient)
56                         return;
57         }
58         else if (routing.type == ROUTE_TYPE_OPT_BCAST)
59         {
60                 params.push_back("*");
61                 params.push_back(command);
62                 sent_cmd = "ENCAP";
63         }
64         else if (routing.type == ROUTE_TYPE_OPT_UCAST)
65         {
66                 TreeServer* sdest = FindServer(routing.serverdest);
67                 if (!sdest)
68                 {
69                         ServerInstance->Logs->Log("m_spanningtree",ERROR,"Trying to route ENCAP to nonexistant server %s",
70                                 routing.serverdest.c_str());
71                         return;
72                 }
73                 params.push_back(sdest->GetID());
74                 params.push_back(command);
75                 sent_cmd = "ENCAP";
76         }
77         else
78         {
79                 Module* srcmodule = thiscmd->creator;
80                 Version ver = srcmodule->GetVersion();
81
82                 if (!(ver.Flags & (VF_COMMON | VF_CORE)))
83                 {
84                         ServerInstance->Logs->Log("m_spanningtree",ERROR,"Routed command %s from non-VF_COMMON module %s",
85                                 command.c_str(), srcmodule->ModuleSourceFile.c_str());
86                         return;
87                 }
88         }
89
90         std::string output_text;
91         ServerInstance->Parser->TranslateUIDs(thiscmd->translation, parameters, output_text, true, thiscmd);
92
93         params.push_back(output_text);
94
95         if (routing.type == ROUTE_TYPE_MESSAGE)
96         {
97                 char pfx = 0;
98                 std::string dest = routing.serverdest;
99                 if (ServerInstance->Modes->FindPrefix(dest[0]))
100                 {
101                         pfx = dest[0];
102                         dest = dest.substr(1);
103                 }
104                 if (dest[0] == '#')
105                 {
106                         Channel* c = ServerInstance->FindChan(dest);
107                         if (!c)
108                                 return;
109                         TreeServerList list;
110                         // TODO OnBuildExemptList hook was here
111                         GetListOfServersForChannel(c,list,pfx, CUList());
112                         std::string data = ":" + user->uuid + " " + sent_cmd;
113                         for (unsigned int x = 0; x < params.size(); x++)
114                                 data += " " + params[x];
115                         for (TreeServerList::iterator i = list.begin(); i != list.end(); i++)
116                         {
117                                 TreeSocket* Sock = i->second->GetSocket();
118                                 if (origin && origin->GetSocket() == Sock)
119                                         continue;
120                                 if (Sock)
121                                         Sock->WriteLine(data);
122                         }
123                 }
124                 else if (dest[0] == '$')
125                 {
126                         if (origin)
127                                 DoOneToAllButSender(user->uuid, sent_cmd, params, origin->GetName());
128                         else
129                                 DoOneToMany(user->uuid, sent_cmd, params);
130                 }
131                 else
132                 {
133                         // user target?
134                         User* d = ServerInstance->FindNick(dest);
135                         if (!d)
136                                 return;
137                         TreeServer* tsd = BestRouteTo(d->server);
138                         if (tsd == origin)
139                                 // huh? no routing stuff around in a circle, please.
140                                 return;
141                         DoOneToOne(user->uuid, sent_cmd, params, d->server);
142                 }
143         }
144         else if (routing.type == ROUTE_TYPE_BROADCAST || routing.type == ROUTE_TYPE_OPT_BCAST)
145         {
146                 if (origin)
147                         DoOneToAllButSender(user->uuid, sent_cmd, params, origin->GetName());
148                 else
149                         DoOneToMany(user->uuid, sent_cmd, params);
150         }
151         else if (routing.type == ROUTE_TYPE_UNICAST || routing.type == ROUTE_TYPE_OPT_UCAST)
152         {
153                 if (origin && routing.serverdest == origin->GetName())
154                         return;
155                 DoOneToOne(user->uuid, sent_cmd, params, routing.serverdest);
156         }
157 }