package org.red5.server.net.mrtmp; /* * RED5 Open Source Flash Server - http://www.osflash.org/red5 * * Copyright (c) 2006-2009 by respective authors (see below). All rights reserved. * * This library is free software; you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free Software * Foundation; either version 2.1 of the License, or (at your option) any later * version. * * This library is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License along * with this library; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.Map.Entry; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.red5.server.api.IConnection; import org.red5.server.net.rtmp.RTMPConnection; import org.red5.server.net.rtmp.RTMPOriginConnection; /** * @author Steven Gong (steven.gong@gmail.com) */ public class SimpleMRTMPOriginManager implements IMRTMPOriginManager { private static final Logger log = LoggerFactory.getLogger(SimpleMRTMPOriginManager.class); private ReadWriteLock lock = new ReentrantReadWriteLock(); private Set<IMRTMPConnection> connSet = new HashSet<IMRTMPConnection>(); private Map<RTMPConnection, IMRTMPConnection> clientToConnMap; private OriginMRTMPHandler originMRTMPHandler; public SimpleMRTMPOriginManager() { // XXX Use HashMap instead of WeakHashMap temporarily // to avoid package routing issue before Terracotta // integration. clientToConnMap = Collections.synchronizedMap( new HashMap<RTMPConnection, IMRTMPConnection>()); } public void setOriginMRTMPHandler(OriginMRTMPHandler originMRTMPHandler) { this.originMRTMPHandler = originMRTMPHandler; } public boolean registerConnection(IMRTMPConnection conn) { lock.writeLock().lock(); try { return connSet.add(conn); } finally { lock.writeLock().unlock(); } } public boolean unregisterConnection(IMRTMPConnection conn) { boolean ret; ArrayList<RTMPConnection> list = new ArrayList<RTMPConnection>(); lock.writeLock().lock(); try { ret = connSet.remove(conn); if (ret) { for (Iterator<Entry<RTMPConnection, IMRTMPConnection>> iter = clientToConnMap.entrySet().iterator(); iter.hasNext(); ) { Entry<RTMPConnection, IMRTMPConnection> entry = iter.next(); if (entry.getValue() == conn) { list.add(entry.getKey()); } } } } finally { lock.writeLock().unlock(); } // close all RTMPOriginConnections for (RTMPConnection rtmpConn : list) { log.debug("Close RTMPOriginConnection " + rtmpConn.getId() + " due to MRTMP Connection closed!"); originMRTMPHandler.closeConnection((RTMPOriginConnection) rtmpConn); } return ret; } public void associate(RTMPConnection rtmpConn, IMRTMPConnection mrtmpConn) { clientToConnMap.put(rtmpConn, mrtmpConn); } public void dissociate(RTMPConnection rtmpConn) { clientToConnMap.remove(rtmpConn); } public IMRTMPConnection lookupMRTMPConnection(RTMPConnection rtmpConn) { lock.readLock().lock(); try { IMRTMPConnection conn = clientToConnMap.get(rtmpConn); if (conn != null && !connSet.contains(conn)) { clientToConnMap.remove(rtmpConn); conn = null; } // mrtmp connection not found, we locate the next mrtmp connection // when the connection is not persistent. if (conn == null && !rtmpConn.getType().equals(IConnection.PERSISTENT)) { if (connSet.size() > 0) { conn = connSet.iterator().next(); } } // TODO handle conn == null case return conn; } finally { lock.readLock().unlock(); } } }