core/modulemanager.lua

changeset 592
c6e2c727d0cc
parent 584
eb0cea29c8d7
parent 591
980ded4c60ef
child 608
3758af511ce8
equal deleted inserted replaced
588:e743cb742ca6 592:c6e2c727d0cc
44 44
45 local api = {}; -- Module API container 45 local api = {}; -- Module API container
46 46
47 local modulemap = { ["*"] = {} }; 47 local modulemap = { ["*"] = {} };
48 48
49 local m_handler_info = multitable_new(); 49 local stanza_handlers = multitable_new();
50 local m_stanza_handlers = multitable_new();
51 local handler_info = {}; 50 local handler_info = {};
52 local stanza_handlers = {};
53 51
54 local modulehelpers = setmetatable({}, { __index = _G }); 52 local modulehelpers = setmetatable({}, { __index = _G });
55 53
56 -- Load modules when a host is activated 54 -- Load modules when a host is activated
57 function load_modules_for_host(host) 55 function load_modules_for_host(host)
70 return nil, "insufficient-parameters"; 68 return nil, "insufficient-parameters";
71 end 69 end
72 70
73 if not modulemap[host] then 71 if not modulemap[host] then
74 modulemap[host] = {}; 72 modulemap[host] = {};
75 stanza_handlers[host] = {};
76 elseif modulemap[host][module_name] then 73 elseif modulemap[host][module_name] then
77 log("warn", "%s is already loaded for %s, so not loading again", module_name, host); 74 log("warn", "%s is already loaded for %s, so not loading again", module_name, host);
78 return nil, "module-already-loaded"; 75 return nil, "module-already-loaded";
79 elseif modulemap["*"][module_name] then 76 elseif modulemap["*"][module_name] then
80 return nil, "global-module-already-loaded"; 77 return nil, "global-module-already-loaded";
121 end 118 end
122 end 119 end
123 120
124 end 121 end
125 122
126 function _handle_stanza(host, origin, stanza)
127 local name, xmlns, origin_type = stanza.name, stanza.attr.xmlns, origin.type;
128
129 local handlers = stanza_handlers[host];
130 if not handlers then
131 log("warn", "No handlers for %s", host);
132 return false;
133 end
134
135 if name == "iq" and xmlns == "jabber:client" and handlers[origin_type] then
136 local child = stanza.tags[1];
137 if child then
138 local xmlns = child.attr.xmlns or xmlns;
139 log("debug", "Stanza of type %s from %s has xmlns: %s", name, origin_type, xmlns);
140 local handler = handlers[origin_type][name] and handlers[origin_type][name][xmlns];
141 if handler then
142 log("debug", "Passing stanza to mod_%s", handler_info[handler].name);
143 return handler(origin, stanza) or true;
144 end
145 end
146 elseif handlers[origin_type] then
147 local handler = handlers[origin_type][name];
148 if handler then
149 handler = handler[xmlns];
150 if handler then
151 log("debug", "Passing stanza to mod_%s", handler_info[handler].name);
152 return handler(origin, stanza) or true;
153 end
154 end
155 end
156 log("debug", "Stanza unhandled by any modules, xmlns: %s", stanza.attr.xmlns);
157 return false; -- we didn't handle it
158 end
159 function handle_stanza(host, origin, stanza) 123 function handle_stanza(host, origin, stanza)
160 local name, xmlns, origin_type = stanza.name, stanza.attr.xmlns, origin.type; 124 local name, xmlns, origin_type = stanza.name, stanza.attr.xmlns, origin.type;
161 if name == "iq" and xmlns == "jabber:client" then 125 if name == "iq" and xmlns == "jabber:client" then
162 xmlns = stanza.tags[1].attr.xmlns; 126 xmlns = stanza.tags[1].attr.xmlns;
163 log("debug", "Stanza of type %s from %s has xmlns: %s", name, origin_type, xmlns); 127 log("debug", "Stanza of type %s from %s has xmlns: %s", name, origin_type, xmlns);
164 end 128 end
165 local handlers = m_stanza_handlers:get(host, origin_type, name, xmlns); 129 local handlers = stanza_handlers:get(host, origin_type, name, xmlns);
166 if handlers then 130 if handlers then
167 log("debug", "Passing stanza to mod_%s", handler_info[handlers[1]].name); 131 log("debug", "Passing stanza to mod_%s", handler_info[handlers[1]].name);
168 (handlers[1])(origin, stanza); 132 (handlers[1])(origin, stanza);
169 return true; 133 return true;
170 else 134 else
183 -- Returns the host that the current module is serving 147 -- Returns the host that the current module is serving
184 function api:get_host() 148 function api:get_host()
185 return self.host; 149 return self.host;
186 end 150 end
187 151
188 152 local function _add_handler(module, origin_type, tag, xmlns, handler)
189 local function __add_iq_handler(module, origin_type, xmlns, handler) 153 local handlers = stanza_handlers:get(module.host, origin_type, tag, xmlns);
190 local handlers = stanza_handlers[module.host]; 154 local msg = (tag == "iq") and "namespace" or "payload namespace";
191 handlers[origin_type] = handlers[origin_type] or {}; 155 if not handlers then
192 handlers[origin_type].iq = handlers[origin_type].iq or {}; 156 stanza_handlers:add(module.host, origin_type, tag, xmlns, handler);
193 if not handlers[origin_type].iq[xmlns] then
194 handlers[origin_type].iq[xmlns]= handler;
195 handler_info[handler] = module; 157 handler_info[handler] = module;
196 module:log("debug", "I now handle tag 'iq' [%s] with payload namespace '%s'", origin_type, xmlns); 158 module:log("debug", "I now handle tag '%s' [%s] with %s '%s'", tag, origin_type, msg, xmlns);
197 else 159 else
198 module:log("warn", "I wanted to handle tag 'iq' [%s] with payload namespace '%s' but mod_%s already handles that", origin_type, xmlns, handler_info[handlers[origin_type].iq[xmlns]].name); 160 module:log("warn", "I wanted to handle tag '%s' [%s] with %s '%s' but mod_%s already handles that", tag, origin_type, msg, xmlns, handler_info[handlers[1]].module.name);
199 end
200 end
201 local function _add_iq_handler(module, origin_type, xmlns, handler)
202 local handlers = m_stanza_handlers:get(module.host, origin_type, "iq", xmlns);
203 if not handlers then
204 m_stanza_handlers:add(module.host, origin_type, "iq", xmlns, handler);
205 handler_info[handler] = module;
206 module:log("debug", "I now handle tag 'iq' [%s] with payload namespace '%s'", origin_type, xmlns);
207 else
208 module:log("warn", "I wanted to handle tag 'iq' [%s] with payload namespace '%s' but mod_%s already handles that", origin_type, xmlns, handler_info[handlers[1]].name);
209 end 161 end
210 end 162 end
211 163
212 function api:add_iq_handler(origin_type, xmlns, handler) 164 function api:add_handler(origin_type, tag, xmlns, handler)
213 if not (origin_type and handler and xmlns) then return false; end 165 if not (origin_type and tag and xmlns and handler) then return false; end
214 if type(origin_type) == "table" then 166 if type(origin_type) == "table" then
215 for _, origin_type in ipairs(origin_type) do 167 for _, origin_type in ipairs(origin_type) do
216 _add_iq_handler(self, origin_type, xmlns, handler); 168 _add_handler(self, origin_type, tag, xmlns, handler);
217 end 169 end
218 return; 170 else
171 _add_handler(self, origin_type, tag, xmlns, handler);
219 end 172 end
220 _add_iq_handler(self, origin_type, xmlns, handler); 173 end
174 function api:add_iq_handler(origin_type, xmlns, handler)
175 self:add_handler(origin_type, "iq", xmlns, handler);
221 end 176 end
222 177
223 function api:add_feature(xmlns) 178 function api:add_feature(xmlns)
224 addDiscoInfoHandler(self.host, function(reply, to, from, node) 179 addDiscoInfoHandler(self.host, function(reply, to, from, node)
225 if #node == 0 then 180 if #node == 0 then
229 end); 184 end);
230 end 185 end
231 186
232 function api:add_event_hook (...) return eventmanager.add_event_hook(...); end 187 function api:add_event_hook (...) return eventmanager.add_event_hook(...); end
233 188
234 local function __add_handler(module, origin_type, tag, xmlns, handler)
235 local handlers = stanza_handlers[module.host];
236 handlers[origin_type] = handlers[origin_type] or {};
237 if not handlers[origin_type][tag] then
238 handlers[origin_type][tag] = handlers[origin_type][tag] or {};
239 handlers[origin_type][tag][xmlns]= handler;
240 handler_info[handler] = module;
241 module:log("debug", "I now handle tag '%s' [%s] with xmlns '%s'", tag, origin_type, xmlns);
242 elseif handler_info[handlers[origin_type][tag]] then
243 log("warning", "I wanted to handle tag '%s' [%s] but mod_%s already handles that", tag, origin_type, handler_info[handlers[origin_type][tag]].module.name);
244 end
245 end
246 local function _add_handler(module, origin_type, tag, xmlns, handler)
247 local handlers = m_stanza_handlers:get(module.host, origin_type, tag, xmlns);
248 if not handlers then
249 m_stanza_handlers:add(module.host, origin_type, tag, xmlns, handler);
250 handler_info[handler] = module;
251 module:log("debug", "I now handle tag '%s' [%s] with xmlns '%s'", tag, origin_type, xmlns);
252 else
253 module:log("warning", "I wanted to handle tag '%s' [%s] but mod_%s already handles that", tag, origin_type, handler_info[handlers[1]].module.name);
254 end
255 end
256
257 function api:add_handler(origin_type, tag, xmlns, handler)
258 if not (origin_type and tag and xmlns and handler) then return false; end
259 if type(origin_type) == "table" then
260 for _, origin_type in ipairs(origin_type) do
261 _add_handler(self, origin_type, tag, xmlns, handler);
262 end
263 return;
264 end
265 _add_handler(self, origin_type, tag, xmlns, handler);
266 end
267
268 -------------------------------------------------------------------- 189 --------------------------------------------------------------------
269 190
270 return _M; 191 return _M;

mercurial