Search in sources :

Example 6 with MultiUserChatService

use of org.jivesoftware.openfire.muc.MultiUserChatService in project Openfire by igniterealtime.

the class SyncLocalOccupantsAndSendJoinPresenceTask method run.

@Override
public void run() {
    Log.debug("Going to execute sync occupants task for {} occupants from node {}", occupants.size(), originator);
    final MultiUserChatService multiUserChatService = XMPPServer.getInstance().getMultiUserChatManager().getMultiUserChatService(subdomain);
    ((MultiUserChatServiceImpl) multiUserChatService).process(this);
    Log.trace("Finished executing sync occupants task for occupants {} from node {}", occupants.size(), originator);
}
Also used : MultiUserChatServiceImpl(org.jivesoftware.openfire.muc.spi.MultiUserChatServiceImpl) MultiUserChatService(org.jivesoftware.openfire.muc.MultiUserChatService)

Example 7 with MultiUserChatService

use of org.jivesoftware.openfire.muc.MultiUserChatService in project Openfire by igniterealtime.

the class ServiceUpdatedEvent method run.

@Override
public void run() {
    MultiUserChatService service = XMPPServer.getInstance().getMultiUserChatManager().getMultiUserChatService(subdomain);
    if (service != null) {
        // Reload properties from database (OF-2164)
        XMPPServer.getInstance().getMultiUserChatManager().refreshService(subdomain);
        if (service instanceof MultiUserChatServiceImpl) {
            MUCPersistenceManager.refreshProperties(subdomain);
            ((MultiUserChatServiceImpl) service).initializeSettings();
        } else {
            // Ok.  We don't handle non default implementations for this.  Why are we seeing it?
            Log.warn("Processing an update event for service '{}' that is of an unknown implementation: {}", subdomain, service.getClass());
        }
    } else {
        // Hrm.  We got an update for something that we don't have.
        Log.warn("ServiceUpdatedEvent: Received update for service we are not running: {}", subdomain);
    }
}
Also used : MultiUserChatServiceImpl(org.jivesoftware.openfire.muc.spi.MultiUserChatServiceImpl) MultiUserChatService(org.jivesoftware.openfire.muc.MultiUserChatService)

Example 8 with MultiUserChatService

use of org.jivesoftware.openfire.muc.MultiUserChatService in project Openfire by igniterealtime.

the class LocalMUCRoomManager method restoreCacheContentAfterJoin.

/**
 * When the local node is joining or leaving a cluster, {@link org.jivesoftware.util.cache.CacheFactory} will swap
 * the implementation used to instantiate caches. This causes the cache content to be 'reset': it will no longer
 * contain the data that's provided by the local node. This method restores data that's provided by the local node
 * in the cache. It is expected to be invoked right after joining the cluster.
 *
 * This method checks whether local occupant nicknames clash with remote ones. If a clash is detected, both
 * occupants are kicked out of the room.
 *
 * ({@link org.jivesoftware.openfire.cluster.ClusterEventListener#joinedCluster()} or leaving
 *
 * @param occupantManager The occupant manager that contains local occupant registration.
 * @return The set of local occupants that is in the room after processing. This is the original set of local occupants of the room minus any occupants that were kicked out.
 */
