RoutingTable.java 18.3 KB
Newer Older
1 2 3 4 5
/**
 * $RCSfile: RoutingTable.java,v $
 * $Revision: 3138 $
 * $Date: 2005-12-01 02:13:26 -0300 (Thu, 01 Dec 2005) $
 *
6
 * Copyright (C) 2004-2008 Jive Software. All rights reserved.
7
 *
8 9 10 11 12 13 14 15 16 17 18
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
19 20
 */

21
package org.jivesoftware.openfire;
22

Gaston Dombiak's avatar
Gaston Dombiak committed
23
import org.jivesoftware.openfire.session.ClientSession;
24 25 26
import org.jivesoftware.openfire.session.LocalClientSession;
import org.jivesoftware.openfire.session.LocalOutgoingServerSession;
import org.jivesoftware.openfire.session.OutgoingServerSession;
27
import org.xmpp.packet.JID;
28
import org.xmpp.packet.Message;
Gaston Dombiak's avatar
Gaston Dombiak committed
29
import org.xmpp.packet.Packet;
30

31
import java.util.Collection;
32
import java.util.List;
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89

/**
 * <p>Maintains server-wide knowledge of routes to any node.</p>
 * <p>Routes are only concerned with node addresses. Destinations are
 * packet handlers (typically of the three following types):</p>
 * <ul>
 * <li>Session - A local or remote session belonging to the server's domain.
 * Remote sessions may be possible in clustered servers.</li>
 * <li>Chatbot - A chatbot which will have various packets routed to it.</li>
 * <li>Transport - A transport for foreign server domains. Foreign domains
 * may be hosted in the same server JVM (e.g. virutal hosted servers, groupchat
 * servers, etc).</li>
 * </ul>
 * <p>In almost all cases, the caller should not be concerned with what
 * handler is associated with a given node. Simply obtain the packet handler
 * and deliver the packet to the node, leaving the details up to the handler.</p>
 * <p>Routes are matched using the stringprep rules given in the XMPP specification.
 * Wildcard routes for a particular name or resource is indicated by a null. E.g.
 * routing to any address at server.com should set the name to null, the host to
 * 'server.com' and the resource to null. A route to the best resource for user@server.com
 * should indicate that route with a null resource component of the XMPPAddress. Session
 * managers should add a route for both the generic user@server.com as well as
 * user@server.com/resource routes (knowing that one is an alias for the other
 * is the responsibility of the session or session manager).</p>
 * <p>In order to accomodate broadcasts, you can also do partial matches by querying
 * all 'child' nodes of a particular node. The routing table contains a forest of
 * node trees. The node tree is arranged in the following heirarchy:</p>
 * <ul>
 * <li>forest - All nodes in the routing table. An XMPP address with host, name, and resource set
 * to null will match all nodes stored in the routing table. Use with extreme caution as the
 * routing table may contain hundreds of thousands of entries and iterators will be produced using
 * a copy of the table for iteration safety.</li>
 * <li>domain root - The root of each node tree is the server domain. An XMPP address
 * containing just a host entry, and null in the name and resource fields will match
 * the domain root. The children will contain both the root entry (if there is one) and
 * all entries with the same host name.</li>
 * <li>user branches - The root's immediate children are the user branches. An
 * XMPP address containing just a hast and name entry, and null in the resource field
 * will match a particular user branch. The children will contain both the user branch
 * (if there is one) and all entries with the same host and name, ignoring resources.
 * This is the most useful for conducting user broadcasts. Note that if the user
 * branch is located on a foreign server, the only route returned will the server-to-server
 * transport.</li>
 * <li>resource leaves - Each user branch can have zero or more resource leaves. A partial
 * match on an XMPP address with values in host, name, and resource fields will be equivalent
 * to the exact match calls since only one route can ever be registered for a particular. See
 * getBestRoute() if you'd like to search for both the resource leaf route, as well as a valid user
 * branch for that node if no leaf exists.</li>
 * </ul>
 * <p>Note: it is important that any component or action affecting routes
 * update the routing table immediately.</p>
 *
 * @author Iain Shigeoka
 */
public interface RoutingTable {

    /**
Gaston Dombiak's avatar
Gaston Dombiak committed
90 91 92 93 94 95 96
     * Adds a route to the routing table for the specified outoing server session. When running
     * inside of a cluster this message <tt>must</tt> be sent from the cluster node that is
     * actually holding the physical connectoin to the remote server.
     *
     * @param route the address associated to the route.
     * @param destination the outgoing server session.
     */
97
    void addServerRoute(JID route, LocalOutgoingServerSession destination);
Gaston Dombiak's avatar
Gaston Dombiak committed
98 99

