public void route(Message packet) {
        if (packet == null) {
            throw new NullPointerException();
        }
        ClientSession session = sessionManager.getSession(packet.getFrom());

        try {
            // Invoke the interceptors before we process the read packet
            InterceptorManager.getInstance().invokeInterceptors(packet, session, true, false);
            if (session == null || session.isAuthenticated()) {
                JID recipientJID = packet.getTo();

                // If the server receives a message stanza with no 'to' attribute, it MUST treat the message as if the 'to' address were the bare JID <localpart@domainpart> of the sending entity.
                if (recipientJID == null) {
                    recipientJID = packet.getFrom().asBareJID();
                }

                // Check if the message was sent to the server hostname
                if (recipientJID.getNode() == null && recipientJID.getResource() == null &&
                        serverName.equals(recipientJID.getDomain())) {
                    if (packet.getElement().element("addresses") != null) {
                        // Message includes multicast processing instructions. Ask the multicastRouter
                        // to route this packet
                        multicastRouter.route(packet);
                    }
                    else {
                        // Message was sent to the server hostname so forward it to a configurable
                        // set of JID's (probably admin users)
                        sendMessageToAdmins(packet);
                    }
                    return;
                }

                boolean isAcceptable = true;
                if (session instanceof LocalClientSession) {
                    // Check if we could process messages 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
                    Message dummyMessage = packet.createCopy();
                    dummyMessage.setFrom(packet.getTo());
                    dummyMessage.setTo(packet.getFrom());
                    if (!((LocalClientSession) session).canDeliver(dummyMessage)) {
                        packet.setTo(session.getAddress());
                        packet.setFrom((JID)null);
                        packet.setError(PacketError.Condition.not_acceptable);
                        session.process(packet);
                        isAcceptable = false;
                    }
                }
                if (isAcceptable) {
                    try {
                        // Deliver stanza to requested route
                        routingTable.routePacket(recipientJID, packet);
                    } catch (Exception e) {
                        log.error("Failed to route packet: " + packet.toXML(), e);
                        routingFailed(recipientJID, packet);
                    }

                    // Sent carbon copies to other resources of the sender:
                    if (session != null && Forwarded.isEligibleForCarbonsDelivery(packet)) {
                        List<JID> routes = routingTable.getRoutes(packet.getFrom().asBareJID(), null);
                        for (JID route : routes) {
                            // The sending server SHOULD NOT send a forwarded copy to the sending full JID if it is a Carbons-enabled resource.
                            if (!route.equals(session.getAddress())) {
                                ClientSession clientSession = sessionManager.getSession(route);
                                if (clientSession != null && clientSession.isMessageCarbonsEnabled()) {
                                    Message message = new Message();
                                    // The wrapping message SHOULD maintain the same 'type' attribute value
                                    message.setType(packet.getType());
                                    // the 'from' attribute MUST be the Carbons-enabled user's bare JID
                                    message.setFrom(packet.getFrom().asBareJID());
                                    // and the 'to' attribute SHOULD be the full JID of the resource receiving the copy
                                    message.setTo(route);
                                    // The content of the wrapping message MUST contain a <sent/> element qualified by the namespace "urn:xmpp:carbons:2", which itself contains a <forwarded/> qualified by the namespace "urn:xmpp:forward:0" that contains the original <message/> stanza.
                                    message.addExtension(new Sent(new Forwarded(packet)));
                                    clientSession.process(message);
                                }
                            }
                        }
                    }
                }
            }
            else if (SessionPacketRouter.isInvalidStanzaSentPriorToResourceBinding(packet, session)) {
                log.debug("Closing session that attempts to send stanza to an entity other than the server itself or the client's account, before completing resource binding. Session closed: {}", session);
                session.deliverRawText(new StreamError(StreamError.Condition.not_authorized).toXML());
                return;
            }
            else {
                packet.setTo(session.getAddress());
                packet.setFrom((JID)null);
                packet.setError(PacketError.Condition.not_authorized);
                session.process(packet);
            }
            // Invoke the interceptors after we have processed the read packet
            InterceptorManager.getInstance().invokeInterceptors(packet, session, true, true);
        } catch (PacketRejectedException e) {
            // An interceptor rejected this packet
            if (session != null && (e.getRejectionError() != null || (e.getRejectionMessage() != null && !e.getRejectionMessage().trim().isEmpty()))) {
                // A message for the rejection will be sent to the sender of the rejected packet
                Message reply = new Message();
                reply.setID(packet.getID());
                reply.setTo(session.getAddress());
                reply.setFrom(packet.getTo());
                reply.setType(packet.getType());
                reply.setThread(packet.getThread());
                if (e.getRejectionMessage() != null && !e.getRejectionMessage().trim().isEmpty()) {
                    reply.setBody(e.getRejectionMessage());
                }
                if (e.getRejectionError() != null) {
                    reply.setError(e.getRejectionError());
                }
                session.process(reply);
            }
        }
    }
<p>Performs the actual packet routing.</p>
<p>You routing is considered 'quick' and implementations may not take
excessive amounts of time to complete the routing. If routing will take
a long amount of time, the actual routing should be done in another thread
so this method returns quickly.</p>
<h2>Warning</h2>
<p>Be careful to enforce concurrency DbC of concurrent by synchronizing
any accesses to class resources.</p>

@param packet The packet to route
@throws NullPointerException If the packet is null
xmppserver/src/main/java/org/jivesoftware/openfire/MessageRouter.java