net.httpserver: Revert commit eccd3c87d717 which has since been fixed in a better way
[prosody.git] / plugins / mod_component.lua
index 7efb4f9c3e94c2c4076854445103ed2267f7b065..fda271ddab671ba44e5db4e715e8793ed8a6322c 100644 (file)
@@ -14,59 +14,87 @@ local hosts = _G.hosts;
 
 local t_concat = table.concat;
 
-local config = require "core.configmanager";
-local cm_register_component = require "core.componentmanager".register_component;
-local cm_deregister_component = require "core.componentmanager".deregister_component;
 local sha1 = require "util.hashes".sha1;
 local st = require "util.stanza";
 
 local log = module._log;
 
+local main_session, send;
+
+local function on_destroy(session, err)
+       if main_session == session then
+               main_session = nil;
+               send = nil;
+               session.on_destroy = nil;
+       end
+end
+
+local function handle_stanza(event)
+       local stanza = event.stanza;
+       if send then
+               stanza.attr.xmlns = nil;
+               send(stanza);
+       else
+               log("warn", "Stanza being handled by default component; bouncing error for: %s", stanza:top_tag());
+               if stanza.attr.type ~= "error" and stanza.attr.type ~= "result" then
+                       event.origin.send(st.error_reply(stanza, "wait", "service-unavailable", "Component unavailable"));
+               end
+       end
+       return true;
+end
+
+module:hook("iq/bare", handle_stanza, -1);
+module:hook("message/bare", handle_stanza, -1);
+module:hook("presence/bare", handle_stanza, -1);
+module:hook("iq/full", handle_stanza, -1);
+module:hook("message/full", handle_stanza, -1);
+module:hook("presence/full", handle_stanza, -1);
+module:hook("iq/host", handle_stanza, -1);
+module:hook("message/host", handle_stanza, -1);
+module:hook("presence/host", handle_stanza, -1);
+
 --- Handle authentication attempts by components
-function handle_component_auth(session, stanza)
-       log("info", "Handling component auth");
+function handle_component_auth(event)
+       local session, stanza = event.origin, event.stanza;
+       
+       if session.type ~= "component" then return; end
+       if main_session == session then return; end
+
        if (not session.host) or #stanza.tags > 0 then
-               (session.log or log)("warn", "Component handshake invalid");
+               (session.log or log)("warn", "Invalid component handshake for host: %s", session.host);
                session:close("not-authorized");
-               return;
+               return true;
        end
        
-       local secret = config.get(session.user, "core", "component_secret");
+       local secret = module:get_option("component_secret");
        if not secret then
-               (session.log or log)("warn", "Component attempted to identify as %s, but component_secret is not set", session.user);
+               (session.log or log)("warn", "Component attempted to identify as %s, but component_secret is not set", session.host);
                session:close("not-authorized");
-               return;
+               return true;
        end
        
        local supplied_token = t_concat(stanza);
        local calculated_token = sha1(session.streamid..secret, true);
        if supplied_token:lower() ~= calculated_token:lower() then
-               log("info", "Component for %s authentication failed", session.host);
+               log("info", "Component authentication failed for %s", session.host);
                session:close{ condition = "not-authorized", text = "Given token does not match calculated token" };
-               return;
+               return true;
        end
        
-       
-       -- Authenticated now
-       log("info", "Component authenticated: %s", session.host);
-       
        -- If component not already created for this host, create one now
-       if not hosts[session.host].connected then
-               local send = session.send;
-               session.component_session = cm_register_component(session.host, function (_, data) 
-                               if data.attr and data.attr.xmlns == "jabber:client" then
-                                       data.attr.xmlns = nil;
-                               end
-                               return send(data);
-                       end);
-               hosts[session.host].connected = true;
-               log("info", "Component successfully registered");
-       else
-               log("error", "Multiple components bound to the same address, first one wins (TODO: Implement stanza distribution)");
+       if not main_session then
+               send = session.send;
+               main_session = session;
+               session.on_destroy = on_destroy;
+               session.component_validate_from = module:get_option_boolean("validate_from_addresses") ~= false;
+               log("info", "Component successfully authenticated: %s", session.host);
+               session.send(st.stanza("handshake"));
+       else -- TODO: Implement stanza distribution
+               log("error", "Multiple components bound to the same address, first one wins: %s", session.host);
+               session:close{ condition = "conflict", text = "Component already connected" };
        end
        
-       -- Signal successful authentication
-       session.send(st.stanza("handshake"));
+       return true;
 end
 
-module:add_handler("component", "handshake", "jabber:component:accept", handle_component_auth);
+module:hook("stanza/jabber:component:accept:handshake", handle_component_auth);