All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.red5.net.websocket.WebSocketScope Maven / Gradle / Ivy

/*
 * RED5 Open Source Flash Server - https://github.com/red5 Copyright 2006-2018 by respective authors (see below). All rights reserved. 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.
 */

package org.red5.net.websocket;

import java.util.Collection;
import java.util.Collections;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;

import org.red5.net.websocket.listener.IWebSocketDataListener;
import org.red5.net.websocket.model.WSMessage;
import org.red5.server.api.scope.IScope;
import org.red5.server.plugin.PluginRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;

/**
 * WebSocketScope contains an IScope and keeps track of WebSocketConnection and IWebSocketDataListener instances.
 * 
 * @author Paul Gregoire ([email protected])
 */
public class WebSocketScope implements InitializingBean, DisposableBean {

    private static Logger log = LoggerFactory.getLogger(WebSocketScope.class);

    protected CopyOnWriteArraySet conns = new CopyOnWriteArraySet<>();

    protected CopyOnWriteArraySet listeners = new CopyOnWriteArraySet<>();

    protected IScope scope;

    protected String path = "default";

    public WebSocketScope() {
    }

    public WebSocketScope(IScope scope) {
        log.debug("Creating WebSocket scope for: {}", scope);
        setScope(scope);
        setPath(String.format("/%s", scope.getName()));
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        register();
    }

    @Override
    public void destroy() throws Exception {
        unregister();
    }

    /**
     * Registers with the WebSocketScopeManager.
     */
    public void register() {
        log.info("Application scope: {}", scope);
        WebSocketScopeManager manager = ((WebSocketPlugin) PluginRegistry.getPlugin(WebSocketPlugin.NAME)).getManager(scope);
        if (manager.setApplication(scope)) {
            log.info("WebSocket app added: {}", scope.getName());
        }
        if (manager.addWebSocketScope(this)) {
            log.info("WebSocket scope added");
        }
    }

    /**
     * Un-registers from the WebSocketScopeManager.
     */
    public void unregister() {
        // clean up the connections by first closing them
        conns.forEach(conn -> {
            conn.close();
        });
        conns.clear();
        // clean up the listeners by first stopping them
        listeners.forEach(listener -> {
            listener.stop();
        });
        listeners.clear();
    }

    /**
     * Returns a connection matching the given HttpSession id.
     * 
     * @param id
     * @return WebSocketConnection for the given id or null if not found
     */
    public WebSocketConnection getConnectionBySessionId(String id) {
        Optional opt = conns.stream().filter(conn -> id.equals(conn.getHttpSessionId())).findFirst();
        if (opt.isPresent()) {
            return opt.get();
        }
        return null;
    }

    /**
     * Returns the set of connections.
     * 
     * @return conns
     */
    public Set getConns() {
        return conns;
    }

    /**
     * Returns the associated scope.
     * 
     * @return scope
     */
    public IScope getScope() {
        return scope;
    }

    /**
     * Sets the associated scope.
     * 
     * @param scope
     */
    public void setScope(IScope scope) {
        this.scope = scope;
        // set this ws scope as an attribute for ez lookup
        this.scope.setAttribute(WSConstants.WS_SCOPE, this);
    }

    /**
     * Sets the path.
     * 
     * @param path
     */
    public void setPath(String path) {
        this.path = path; // /room/name
    }

    /**
     * Returns the path of the scope.
     * 
     * @return path
     */
    public String getPath() {
        return path;
    }

    /**
     * Add new connection on scope.
     * 
     * @param conn WebSocketConnection
     */
    public void addConnection(WebSocketConnection conn) {
        if (conns.add(conn)) {
            for (IWebSocketDataListener listener : listeners) {
                listener.onWSConnect(conn);
            }
        } else {
            log.warn("Add connection failed for: {}", conn);
        }
    }

    /**
     * Remove connection from scope.
     * 
     * @param conn WebSocketConnection
     */
    public void removeConnection(WebSocketConnection conn) {
        if (conns.remove(conn)) {
            for (IWebSocketDataListener listener : listeners) {
                listener.onWSDisconnect(conn);
            }
        } else {
            log.warn("Remove connection failed for: {}", conn);
        }
    }

    /**
     * Add new listener on scope.
     * 
     * @param listener IWebSocketDataListener
     */
    public void addListener(IWebSocketDataListener listener) {
        log.info("addListener: {}", listener);
        listeners.add(listener);
    }

    /**
     * Remove listener from scope.
     * 
     * @param listener IWebSocketDataListener
     */
    public void removeListener(IWebSocketDataListener listener) {
        log.info("removeListener: {}", listener);
        listeners.remove(listener);
    }

    /**
     * Add new listeners on scope.
     * 
     * @param listeners
     *            list of IWebSocketDataListener
     */
    public void setListeners(Collection listeners) {
        log.trace("setListeners: {}", listeners);
        this.listeners.addAll(listeners);
    }

    /**
     * Returns the listeners in an unmodifiable set.
     * 
     * @return listeners
     */
    public Set getListeners() {
        return Collections.unmodifiableSet(listeners);
    }

    /**
     * Checks for a listener by class type.
     * 
     * @param clazz
     * @return true if one exists and false otherwise
     */
    public boolean hasListener(Class clazz) {
        return listeners.stream().filter(listener -> listener.getClass().isInstance(clazz)).findFirst().isPresent();
    }

    /**
     * Check the scope state.
     * 
     * @return true:still have relation
     */
    public boolean isValid() {
        return (conns.size() + listeners.size()) > 0;
    }

    /**
     * Message received from client and passed on to the listeners.
     * 
     * @param message
     */
    public void onMessage(WSMessage message) {
        log.trace("Listeners: {}", listeners.size());
        listeners.forEach(listener -> {
            try {
                listener.onWSMessage(message);
            } catch (Exception e) {
                log.warn("onMessage exception", e);
            }
        });
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((path == null) ? 0 : path.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        WebSocketScope other = (WebSocketScope) obj;
        if (path == null) {
            if (other.path != null)
                return false;
        } else if (!path.equals(other.path))
            return false;
        return true;
    }

    @Override
    public String toString() {
        return "WebSocketScope [path=" + path + ", listeners=" + listeners.size() + ", connections=" + conns.size() + "]";
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy