⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sessionmanager.java

📁 基于Jabber协议的即时消息服务器
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
                // the remote server
                sessions.add(session);
            }
        }
    }

    /**
     * Unregisters the server sessions originated by a remote server with the specified hostname.
     * Notice that the remote server may be hosting several subdomains as well as virtual hosts so
     * the same IncomingServerSession may be associated with many keys. The remote server may have
     * many sessions established with this server (eg. to the server itself and to subdomains
     * hosted by this server).
     *
     * @param hostname the hostname that is being served by the remote server.
     */
    public void unregisterIncomingServerSessions(String hostname) {
        synchronized (incomingServerSessions) {
            incomingServerSessions.remove(hostname);
        }
    }

    /**
     * Unregisters the specified remote server session originiated by the specified remote server.
     *
     * @param hostname the hostname that is being served by the remote server.
     * @param session the session to unregiser.
     */
    private void unregisterIncomingServerSession(String hostname, IncomingServerSession session) {
        synchronized (incomingServerSessions) {
            List<IncomingServerSession> sessions = incomingServerSessions.get(hostname);
            if (sessions != null) {
                sessions.remove(session);
                if (sessions.isEmpty()) {
                    // Remove key since there are no more sessions associated
                    incomingServerSessions.remove(hostname);
                }
            }
        }
    }

    /**
     * Registers that a server session originated by this server has been established to
     * a remote server named hostname. This session will only be used for sending packets
     * to the remote server and cannot receive packets. The {@link OutgoingServerSession}
     * may have one or more domains, subdomains or virtual hosts authenticated with the
     * remote server.
     *
     * @param hostname the hostname that is being served by the remote server.
     * @param session the outgoing server session to the remote server.
     */
    public void registerOutgoingServerSession(String hostname, OutgoingServerSession session) {
        outgoingServerSessions.put(hostname, session);
    }

    /**
     * Unregisters the server session that was originated by this server to a remote server
     * named hostname. This session was only being used for sending packets
     * to the remote server and not for receiving packets. The {@link OutgoingServerSession}
     * may have one or more domains, subdomains or virtual hosts authenticated with the
     * remote server.
     *
     * @param hostname the hostname that the session was connected with.
     */
    public void unregisterOutgoingServerSession(String hostname) {
        outgoingServerSessions.remove(hostname);
    }

    /**
     * Add a new session to be managed.
     */
    public void addSession(ClientSession session) {
        String username = session.getAddress().getNode();
        SessionMap resources;

        synchronized (username.intern()) {
            resources = sessions.get(username);
            if (resources == null) {
                resources = new SessionMap();
                sessions.put(username, resources);
            }
            resources.addSession(session);
        }
        // Remove the pre-Authenticated session but remember to use the temporary ID as the key
        preAuthenticatedSessions.remove(session.getStreamID().toString());
        // Fire session created event.
        SessionEventDispatcher
                .dispatchEvent(session, SessionEventDispatcher.EventType.session_created);
    }

    /**
     * Notification message sent when a client sent an available presence for the session. Making
     * the session available means that the session is now eligible for receiving messages from
     * other clients. Sessions whose presence is not available may only receive packets (IQ packets)
     * from the server. Therefore, an unavailable session remains invisible to other clients.
     *
     * @param session the session that receieved an available presence.
     */
    public void sessionAvailable(ClientSession session) {
        if (anonymousSessions.containsValue(session)) {
            // Anonymous session always have resources so we only need to add one route. That is
            // the route to the anonymous session
            routingTable.addRoute(session.getAddress(), session);
        }
        else {
            // A non-anonymous session is now available
            Session defaultSession;
            try {
                SessionMap sessionMap = sessions.get(session.getUsername());
                if (sessionMap == null) {
                    Log.warn("No SessionMap found for session" + "\n" + session);
                }
                // Update the order of the sessions based on the new presence of this session
                sessionMap.sessionAvailable(session);
                defaultSession = sessionMap.getDefaultSession(true);
                JID node = new JID(defaultSession.getAddress().getNode(),
                        defaultSession.getAddress().getDomain(), null);
                // Add route to default session (used when no resource is specified)
                routingTable.addRoute(node, defaultSession);
                // Add route to the new session
                routingTable.addRoute(session.getAddress(), session);
                // Broadcast presence between the user's resources
                broadcastPresenceOfOtherResource(session);
            }
            catch (UserNotFoundException e) {
                // Do nothing since the session is anonymous (? - shouldn't happen)
            }
        }
    }

    /**
     * Sends the presences of other connected resources to the resource that just connected.
     * 
     * @param session the newly created session.
     */
    private void broadcastPresenceOfOtherResource(ClientSession session)
            throws UserNotFoundException {
        Presence presence;
        Collection<ClientSession> availableSession;
        SessionMap sessionMap = sessions.get(session.getUsername());
        if (sessionMap != null) {
            availableSession = new ArrayList<ClientSession>(sessionMap.getAvailableSessions());
            for (ClientSession userSession : availableSession) {
                if (userSession != session) {
                    // Send the presence of an existing session to the session that has just changed
                    // the presence
                    presence = userSession.getPresence().createCopy();
                    presence.setTo(session.getAddress());
                    session.process(presence);
                }
            }
        }
    }

    /**
     * Broadcasts presence updates from the originating user's resource to any of the user's
     * existing available resources (if any).
     *
     * @param originatingResource the full JID of the session that sent the presence update.
     */
    public void broadcastPresenceToOtherResources(JID originatingResource, Presence presence) {
        Collection<ClientSession> availableSession;
        SessionMap sessionMap = sessions.get(originatingResource.getNode());
        if (sessionMap != null) {
            availableSession = new ArrayList<ClientSession>(sessionMap.getAvailableSessions());
            for (ClientSession userSession : availableSession) {
                if (userSession.getAddress() != originatingResource) {
                    // Send the presence of the session whose presence has changed to
                    // this other user's session
                    presence.setTo(userSession.getAddress());
                    userSession.process(presence);
                }
            }
        }
    }

    /**
     * Notification message sent when a client sent an unavailable presence for the session. Making
     * the session unavailable means that the session is not eligible for receiving messages from
     * other clients.
     *
     * @param session the session that receieved an unavailable presence.
     */
    public void sessionUnavailable(ClientSession session) {
        if (session.getAddress() != null && routingTable != null &&
                session.getAddress().toBareJID().trim().length() != 0) {
            // Remove route to the removed session (anonymous or not)
            routingTable.removeRoute(session.getAddress());
            try {
                if (session.getUsername() == null) {
                    // Do nothing since this is an anonymous session
                    return;
                }
                SessionMap sessionMap = sessions.get(session.getUsername());
                // If sessionMap is null, which is an irregular case, try to clean up the routes to
                // the user from the routing table
                if (sessionMap == null) {
                    JID userJID = new JID(session.getUsername(), serverName, "");
                    if (routingTable.getRoute(userJID) != null) {
                        // Remove the route for the session's BARE address
                        routingTable.removeRoute(new JID(session.getAddress().getNode(),
                                session.getAddress().getDomain(), ""));
                    }
                }
                // If all the user sessions are gone then remove the route to the default session
                else if (sessionMap.getAvailableSessions().isEmpty()) {
                    // Remove the route for the session's BARE address
                    routingTable.removeRoute(new JID(session.getAddress().getNode(),
                            session.getAddress().getDomain(), ""));
                }
                else {
                    // Update the order of the sessions based on the new presence of this session
                    sessionMap.sessionUnavailable(session);
                    // Update the route for the session's BARE address
                    Session defaultSession = sessionMap.getDefaultSession(true);
                    routingTable.addRoute(new JID(defaultSession.getAddress().getNode(),
                            defaultSession.getAddress().getDomain(), ""),
                            defaultSession);
                }
            }
            catch (UserNotFoundException e) {
                // Do nothing since the session is anonymous
            }
        }
    }

    /**
     * Change the priority of a session, that was already available, associated with the sender.
     *
     * @param sender   The sender who's session just changed priority
     * @param priority The new priority for the session
     */
    public void changePriority(JID sender, int priority) {
        if (sender.getNode() == null || !userManager.isRegisteredUser(sender.getNode())) {
            // Do nothing if the session belongs to an anonymous user
            return;
        }
        Session defaultSession;
        String username = sender.getNode();
        SessionMap resources = sessions.get(username);
        if (resources == null) {
            return;
        }
        synchronized (username.intern()) {
            resources.changePriority(sender, priority);

            // Get the session with highest priority
            defaultSession = resources.getDefaultSession(true);
        }
        // Update the route to the bareJID with the session with highest priority
        routingTable.addRoute(new JID(defaultSession.getAddress().getNode(),
                defaultSession.getAddress().getDomain(), ""),
                defaultSession);
    }


    /**
     * Retrieve the best route to deliver packets to this session given the recipient jid. If the
     * requested JID does not have a node (i.e. username) then the best route will be looked up
     * in the anonymous sessions list. Otherwise, try to find a root for the exact JID
     * (i.e. including the resource) and if none is found then answer the deafult session if any.
     *
     * @param recipient The recipient ID to deliver packets to
     * @return The XMPPAddress best suited to use for delivery to the recipient
     */
    public ClientSession getBestRoute(JID recipient) {
        // Return null if the JID belongs to a foreign server
        if (serverName == null || !serverName.equals(recipient.getDomain())) {
             return null;
        }
        ClientSession session = null;
        String resource = recipient.getResource();
        String username = recipient.getNode();
        if (resource != null && (username == null || !userManager.isRegisteredUser(username))) {
            session = anonymousSessions.get(resource);
            if (session == null){
                session = getSession(recipient);
            }
        }
        else {
            SessionMap sessionMap = sessions.get(username);
            if (sessionMap != null) {
                if (resource == null) {
                    synchronized (username.intern()) {
                        session = sessionMap.getDefaultSession(false);
                    }
                }
                else {
                    session = sessionMap.getSession(resource);
                    if (session == null) {
                        synchronized (username.intern()) {
                            session = sessionMap.getDefaultSession(false);
                        }
                    }
                }
            }
        }
        // Sanity check - check if the underlying session connection is closed. Remove the session
        // from the list of sessions if the session is closed and proceed to look for another route.
        if (session != null && session.getConnection().isClosed()) {
            removeSession(session);
            return getBestRoute(recipient);
        }
        return session;
    }

    public boolean isAnonymousRoute(String username) {
        // JID's node and resource are the same for anonymous sessions
        return anonymousSessions.containsKey(username);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -