IQRouterImpl.java 7.24 KB
Newer Older
Matt Tucker's avatar
Matt Tucker committed
1 2 3 4 5
/**
 * $RCSfile$
 * $Revision$
 * $Date$
 *
Matt Tucker's avatar
Matt Tucker committed
6
 * Copyright (C) 2004 Jive Software. All rights reserved.
Matt Tucker's avatar
Matt Tucker committed
7
 *
Matt Tucker's avatar
Matt Tucker committed
8 9
 * This software is published under the terms of the GNU Public License (GPL),
 * a copy of which is included in this distribution.
Matt Tucker's avatar
Matt Tucker committed
10
 */
Matt Tucker's avatar
Matt Tucker committed
11

Matt Tucker's avatar
Matt Tucker committed
12 13 14 15 16
package org.jivesoftware.messenger.spi;

import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
Derek DeMoro's avatar
Derek DeMoro committed
17
import java.util.Map;
18 19 20 21 22 23
import org.jivesoftware.messenger.*;
import org.jivesoftware.messenger.auth.UnauthorizedException;
import org.jivesoftware.messenger.container.BasicModule;
import org.jivesoftware.messenger.handler.IQHandler;
import org.jivesoftware.util.LocaleUtils;
import org.jivesoftware.util.Log;
Matt Tucker's avatar
Matt Tucker committed
24 25 26 27
import org.xmpp.packet.IQ;
import org.xmpp.packet.JID;
import org.xmpp.packet.PacketError;
import org.dom4j.Element;
Matt Tucker's avatar
Matt Tucker committed
28 29 30 31 32 33 34 35

/**
 * Generic presence routing base class.
 *
 * @author Iain Shigeoka
 */
public class IQRouterImpl extends BasicModule implements IQRouter {

36 37
    private RoutingTable routingTable;
    private LinkedList iqHandlers = new LinkedList();
Derek DeMoro's avatar
Derek DeMoro committed
38 39
    private Map namespace2Handlers = new HashMap();
    private SessionManager sessionManager;
Matt Tucker's avatar
Matt Tucker committed
40 41 42 43 44 45 46 47 48 49 50 51

    /**
     * Creates a packet router.
     */
    public IQRouterImpl() {
        super("XMPP IQ Router");
    }

    public void route(IQ packet) {
        if (packet == null) {
            throw new NullPointerException();
        }
52
        Session session = sessionManager.getSession(packet.getFrom());
Matt Tucker's avatar
Matt Tucker committed
53 54
        if (session == null || session.getStatus() == Session.STATUS_AUTHENTICATED
                || (isLocalServer(packet.getTo())
Derek DeMoro's avatar
Derek DeMoro committed
55 56
                && ("jabber:iq:auth".equals(packet.getChildElement().getNamespaceURI())
                || "jabber:iq:register".equals(packet.getChildElement().getNamespaceURI())))
Matt Tucker's avatar
Matt Tucker committed
57 58 59 60
        ) {
            handle(packet);
        }
        else {
Derek DeMoro's avatar
Derek DeMoro committed
61 62
            packet.setTo(sessionManager.getSession(packet.getFrom()).getAddress());
            packet.setError(PacketError.Condition.not_authorized);
Matt Tucker's avatar
Matt Tucker committed
63
            try {
Derek DeMoro's avatar
Derek DeMoro committed
64
                sessionManager.getSession(packet.getFrom()).process(packet);
Matt Tucker's avatar
Matt Tucker committed
65 66 67 68 69 70 71
            }
            catch (UnauthorizedException ue) {
                Log.error(ue);
            }
        }
    }

Matt Tucker's avatar
Matt Tucker committed
72 73 74
    private boolean isLocalServer(JID recipientJID) {
        return recipientJID == null || recipientJID.getDomain() == null
                || "".equals(recipientJID.getDomain()) || recipientJID.getResource() == null
75
                || "".equals(recipientJID.getResource());
76
    }
Matt Tucker's avatar
Matt Tucker committed
77 78