public Set<OccupantManager.Occupant> restoreCacheContentAfterJoin(@Nonnull final OccupantManager occupantManager) {
    Log.debug("Restoring cache content for cache '{}' after we joined the cluster, by adding all MUC Rooms that are known to the local node.", ROOM_CACHE.getName());
    final Set<OccupantManager.Occupant> localOccupants = occupantManager.getLocalOccupants();
    final Set<OccupantManager.Occupant> occupantsToRetain = new HashSet<>(localOccupants);
    final Map<String, List<OccupantManager.Occupant>> localOccupantByRoom = localOccupants.stream().collect(Collectors.groupingBy(OccupantManager.Occupant::getRoomName));
    // The state of the rooms in the clustered cache should be modified to include our local occupants.
    for (Map.Entry<String, MUCRoom> localRoomEntry : localRooms.entrySet()) {
        final String roomName = localRoomEntry.getKey();
        Log.trace("Re-adding local room '{}' to cluster cache.", roomName);
        final Lock lock = ROOM_CACHE.getLock(roomName);
        lock.lock();
        try {
            final MUCRoom localRoom = localRoomEntry.getValue();
            if (!ROOM_CACHE.containsKey(roomName)) {
                Log.trace("Room was not known to the cluster. Added our representation.");
                ROOM_CACHE.put(roomName, localRoom);
            } else {
                Log.trace("Room was known to the cluster. Merging our local representation with cluster-provided data.");
                final MUCRoom roomInCluster = ROOM_CACHE.get(roomName);
                // Get all occupants that were provided by the local node, and add them to the cluster-representation.
                final List<OccupantManager.Occupant> localOccupantsToRestore = localOccupantByRoom.get(roomName);
                if (localOccupantsToRestore != null) {
                    Log.trace("These occupants of the room are recognized as living on our cluster node. Adding them from the cluster-based room: {}", localOccupantsToRestore.stream().map(OccupantManager.Occupant::getRealJID).map(JID::toString).collect(Collectors.joining(", ")));
                    for (OccupantManager.Occupant localOccupantToRestore : localOccupantsToRestore) {
                        // Get the Role for the local occupant from the local representation of the room, and add that to the cluster room.
                        final MUCRole localOccupantRole = localRoom.getOccupantByFullJID(localOccupantToRestore.getRealJID());
                        if (localOccupantRole == null) {
                            Log.trace("Trying to add occupant '{}' but no role for that occupant exists in the local room. Data inconsistency?", localOccupantToRestore.getRealJID());
                            continue;
                        } else {
                            Log.trace("Found localOccupantRole {} for localOccupantToRestore {}, client route = {}", localOccupantRole, localOccupantToRestore.getRealJID(), XMPPServer.getInstance().getRoutingTable().getClientRoute(localOccupantToRestore.getRealJID()));
                        }
                        // OF-2165
                        // Check if the nickname of this occupant already existed for another user in the room.
                        // If it did, we need to kick the users out. With sincere apologies.
                        String nickBeingAddedToRoom = localOccupantRole.getNickname();
                        boolean occupantWasKicked = false;
                        try {
                            final List<MUCRole> existingOccupantsWithSameNick = roomInCluster.getOccupantsByNickname(nickBeingAddedToRoom);
                            final List<JID> otherUsersWithSameNick = existingOccupantsWithSameNick.stream().map(MUCRole::getUserAddress).filter(bareJid -> !bareJid.equals(localOccupantRole.getUserAddress())).collect(Collectors.toList());
                            if (!otherUsersWithSameNick.isEmpty()) {
                                // We will be routing presences to several users. The routing table may not have
                                // finished updating the client routes. However those are needed for routing the
                                // stanzas, specifically the local client route. So do that first.
                                RoutingTable routingTable = XMPPServer.getInstance().getRoutingTable();
                                if (routingTable instanceof RoutingTableImpl) {
                                    RoutingTableImpl.class.cast(routingTable).addLocalClientRoutesToCache();
                                }
                                // There is at least one remote occupant, being a different user, with the same nick.
                                // Kick all.
                                otherUsersWithSameNick.forEach(jid -> kickOccupantBecauseOfNicknameCollision(roomInCluster, nickBeingAddedToRoom, jid, occupantManager));
                                final JID localUserToBeKickedFullJid = localOccupantToRestore.getRealJID();
                                // Now kick the local user. It has to be added to the room for a short instant so that it can actually be kicked out.
                                // Normally we would do this with:
                                // roomInCluster.addOccupantRole(localOccupantRole);
                                // But that notifies other nodes as well about the new occupant. We don't want that, this is
                                // entirely a local affair. Therefore perform two separate steps instead, without invoking
                                // occupant joined events.
                                roomInCluster.occupants.add(localOccupantRole);
                                occupantManager.registerOccupantJoinedLocally(localOccupantRole.getRoleAddress().asBareJID(), localOccupantRole.getUserAddress(), localOccupantRole.getNickname());
                                // Just added. Now kick out.
                                kickOccupantBecauseOfNicknameCollision(roomInCluster, nickBeingAddedToRoom, localUserToBeKickedFullJid, occupantManager);
                                // Inform other nodes of the kick, so they can remove the occupants from their occupant registration
                                occupantManager.occupantNickKicked(roomInCluster.getJID(), nickBeingAddedToRoom);
                                occupantWasKicked = true;
                            }
                        } catch (UserNotFoundException e) {
                        // This is actually the happy path. There is no remote occupant in the room with the same nick. Proceed.
                        }
                        if (!occupantWasKicked) {
                            roomInCluster.addOccupantRole(localOccupantRole);
                        } else {
                            occupantsToRetain.remove(localOccupantToRestore);
                        }
                    }
                }
                if (!roomInCluster.equals(localRoom)) {
                    // TODO: unsure if #equals() is enough to verify equality here.
                    Log.warn("Joined an Openfire cluster on which a room exists that clashes with a room that exists locally. Room name: '{}' on service '{}'", roomName, serviceName);
                // TODO: handle collision. Two nodes have different rooms using the same name.
                }
                // Sync room back to make cluster aware of changes.
                Log.debug("Re-added local room '{}' to cache, with occupants: {}", roomName, roomInCluster.getOccupants().stream().map(MUCRole::getUserAddress).map(JID::toString).collect(Collectors.joining(", ")));
                ROOM_CACHE.put(roomName, roomInCluster);
            // TODO: update the local copy of the room with occupants, maybe?
            }
        } finally {
            lock.unlock();
        }
    }
    // Add a cluster listener to clean up locally stored data when another cluster node removes it from the cache.
    ROOM_CACHE.addClusteredCacheEntryListener(new ClusteredCacheEntryListener<String, MUCRoom>() {

        @Override
        public void entryAdded(@Nonnull String key, @Nullable MUCRoom newValue, @Nonnull NodeID nodeID) {
        }

        @Override
        public void entryRemoved(@Nonnull String key, @Nullable MUCRoom oldValue, @Nonnull NodeID nodeID) {
            localRooms.remove(key);
            final MultiUserChatService service = XMPPServer.getInstance().getMultiUserChatManager().getMultiUserChatService(serviceName);
            if (service != null) {
                service.getOccupantManager().roomDestroyed(new JID(key, service.getServiceDomain(), null));
            }
        }

        @Override
        public void entryUpdated(@Nonnull String key, @Nullable MUCRoom oldValue, @Nullable MUCRoom newValue, @Nonnull NodeID nodeID) {
        }

        @Override
        public void entryEvicted(@Nonnull String key, @Nullable MUCRoom oldValue, @Nonnull NodeID nodeID) {
            localRooms.remove(key);
            final MultiUserChatService service = XMPPServer.getInstance().getMultiUserChatManager().getMultiUserChatService(serviceName);
            if (service != null) {
                service.getOccupantManager().roomDestroyed(new JID(key, service.getServiceDomain(), null));
            }
        }

        @Override
        public void mapCleared(@Nonnull NodeID nodeID) {
        }

        @Override
        public void mapEvicted(@Nonnull NodeID nodeID) {
        }
    }, false, false);
    return occupantsToRetain;
}
Also used : Presence(org.xmpp.packet.Presence) GroupEventDispatcher(org.jivesoftware.openfire.event.GroupEventDispatcher) RoutingTableImpl(org.jivesoftware.openfire.spi.RoutingTableImpl) Date(java.util.Date) MultiUserChatService(org.jivesoftware.openfire.muc.MultiUserChatService) CacheFactory(org.jivesoftware.util.cache.CacheFactory) ClusteredCacheEntryListener(org.jivesoftware.openfire.cluster.ClusteredCacheEntryListener) LoggerFactory(org.slf4j.LoggerFactory) NotAllowedException(org.jivesoftware.openfire.muc.NotAllowedException) HashMap(java.util.HashMap) JID(org.xmpp.packet.JID) HashSet(java.util.HashSet) NodeID(org.jivesoftware.openfire.cluster.NodeID) Duration(java.time.Duration) Map(java.util.Map) XMPPServer(org.jivesoftware.openfire.XMPPServer) Nonnull(javax.annotation.Nonnull) Nullable(javax.annotation.Nullable) Cache(org.jivesoftware.util.cache.Cache) RoutingTable(org.jivesoftware.openfire.RoutingTable) Logger(org.slf4j.Logger) Collection(java.util.Collection) MUCRoom(org.jivesoftware.openfire.muc.MUCRoom) Set(java.util.Set) Collectors(java.util.stream.Collectors) UserNotFoundException(org.jivesoftware.openfire.user.UserNotFoundException) MUCRole(org.jivesoftware.openfire.muc.MUCRole) List(java.util.List) Lock(java.util.concurrent.locks.Lock) Collections(java.util.Collections) UserNotFoundException(org.jivesoftware.openfire.user.UserNotFoundException) MultiUserChatService(org.jivesoftware.openfire.muc.MultiUserChatService) MUCRole(org.jivesoftware.openfire.muc.MUCRole) NodeID(org.jivesoftware.openfire.cluster.NodeID) List(java.util.List) HashSet(java.util.HashSet) JID(org.xmpp.packet.JID) RoutingTableImpl(org.jivesoftware.openfire.spi.RoutingTableImpl) Lock(java.util.concurrent.locks.Lock) MUCRoom(org.jivesoftware.openfire.muc.MUCRoom) RoutingTable(org.jivesoftware.openfire.RoutingTable) HashMap(java.util.HashMap) Map(java.util.Map)

Example 9 with MultiUserChatService

use of org.jivesoftware.openfire.muc.MultiUserChatService in project Openfire by igniterealtime.

the class AbstractXepSupport method start.

public void start() {
    for (IQHandler iqHandler : iqHandlers) {
        try {
            iqHandler.initialize(server);
            iqHandler.start();
        } catch (Exception e) {
            Log.error("Unable to initialize and start " + iqHandler.getClass());
            continue;
        }
        element2Handlers.put(iqHandler.getInfo().getName(), iqHandler);
        if (iqHandler instanceof ServerFeaturesProvider) {
            for (Iterator<String> i = ((ServerFeaturesProvider) iqHandler).getFeatures(); i.hasNext(); ) {
                server.getIQDiscoInfoHandler().addServerFeature(i.next());
            }
        }
        if (muc) {
            MultiUserChatManager manager = server.getMultiUserChatManager();
            for (MultiUserChatService mucService : manager.getMultiUserChatServices()) {
                mucService.addIQHandler(iqHandler);
                mucService.addExtraFeature(namespace);
            }
        }
    }
    server.getIQDiscoInfoHandler().addServerFeature(namespace);
    server.getIQRouter().addHandler(iqDispatcher);
}
Also used : IQHandler(org.jivesoftware.openfire.handler.IQHandler) MultiUserChatManager(org.jivesoftware.openfire.muc.MultiUserChatManager) MultiUserChatService(org.jivesoftware.openfire.muc.MultiUserChatService) ServerFeaturesProvider(org.jivesoftware.openfire.disco.ServerFeaturesProvider) UnauthorizedException(org.jivesoftware.openfire.auth.UnauthorizedException)

Example 10 with MultiUserChatService

use of org.jivesoftware.openfire.muc.MultiUserChatService in project Openfire by igniterealtime.

the class AbstractXepSupport method stop.

public void stop() {
    IQRouter iqRouter = server.getIQRouter();
    IQDiscoInfoHandler iqDiscoInfoHandler = server.getIQDiscoInfoHandler();
    for (IQHandler iqHandler : iqHandlers) {
        element2Handlers.remove(iqHandler.getInfo().getName());
        try {
            iqHandler.stop();
            iqHandler.destroy();
        } catch (Exception e) {
            Log.warn("Unable to stop and destroy " + iqHandler.getClass());
        }
        if (iqHandler instanceof ServerFeaturesProvider) {
            for (Iterator<String> i = ((ServerFeaturesProvider) iqHandler).getFeatures(); i.hasNext(); ) {
                if (iqDiscoInfoHandler != null) {
                    iqDiscoInfoHandler.removeServerFeature(i.next());
                }
            }
        }
        if (muc) {
            MultiUserChatManager manager = server.getMultiUserChatManager();
            for (MultiUserChatService mucService : manager.getMultiUserChatServices()) {
                mucService.removeIQHandler(iqHandler);
                mucService.removeExtraFeature(namespace);
            }
        }
    }
    if (iqRouter != null) {
        iqRouter.removeHandler(iqDispatcher);
    }
}
Also used : IQDiscoInfoHandler(org.jivesoftware.openfire.disco.IQDiscoInfoHandler) IQHandler(org.jivesoftware.openfire.handler.IQHandler) MultiUserChatManager(org.jivesoftware.openfire.muc.MultiUserChatManager) MultiUserChatService(org.jivesoftware.openfire.muc.MultiUserChatService) ServerFeaturesProvider(org.jivesoftware.openfire.disco.ServerFeaturesProvider) IQRouter(org.jivesoftware.openfire.IQRouter) UnauthorizedException(org.jivesoftware.openfire.auth.UnauthorizedException)

Aggregations

MultiUserChatService (org.jivesoftware.openfire.muc.MultiUserChatService)17 MUCRoom (org.jivesoftware.openfire.muc.MUCRoom)5 MUCRole (org.jivesoftware.openfire.muc.MUCRole)3 MultiUserChatManager (org.jivesoftware.openfire.muc.MultiUserChatManager)3 MultiUserChatServiceImpl (org.jivesoftware.openfire.muc.spi.MultiUserChatServiceImpl)3 JID (org.xmpp.packet.JID)3 ArchivedMessage (com.reucon.openfire.plugin.archive.model.ArchivedMessage)2 Date (java.util.Date)2 List (java.util.List)2 Lock (java.util.concurrent.locks.Lock)2 UnauthorizedException (org.jivesoftware.openfire.auth.UnauthorizedException)2 ServerFeaturesProvider (org.jivesoftware.openfire.disco.ServerFeaturesProvider)2 IQHandler (org.jivesoftware.openfire.handler.IQHandler)2 NotAllowedException (org.jivesoftware.openfire.muc.NotAllowedException)2 LocalMUCRoom (org.jivesoftware.openfire.muc.spi.LocalMUCRoom)2 XmppResultSet (com.reucon.openfire.plugin.archive.xep0059.XmppResultSet)1 Connection (java.sql.Connection)1 PreparedStatement (java.sql.PreparedStatement)1 ResultSet (java.sql.ResultSet)1 SQLException (java.sql.SQLException)1