    /**
100 101 102 103 104 105
     * Adds a route to the routing table for the specified internal or external component. <p>
     *
     * When running inside of a cluster this message <tt>must</tt> be sent from the cluster
     * node that is actually hosting the component. The component may be available in all
     * or some of cluster nodes. The routing table will keep track of all nodes hosting
     * the component. 
Gaston Dombiak's avatar
Gaston Dombiak committed
106 107 108
     *
     * @param route the address associated to the route.
     * @param destination the component.
109
     */
Gaston Dombiak's avatar
Gaston Dombiak committed
110
    void addComponentRoute(JID route, RoutableChannelHandler destination);
111 112

    /**
Gaston Dombiak's avatar
Gaston Dombiak committed
113 114 115 116 117
     * Adds a route to the routing table for the specified client session. The client
     * session will be added as soon as the user has finished authenticating with the server.
     * Moreover, when the user becomes available or unavailable then the routing table will
     * get updated again. When running inside of a cluster this message <tt>must</tt> be sent
     * from the cluster node that is actually holding the client session.
118
     *
Gaston Dombiak's avatar
Gaston Dombiak committed
119 120
     * @param route the address associated to the route.
     * @param destination the client session.
121
     * @return true if route was added to the table or false if already present.
122
     */
123
    boolean addClientRoute(JID route, LocalClientSession destination);
124 125

    /**
Gaston Dombiak's avatar
Gaston Dombiak committed
126 127
     * Routes a packet to the specified address. The packet destination can be a
     * user on the local server, a component, or a foreign server.<p>
128
     *
Gaston Dombiak's avatar
Gaston Dombiak committed
129 130 131
     * When routing a packet to a remote server then a new outgoing connection
     * will be created to the remote server if none was found and the packet
     * will be delivered. If an existing outgoing connection already exists then
guus's avatar
guus committed
132
     * it will be used for delivering the packet. Moreover, when running inside of a cluster
Gaston Dombiak's avatar
Gaston Dombiak committed
133 134 135 136
     * the node that has the actual outgoing connection will be requested to deliver
     * the requested packet.<p>
     *
     * Packets routed to components will only be sent if the internal or external
guus's avatar
guus committed
137
     * component is connected to the server. Moreover, when running inside of a cluster
Gaston Dombiak's avatar
Gaston Dombiak committed
138
     * the node that is hosting the component will be requested to deliver the requested
139 140
     * packet. It will be first checked if the component is available in this JVM and if not
     * then the first cluster node found hosting the component will be used.<p>
Gaston Dombiak's avatar
Gaston Dombiak committed
141 142 143 144 145 146
     *
     * Packets routed to users will be delivered if the user is connected to the server. Depending
     * on the packet type and the sender of the packet only available or all user sessions could
     * be considered. For instance, {@link org.xmpp.packet.Message Messages} and
     * {@link org.xmpp.packet.Presence Presences} are only sent to available client sessions whilst
     * {@link org.xmpp.packet.IQ IQs} originated to the server can be sent to available or unavailable
guus's avatar
guus committed
147
     * sessions. When running inside of a cluster the node that is hosting the user session will be
Gaston Dombiak's avatar
Gaston Dombiak committed
148 149
     * requested to deliver the requested packet.<p>
     *
guus's avatar
guus committed
150
     * @param jid the recipient of the packet to route.
Gaston Dombiak's avatar
Gaston Dombiak committed
151
     * @param packet the packet to route.
Gaston Dombiak's avatar
Gaston Dombiak committed
152 153
     * @param fromServer true if the packet was created by the server. This packets should
     *        always be delivered
Gaston Dombiak's avatar
Gaston Dombiak committed
154 155
     * @throws PacketException thrown if the packet is malformed (results in the sender's
     *      session being shutdown).
156
     */
Gaston Dombiak's avatar
Gaston Dombiak committed
157
    void routePacket(JID jid, Packet packet, boolean fromServer) throws PacketException;
158 159