    private void handle(IQ packet) {
Matt Tucker's avatar
Matt Tucker committed
79
        JID recipientJID = packet.getTo();
Matt Tucker's avatar
Matt Tucker committed
80 81 82
        try {
            if (isLocalServer(recipientJID)) {

Matt Tucker's avatar
Matt Tucker committed
83 84 85
                Element childElement = packet.getChildElement();
                String namespace = null;
                if (childElement != null) {
86
                    namespace = childElement.getNamespaceURI();
Matt Tucker's avatar
Matt Tucker committed
87
                }
Matt Tucker's avatar
Matt Tucker committed
88 89 90 91 92 93 94 95
                if (namespace == null) {
                    // Do nothing. We can't handle queries outside of a valid namespace
                    Log.warn("Unknown packet " + packet);
                }
                else {
                    IQHandler handler = getHandler(namespace);
                    if (handler == null) {
                        // Answer an error if JID is of the form <domain>
Matt Tucker's avatar
Matt Tucker committed
96 97
                        if (recipientJID.getNode() == null || "".equals(recipientJID.getNode())) {
                            packet.setError(PacketError.Condition.feature_not_implemented);
Matt Tucker's avatar
Matt Tucker committed
98 99
                        }
                        else {
100
                            // JID is of the form <node@domain>
Matt Tucker's avatar
Matt Tucker committed
101 102
                            try {
                                // Let a "service" handle this packet otherwise return an error
103
                                // Useful for MUC where node refers to a room and domain is the
Matt Tucker's avatar
Matt Tucker committed
104 105 106 107 108 109 110 111 112 113 114
                                // MUC service.
                                ChannelHandler route = routingTable.getRoute(recipientJID);
                                if (route instanceof BasicModule) {
                                    route.process(packet);
                                    return;
                                }
                            }
                            catch (NoSuchRouteException e) {
                                // do nothing
                            }
                            // Answer an error since the server can't handle packets sent to a node
Matt Tucker's avatar
Matt Tucker committed
115
                            packet.setError(PacketError.Condition.service_unavailable);
Matt Tucker's avatar
Matt Tucker committed
116
                        }
Derek DeMoro's avatar
Derek DeMoro committed
117
                        Session session = sessionManager.getSession(packet.getFrom());
Matt Tucker's avatar
Matt Tucker committed
118 119 120 121 122 123 124 125 126 127 128 129 130 131
                        if (session != null) {
                            session.getConnection().deliver(packet);
                        }
                        else {
                            Log.warn("Packet could not be delivered " + packet);
                        }
                    }
                    else {
                        handler.process(packet);
                    }
                }

            }
            else {
132
                // JID is of the form <node@domain/resource>
Matt Tucker's avatar
Matt Tucker committed
133 134 135 136 137 138
                ChannelHandler route = routingTable.getRoute(recipientJID);
                route.process(packet);
            }
        }
        catch (NoSuchRouteException e) {
            Log.info("Packet sent to unreachable address " + packet);
Derek DeMoro's avatar
Derek DeMoro committed
139
            Session session = sessionManager.getSession(packet.getFrom());
Matt Tucker's avatar
Matt Tucker committed
140 141
            if (session != null) {
                try {
Derek DeMoro's avatar
Derek DeMoro committed
142
                    packet.setError(PacketError.Condition.service_unavailable);
Matt Tucker's avatar
Matt Tucker committed
143 144 145 146 147 148 149 150 151 152
                    session.getConnection().deliver(packet);
                }
                catch (UnauthorizedException ex) {
                    Log.error(LocaleUtils.getLocalizedString("admin.error.routing"), e);
                }
            }
        }
        catch (Exception e) {
            Log.error(LocaleUtils.getLocalizedString("admin.error.routing"), e);
            try {
Derek DeMoro's avatar
Derek DeMoro committed
153
                Session session = sessionManager.getSession(packet.getFrom());
Matt Tucker's avatar
Matt Tucker committed
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
                if (session != null) {
                    Connection conn = session.getConnection();
                    if (conn != null) {
                        conn.close();
                    }
                }
            }
            catch (UnauthorizedException e1) {
                // do nothing
            }
        }
    }

    private IQHandler getHandler(String namespace) {
        IQHandler handler = null;

        handler = (IQHandler)namespace2Handlers.get(namespace);
        if (handler == null) {
            Iterator handlerIter = iqHandlers.iterator();
            while (handlerIter.hasNext() && handler == null) {
                IQHandler handlerCandidate = (IQHandler)handlerIter.next();
                IQHandlerInfo handlerInfo = handlerCandidate.getInfo();
                if (handlerInfo != null && namespace.equalsIgnoreCase(handlerInfo.getNamespace())) {
                    handler = handlerCandidate;
                }
            }
            if (handler != null) {
                namespace2Handlers.put(namespace, handler);
            }
        }
        return handler;
    }

187 188 189 190 191
    public void initialize(XMPPServer server) {
        super.initialize(server);
        routingTable = server.getRoutingTable();
        iqHandlers.addAll(server.getIQHandlers());
        sessionManager = server.getSessionManager();
Matt Tucker's avatar
Matt Tucker committed
192 193
    }
}