/*
* Mobicents, Communications Middleware
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party
* contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Middleware LLC.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program 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 distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
*
* Boston, MA 02110-1301 USA
*/
package org.mobicents.media.server.ctrl.mgcp;
import jain.protocol.ip.mgcp.JainMgcpEvent;
import jain.protocol.ip.mgcp.message.Notify;
import jain.protocol.ip.mgcp.message.parms.EndpointIdentifier;
import jain.protocol.ip.mgcp.message.parms.EventName;
import jain.protocol.ip.mgcp.message.parms.NotifiedEntity;
import jain.protocol.ip.mgcp.message.parms.RequestIdentifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.mobicents.media.server.ctrl.mgcp.evt.EventDetector;
import org.mobicents.media.server.ctrl.mgcp.evt.SignalGenerator;
import org.mobicents.media.server.spi.Connection;
import org.mobicents.media.server.spi.ConnectionListener;
import org.mobicents.media.server.spi.ConnectionMode;
import org.mobicents.media.server.spi.ConnectionState;
import org.mobicents.media.server.spi.Endpoint;
/**
*
* @author kulikov
*/
public class Request implements Runnable, ConnectionListener {
private static int txID = 1;
private RequestIdentifier reqID;
private MgcpController controller;
private EndpointIdentifier endpointID;
private Endpoint endpoint;
private ArrayList<Connection> connections = new ArrayList<Connection>();
private NotifiedEntity notifiedEntity;
private HashMap<String, List<EventDetector>> connectionDetectors = new HashMap<String, List<EventDetector>>();
private HashMap<String, List<SignalGenerator>> connectionGenerators = new HashMap<String, List<SignalGenerator>>();
private ArrayList<EventDetector> endpointDetectors = new ArrayList<EventDetector>();
private ArrayList<SignalGenerator> endpointGenerators = new ArrayList<SignalGenerator>();
private HashMap<String, Iterator<SignalGenerator>> connectionSignalQueue = new HashMap<String, Iterator<SignalGenerator>>();
private Iterator<SignalGenerator> endpointSignalQueue;
private HashMap<String, SignalGenerator> activeConnectionSignals = new HashMap<String, SignalGenerator>();
private SignalGenerator activeEndpointSignal;
public Request(MgcpController controller, RequestIdentifier reqID, EndpointIdentifier endpointID,
Endpoint endpoint, NotifiedEntity notifiedEntity) {
this.controller = controller;
this.reqID = reqID;
this.endpointID = endpointID;
this.endpoint = endpoint;
this.notifiedEntity = notifiedEntity;
}
public void append(EventDetector detector, Connection connection) {
detector.setRequest(this);
if (connection == null) {
endpointDetectors.add(detector);
return;
}
if (connectionDetectors.containsKey(connection.getId())) {
connectionDetectors.get(connection.getId()).add(detector);
} else {
ArrayList<EventDetector> list = new ArrayList();
list.add(detector);
connectionDetectors.put(connection.getId(), list);
if (!connections.contains(connection)) {
connection.addListener(this);
connections.add(connection);
}
}
}
public void append(SignalGenerator generator, Connection connection) {
if (connection == null) {
endpointGenerators.add(generator);
return;
}
if (connectionGenerators.containsKey(connection.getId())) {
connectionGenerators.get(connection.getId()).add(generator);
} else {
ArrayList<SignalGenerator> list = new ArrayList();
list.add(generator);
connectionGenerators.put(connection.getId(), list);
if (!connections.contains(connection)) {
connection.addListener(this);
connections.add(connection);
}
}
}
public void run() {
// starting detectors on connections
Collection<List<EventDetector>> detItems = connectionDetectors.values();
for (List<EventDetector> item : detItems) {
for (EventDetector det : item) {
det.start();
}
}
// starting detectors on endpoint
for (EventDetector det : endpointDetectors) {
det.start();
}
// starting first signal from queue for each connection
Set<String> connectionIDs = connectionSignalQueue.keySet();
for (String connectionID : connectionIDs) {
Iterator<SignalGenerator> queue = connectionSignalQueue.get(connectionID);
SignalGenerator gen = queue.next();
activeConnectionSignals.put(connectionID, gen);
gen.start(this);
}
// starting first signal for endpoint
if (endpointSignalQueue.hasNext()) {
activeEndpointSignal = endpointSignalQueue.next();
activeEndpointSignal.start(this);
}
}
public void cancel() {
// stopping detectors on connections
Collection<List<EventDetector>> detItems = connectionDetectors.values();
for (List<EventDetector> item : detItems) {
for (EventDetector det : item) {
det.stop();
}
}
// starting detectors on endpoint
for (EventDetector det : endpointDetectors) {
det.stop();
}
// starting first signal from queue for each connection
Collection<SignalGenerator> signals = activeConnectionSignals.values();
for (SignalGenerator signal : signals) {
signal.cancel();
}
if (activeEndpointSignal != null) {
activeEndpointSignal.cancel();
}
this.connections.clear();
this.endpointDetectors.clear();
this.endpointGenerators.clear();
this.connectionDetectors.clear();
this.connectionGenerators.clear();
this.activeConnectionSignals.clear();
}
private boolean verifyDetectors(Connection connection) {
if (!connectionDetectors.containsKey(connection.getId())) {
return true;
}
Iterator<EventDetector> list = connectionDetectors.get(connection.getId()).iterator();
boolean res = true;
while (res && list.hasNext()) {
res = res & list.next().verify(connection);
}
return res;
}
private boolean verifyGenerators(Connection connection) {
if (!connectionGenerators.containsKey(connection.getId())) {
return true;
}
Iterator<SignalGenerator> list = connectionGenerators.get(connection.getId()).iterator();
boolean res = true;
while (res && list.hasNext()) {
res = res & list.next().verify(connection);
}
if (res) {
connectionSignalQueue.put(connection.getId(), connectionGenerators.get(connection.getId()).iterator());
}
return res;
}
public boolean verifyDetectors() {
Iterator<Connection> list = connections.iterator();
boolean res = true;
while (res && list.hasNext()) {
res = res & this.verifyDetectors(list.next());
}
Iterator<EventDetector> list2 = endpointDetectors.iterator();
while (res && list2.hasNext()) {
res = res & list2.next().verify(endpoint);
}
return res;
}
public boolean verifyGenerators() {
Iterator<Connection> list = connections.iterator();
boolean res = true;
while (res && list.hasNext()) {
res = res & this.verifyGenerators(list.next());
}
Iterator<SignalGenerator> list2 = endpointGenerators.iterator();
while (res && list2.hasNext()) {
res = res & list2.next().verify(endpoint);
}
endpointSignalQueue = endpointGenerators.iterator();
return res;
}
public void onStateChange(Connection connection, ConnectionState oldState) {
if (connection.getState() != ConnectionState.CLOSED) {
return;
}
// shutdown signal queue
connectionSignalQueue.remove(connection.getId());
// shutdown signal generaot list
connectionGenerators.remove(connection.getId());
// terminate current signal
SignalGenerator gen = activeConnectionSignals.get(connection.getId());
if (gen != null) {
gen.cancel();
}
// disable detectors if assigned
connectionDetectors.remove(connection.getId());
List<EventDetector> list = connectionDetectors.remove(connection.getId());
if (list != null) {
for (EventDetector det : list) {
det.stop();
}
}
// remove connection instance if present
connections.remove(connection);
}
public void onModeChange(Connection connection, ConnectionMode oldMode) {
}
public int getTxID() {
txID++;
if (txID == Integer.MAX_VALUE) {
txID = 1;
}
return txID;
}
public void sendNotify(EventName eventName) {
Notify notify = new Notify(this, endpointID, reqID, new EventName[] { eventName });
notify.setNotifiedEntity(notifiedEntity);
notify.setTransactionHandle(txID++);
notify.setRequestIdentifier(reqID);
controller.getMgcpProvider().sendMgcpEvents(new JainMgcpEvent[] { notify });
}
}