private void handle(IQ packet) {
        JID recipientJID = packet.getTo();
        // Check if the packet was sent to the server hostname
        if (recipientJID != null && recipientJID.getNode() == null &&
                recipientJID.getResource() == null && serverName.equals(recipientJID.getDomain())) {
            Element childElement = packet.getChildElement();
            if (childElement != null && childElement.element("addresses") != null) {
                // Packet includes multicast processing instructions. Ask the multicastRouter
                // to route this packet
                multicastRouter.route(packet);
                return;
            }
        }
        if (packet.getID() != null && (IQ.Type.result == packet.getType() || IQ.Type.error == packet.getType())) {
            // The server got an answer to an IQ packet that was sent from the server

            // If there's a listener for this result at all, then it's likely that that listener had been registered
            // on this cluster node. For efficiency, try the local cluster node before triggering tasks in the rest
            // of the cluster.
            IQResultListener iqResultListener = resultListeners.remove(packet.getID());
            if (iqResultListener != null) {
                resultTimeout.remove(packet.getID());
                resultPending.remove(packet.getID());
                try {
                    iqResultListener.receivedAnswer(packet);
                }
                catch (Exception e) {
                    Log.error("Error processing answer of remote entity. Answer: " + packet.toXML(), e);
                }
                return;
            } else if (ClusterManager.isClusteringStarted() ) {
                // Only do lookups in the cluster, after it's determined that the local node cannot process the result.
                final NodeID nodeID = resultPending.remove(packet.getID()); // remove it, to reduce the risk of this packet being sent back and forth.
                if ( nodeID != null && !XMPPServer.getInstance().getNodeID().equals( nodeID ) )
                {
                    CacheFactory.doClusterTask( new IQResultListenerTask( packet ), nodeID.toByteArray() );
                    return;
                }
            }
        }
        try {
            // Check for registered components, services or remote servers

            // OF-2112: It is generally permissible to route stanzas that have no 'from' attribute. However,
            // they are not allowed in s2s traffic.
            if (packet.getFrom() == null && !XMPPServer.getInstance().isLocal(recipientJID)) {
                // Stanzas that originate from clients _always_ have a 'from' attribute (as that attribute value is set/
                // overwritten by Openfire upon receiving the stanza, to prevent abuse where a user tries to impersonate
                // someone else). That means that, if we're processing a stanza without a 'from' attribute, that the
                // stanza is very likely to originate from Openfire's code. If we have code that generates a stanza
                // without a 'from' address but addressed to a remote domain, this simply is a bug that we should very
                // verbosely warn about.
                Log.error("Unable to process a stanza that has no 'from' attribute, addressed to a remote entity. Stanza is being dropped: {}", packet.toXML());
                return;
            }
            if (recipientJID != null &&
                (routingTable.hasComponentRoute(recipientJID) ||
                    (packet.getFrom() != null && routingTable.hasServerRoute(new DomainPair(packet.getFrom().getDomain(), recipientJID.getDomain()))))) {
                // A component/service/remote server was found that can handle the Packet
                routingTable.routePacket(recipientJID, packet);
                return;
            }

            if (isLocalServer(recipientJID)) {
                // Let the server handle the Packet
                Element childElement = packet.getChildElement();
                String namespace = null;
                if (childElement != null) {
                    namespace = childElement.getNamespaceURI();
                }
                if (namespace == null) {
                    if (packet.getType() != IQ.Type.result && packet.getType() != IQ.Type.error) {
                        // Do nothing. We can't handle queries outside of a valid namespace
                        Log.warn("Unknown packet " + packet.toXML());
                    }
                }
                else {
                    // Check if communication to local users is allowed
                    if (recipientJID != null && (userManager.isRegisteredUser(recipientJID, false) || UserManager.isPotentialFutureLocalUser(recipientJID)))
                    {
                        PrivacyList list = PrivacyListManager.getInstance().getDefaultPrivacyList(recipientJID.getNode());
                        if (list != null && list.shouldBlockPacket(packet)) {
                            // Communication is blocked
                            if (IQ.Type.set == packet.getType() || IQ.Type.get == packet.getType()) {
                                // Answer that the service is unavailable
                                Log.trace("Responding with 'service-unavailable' as IQ request blocked by privacy list, to: {}", packet);
                                sendErrorPacket(packet, PacketError.Condition.service_unavailable);
                            }
                            return;
                        }
                    }
                    IQHandler handler = getHandler(namespace);
                    if (handler == null) {
                        if (recipientJID == null) {
                            // Answer an error since the server can't handle the requested namespace
                            Log.trace("Responding with 'service-unavailable' since the server can't handle the requested namespace, to: {}", packet);
                            sendErrorPacket(packet, PacketError.Condition.service_unavailable);
                        }
                        else if (recipientJID.getNode() == null ||
                                "".equals(recipientJID.getNode())) {
                            // Answer an error if JID is of the form <domain>
                            sendErrorPacket(packet, PacketError.Condition.feature_not_implemented);
                        }
                        else {
                            // JID is of the form <node@domain>
                            Log.trace("Responding with 'service-unavailable' since the server can't handle packets sent to a node, to: {}", packet);
                            sendErrorPacket(packet, PacketError.Condition.service_unavailable);
                        }
                    }
                    else {
                        handler.process(packet);
                    }
                }
            }
            else {

                // RFC 6121 8.5.1.  No Such User http://xmpp.org/rfcs/rfc6121.html#rules-localpart-nosuchuser
                // If the 'to' address specifies a bare JID <localpart@domainpart> or full JID <localpart@domainpart/resourcepart> where the domainpart of the JID matches a configured domain that is serviced by the server itself, the server MUST proceed as follows.
                // If the user account identified by the 'to' attribute does not exist, how the stanza is processed depends on the stanza type.
                if (packet.isRequest() && recipientJID != null && recipientJID.getNode() != null
                    && !XMPPServer.getInstance().isRemote(recipientJID)
                    && !userManager.isRegisteredUser(recipientJID, false)
                    && !UserManager.isPotentialFutureLocalUser(recipientJID)
                    && !sessionManager.isAnonymousClientSession(recipientJID)
                    && sessionManager.getSession(recipientJID) == null
                    && !(recipientJID.asBareJID().equals(packet.getFrom().asBareJID()) && sessionManager.isPreAuthenticatedSession(packet.getFrom())) // A pre-authenticated session queries the server about itself.
                )
                {
                    // For an IQ stanza, the server MUST return a <service-unavailable/> stanza error to the sender.
                    Log.trace("Responding with 'service-unavailable' since there's no such local user that matches the addressee, to: {}", packet);
                    sendErrorPacket(packet, PacketError.Condition.service_unavailable);
                    return;
                }

                ClientSession session = sessionManager.getSession(packet.getFrom());
                boolean isAcceptable = true;
                if (session instanceof LocalClientSession) {
                    // Check if we could process IQ stanzas from the recipient.
                    // If not, return a not-acceptable error as per XEP-0016:
                    // If the user attempts to send an outbound stanza to a contact and that stanza type is blocked, the user's server MUST NOT route the stanza to the contact but instead MUST return a <not-acceptable/> error
                    IQ dummyIQ = packet.createCopy();
                    dummyIQ.setFrom(packet.getTo());
                    dummyIQ.setTo(packet.getFrom());
                    if (!((LocalClientSession) session).canDeliver(dummyIQ)) {
                        packet.setTo(session.getAddress());
                        packet.setFrom((JID) null);
                        packet.setError(PacketError.Condition.not_acceptable);
                        session.process(packet);
                        isAcceptable = false;
                    }
                }

                if (isAcceptable) {
                    // JID is of the form <node@domain/resource> or belongs to a remote server
                    // or to an uninstalled component
                    routingTable.routePacket(recipientJID, packet);
                }
            }
        }
        catch (Exception e) {
            Log.error(LocaleUtils.getLocalizedString("admin.error.routing"), e);
            Session session = sessionManager.getSession(packet.getFrom());
            if (session != null) {
                IQ reply = IQ.createResultIQ(packet);
                reply.setError(PacketError.Condition.internal_server_error);
                session.process(reply);
            }
        }
    }
A JID is considered local if:
1) is null or
2) has no domain or domain is empty
or
if it's not a full JID and it was sent to the server itself.

@param recipientJID address to check.
@return true if the specified address belongs to the local server.
xmppserver/src/main/java/org/jivesoftware/openfire/IQRouter.java