/*
* RED5 Open Source Flash Server - http://code.google.com/p/red5/
*
* Copyright 2006-2012 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.server.net.mrtmp;
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();
}
}
}