    /**
Gaston Dombiak's avatar
Gaston Dombiak committed
160 161
     * Returns true if a registered user or anonymous user with the specified full JID is
     * currently logged. When running inside of a cluster a true value will be returned
162 163 164
     * as long as the user is connected to any cluster node.
     *
     * // TODO Should we care about available or not available????
Gaston Dombiak's avatar
Gaston Dombiak committed
165 166 167 168 169 170 171
     *
     * @param jid the full JID of the user.
     * @return true if a registered user or anonymous user with the specified full JID is
     * currently logged.
     */
    boolean hasClientRoute(JID jid);

172 173 174 175 176 177 178 179 180 181
    /**
     * Returns true if an anonymous user with the specified full JID is currently logged.
     * When running inside of a cluster a true value will be returned as long as the
     * user is connected to any cluster node.
     *
     * @param jid the full JID of the anonymous user.
     * @return true if an anonymous user with the specified full JID is currently logged.
     */
    boolean isAnonymousRoute(JID jid);

182 183 184 185 186 187 188 189 190 191 192 193 194
    /**
     * Returns true if the specified address belongs to a route that is hosted by this JVM.
     * When running inside of a cluster each cluster node will host routes to local resources.
     * A false value could either mean that the route is not hosted by this JVM but other
     * cluster node or that there is no route to the specified address. Use
     * {@link XMPPServer#isLocal(org.xmpp.packet.JID)} to figure out if the address
     * belongs to tge domain hosted by this server.
     *
     * @param jid the address of the route.
     * @return true if the specified address belongs to a route that is hosted by this JVM.
     */
    boolean isLocalRoute(JID jid);

Gaston Dombiak's avatar
Gaston Dombiak committed
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
    /**
     * Returns true if an outgoing server session exists to the specified remote server.
     * The JID can be a full JID or a bare JID since only the domain of the specified
     * address will be used to look up the route.<p>
     *
     * When running inside of a cluster the look up will be done in all the cluster. So
     * as long as a node has a connection to the remote server a true value will be
     * returned.
     *
     * @param jid JID that specifies the remote server address.
     * @return true if an outgoing server session exists to the specified remote server.
     */
    boolean hasServerRoute(JID jid);

    /**
     * Returns true if an internal or external component is hosting the specified address.
     * The JID can be a full JID or a bare JID since only the domain of the specified
     * address will be used to look up the route.<p>
     *
     * When running inside of a cluster the look up will be done in all the cluster. So
     * as long as a node is hosting the component  a true value will be returned.
     *
     * @param jid JID that specifies the component address.
     * @return true if an internal or external component is hosting the specified address.
     */
    boolean hasComponentRoute(JID jid);

222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
    /**
     * Returns the client session associated to the specified XMPP address or <tt>null</tt>
     * if none was found. When running inside of a cluster and a remote node is hosting
     * the client session then a session surrage will be returned.
     *
     * @param jid the address of the session.
     * @return the client session associated to the specified XMPP address or null if none was found.
     */
    ClientSession getClientRoute(JID jid);

    /**
     * Returns collection of client sessions authenticated with the server. When running inside
     * of a cluster the returned sessions will include sessions connected to this JVM and also
     * other cluster nodes.
     *
     * TODO Prevent usage of this message and change original requirement to avoid having to load all sessions.
     * TODO This may not scale when hosting millions of sessions.
     *
240
     * @param onlyLocal true if only client sessions connected to this JVM must be considered.
241 242
     * @return collection of client sessions authenticated with the server.
     */
243
    Collection<ClientSession> getClientsRoutes(boolean onlyLocal);
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263

    /**
     * Returns the outgoing server session associated to the specified XMPP address or <tt>null</tt>
     * if none was found. When running inside of a cluster and a remote node is hosting
     * the session then a session surrage will be returned.
     *
     * @param jid the address of the session.
     * @return the outgoing server session associated to the specified XMPP address or null if none was found.
     */
    OutgoingServerSession getServerRoute(JID jid);

    /**
     * Returns a collection with the hostnames of the remote servers that currently may receive
     * packets sent from this server.
     *
     * @return a collection with the hostnames of the remote servers that currently may receive
     *         packets sent from this server.
     */
    Collection<String> getServerHostnames();

Gaston Dombiak's avatar
Gaston Dombiak committed
264 265 266 267 268 269 270 271 272
    /**
     * Returns the number of outgoing server sessions hosted in this JVM. When runing inside of
     * a cluster you will need to get this value for each cluster node to learn the total number
     * of outgoing server sessions.
     *
     * @return the number of outgoing server sessions hosted in this JVM.
     */
    int getServerSessionsCount();

273 274 275 276 277 278 279 280
    /**
     * Returns domains of components hosted by the server. When running in a cluster, domains of
     * components running in any node will be returned.
     *
     * @return domains of components hosted by the server.
     */
    Collection<String> getComponentsDomains();

Gaston Dombiak's avatar
Gaston Dombiak committed
281 282 283 284 285 286 287 288 289 290 291
    /**
     * Returns the list of routes associated to the specified route address. When asking
     * for routes to a remote server then the requested JID will be included as the only
     * value of the returned collection. It is indifferent if an outgoing session to the
     * specified remote server exists or not.<p>
     *
     * When asking for routes to client sessions the specified route address could either
     * be a full JID of a bare JID. In the case of a full JID, a single element will be
     * included in the answer in case the specified full JID exists or an empty collection
     * if the full JID does not exist. Moreover, when passing a bare JID a list of full
     * JIDs will be returned for each available resource associated to the bare JID. In
292 293 294 295 296
     * any case, only JIDs of <tt>available</tt> client sessions are returned. However,
     * there is an exception with directed presences. Unavailable routes may be returned
     * if and only if the owner of the route sent a directed presence to the requester
     * thus becoming available to the requester. If requester is <tt>null</tt> then only
     * available resources are considered.<p>
Gaston Dombiak's avatar
Gaston Dombiak committed
297 298 299 300 301 302
     *
     * When asking for routes to components a single element will be returned in the answer
     * only if an internal or external component is found for the specified route address.
     * If no component was found then an empty collection will be returned.
     *
     * @param route The address we want a route to.
303 304
     * @param requester The address of the entity requesting the routes or null if we don't
     * care about directed presences.
Gaston Dombiak's avatar
Gaston Dombiak committed
305 306
     * @return list of routes associated to the specified route address.
     */
307
    List<JID> getRoutes(JID route, JID requester);
Gaston Dombiak's avatar
Gaston Dombiak committed
308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336

    /**
     * Returns true if a route of a client session has been successfully removed. When running
     * inside of a cluster this message <tt>must</tt> be sent from the cluster node that is
     * actually hosting the client session.
     *
     * @param route the route to remove.
     * @return true if a route of a client session has been successfully removed.
     */
    boolean removeClientRoute(JID route);

    /**
     * Returns true if a route to an outoing server has been successfully removed. When running
     * inside of a cluster this message <tt>must</tt> be sent from the cluster node that is
     * actually holding the physical connectoin to the remote server. 
     *
     * @param route the route to remove.
     * @return true if the route was successfully removed.
     */
    boolean removeServerRoute(JID route);

    /**
     * Returns true if a route of a component has been successfully removed. Both internal
     * and external components have a route in the table. When running inside of a cluster
     * this message <tt>must</tt> be sent from the cluster node that is actually hosting the
     * component.
     *
     * @param route the route to remove.
     * @return true if a route of a component has been successfully removed.
337
     */
Gaston Dombiak's avatar
Gaston Dombiak committed
338
    boolean removeComponentRoute(JID route);
339 340

    /**
Gaston Dombiak's avatar
Gaston Dombiak committed
341 342
     * Sets the {@link RemotePacketRouter} to use for deliverying packets to entities hosted
     * in remote nodes of the cluster.
343
     *
Gaston Dombiak's avatar
Gaston Dombiak committed
344 345
     * @param remotePacketRouter the RemotePacketRouter to use for deliverying packets to entities hosted
     *        in remote nodes of the cluster.
346
     */
Gaston Dombiak's avatar
Gaston Dombiak committed
347
    void setRemotePacketRouter(RemotePacketRouter remotePacketRouter);
348

349 350 351 352 353 354 355 356 357
    /**
     * Returns the {@link RemotePacketRouter} to use for deliverying packets to entities hosted
     * in remote nodes of the cluster or <tt>null</tt> if none was set.
     *
     * @return the RemotePacketRouter to use for deliverying packets to entities hosted
     *        in remote nodes of the cluster.
     */
    RemotePacketRouter getRemotePacketRouter();

358 359 360 361 362 363 364 365
    /**
     * Broadcasts the specified message to connected client sessions to the local node or
     * across the cluster. Both available and unavailable client sessions will receive the message.
     *
     * @param packet the message to broadcast.
     * @param onlyLocal true if only client sessions connecte to the local JVM will get the message.
     */
    void broadcastPacket(Message packet, boolean onlyLocal);
366
}