package org.restcomm.javax.media.mscontrol.networkconnection;
import jain.protocol.ip.mgcp.message.parms.ConnectionIdentifier;
import jain.protocol.ip.mgcp.message.parms.EndpointIdentifier;
import java.util.Iterator;
import java.util.concurrent.CopyOnWriteArrayList;
import javax.media.mscontrol.MediaConfig;
import javax.media.mscontrol.MediaErr;
import javax.media.mscontrol.MediaEvent;
import javax.media.mscontrol.MediaEventListener;
import javax.media.mscontrol.MediaObject;
import javax.media.mscontrol.MsControlException;
import javax.media.mscontrol.networkconnection.NetworkConnection;
import javax.media.mscontrol.networkconnection.SdpPortManager;
import javax.media.mscontrol.networkconnection.SdpPortManagerEvent;
import javax.media.mscontrol.resource.Action;
import javax.media.mscontrol.resource.AllocationEventListener;
import org.restcomm.fsm.FSM;
import org.restcomm.fsm.Logger;
import org.restcomm.fsm.UnknownTransitionException;
import org.restcomm.javax.media.mscontrol.MediaConfigImpl;
import org.restcomm.javax.media.mscontrol.MediaSessionImpl;
import org.restcomm.javax.media.mscontrol.container.ContainerImpl;
import org.restcomm.javax.media.mscontrol.container.Endpoint;
import org.restcomm.javax.media.mscontrol.networkconnection.fsm.ConnectionState;
import org.restcomm.javax.media.mscontrol.networkconnection.fsm.ConnectionTransition;
/**
*
* @author amit bhayani
*
*/
public final class NetworkConnectionImpl extends ContainerImpl implements NetworkConnection, Logger {
//Configuration pattern related to NetworkConnection.BASE
public final static MediaConfig BASE_CONFIG = new BaseConfig().getConfig();
protected SdpPortManagerImpl sdpPortManager = null;
// protected EndpointIdentifier endpointName;
protected ConnectionIdentifier connectionID;
private CopyOnWriteArrayList<MediaEventListener<? extends MediaEvent<?>>> listeners =
new CopyOnWriteArrayList<MediaEventListener<? extends MediaEvent<?>>>();
//FSM processor
protected FSM fsm;
//last error occured
protected MediaErr error = MediaErr.NO_ERROR;
protected String errorMsg;
public NetworkConnectionImpl(MediaSessionImpl session, MediaConfigImpl config) throws MsControlException {
super(session, config.getParameters());
this.config = config;
//determine endpoint local name
String localName = (String)config.getValue(ENDPOINT_NAME);
//domain name of the server is constructed using proprties from config
String domainName = session.getDriver().getRemoteDomainName();
//finally, the endpoint identifier is constructed
// endpointName = new EndpointIdentifier(localName, domainName);
endpoint = new Endpoint(new EndpointIdentifier(localName, domainName));
maxJoinees = 1;
sdpPortManager = new SdpPortManagerImpl(this);
this.init();
}
protected void init() {
fsm = new FSM(session.getDriver().getScheduler());
fsm.setLogger(this);
fsm.createState(ConnectionState.NULL);
fsm.createState(ConnectionState.OPENING);
fsm.createState(ConnectionState.OPEN);
fsm.createState(ConnectionState.CANCELED);
fsm.createState(ConnectionState.HALF_OPEN);
fsm.createState(ConnectionState.MODIFYING);
fsm.createState(ConnectionState.CLOSING).setOnEnter(
new DeleteConnectionRequest(this));
fsm.createState(ConnectionState.FAILED).setOnEnter(
new SdpPortManagerEventImpl(sdpPortManager, SdpPortManagerEvent.NETWORK_STREAM_FAILURE));
fsm.createState(ConnectionState.INVALID);
fsm.setStart(ConnectionState.NULL);
fsm.setEnd(ConnectionState.INVALID);
//******************************************************************/
// STATE NULL /
//******************************************************************/
//transition from NULL to OPENING
fsm.createTransition(ConnectionTransition.OPEN,
ConnectionState.NULL, ConnectionState.OPENING).setHandler(
new CreateConnectionRequest(this));
fsm.createTransition(ConnectionTransition.CLOSE,
ConnectionState.NULL, ConnectionState.INVALID);
//******************************************************************/
// STATE OPENING /
//******************************************************************/
//transition from OPENING to OPEN
fsm.createTransition(ConnectionTransition.OPENED,
ConnectionState.OPENING, ConnectionState.OPEN).setHandler(
new SdpPortManagerEventImpl(sdpPortManager, SdpPortManagerEvent.ANSWER_GENERATED));
//transition from OPENING to HALF_OPEN
fsm.createTransition(ConnectionTransition.CREATED,
ConnectionState.OPENING, ConnectionState.HALF_OPEN).setHandler(
new SdpPortManagerEventImpl(sdpPortManager, SdpPortManagerEvent.OFFER_GENERATED));
//transition from OPENING to CANCELED
fsm.createTransition(ConnectionTransition.CLOSE,
ConnectionState.OPENING, ConnectionState.CANCELED);
//transition from OPENING to FAILED
fsm.createTransition(ConnectionTransition.FAILURE,
ConnectionState.OPENING, ConnectionState.FAILED);
//transition from OPENING to FAILED
fsm.createTimeoutTransition(
ConnectionState.OPENING, ConnectionState.FAILED, 5000).setHandler(
new TimeoutError(this));
//******************************************************************/
// STATE OPENED /
//******************************************************************/
//transition to CLOSING
fsm.createTransition(ConnectionTransition.CLOSE,
ConnectionState.OPEN, ConnectionState.CLOSING);
//******************************************************************/
// STATE HALF_OPEN /
//******************************************************************/
//transition to MODIFYING
fsm.createTransition(ConnectionTransition.MODIFY,
ConnectionState.HALF_OPEN, ConnectionState.MODIFYING).setHandler(
new ModifyConnectionRequest(this));
//transition to CLOSING
fsm.createTransition(ConnectionTransition.CLOSE,
ConnectionState.HALF_OPEN, ConnectionState.CLOSING);
//******************************************************************/
// STATE MODIFYING /
//******************************************************************/
//transition to OPEN
fsm.createTransition(
ConnectionTransition.OPENED,
ConnectionState.MODIFYING, ConnectionState.OPEN).setHandler(
new SdpPortManagerEventImpl(sdpPortManager, SdpPortManagerEvent.ANSWER_PROCESSED));
//transition to FAILED
fsm.createTransition(
ConnectionTransition.FAILURE,
ConnectionState.MODIFYING, ConnectionState.FAILED);
//transition to CLOSING
fsm.createTransition(ConnectionTransition.CLOSE,
ConnectionState.MODIFYING, ConnectionState.CLOSING);
fsm.createTimeoutTransition(
ConnectionState.MODIFYING, ConnectionState.FAILED, 5000).setHandler(
new TimeoutError(this));
//******************************************************************/
// STATE CANCELED /
//******************************************************************/
//transition to CLOSING upon OPENED signal
fsm.createTransition(ConnectionTransition.OPENED,
ConnectionState.CANCELED, ConnectionState.CLOSING);
//transition to CLOSING upon CREATED signal
fsm.createTransition(ConnectionTransition.CREATED,
ConnectionState.CANCELED, ConnectionState.CLOSING);
fsm.createTransition(ConnectionTransition.CLOSE,
ConnectionState.CANCELED, ConnectionState.CANCELED);
//transition to CLOSING without signals
fsm.createTimeoutTransition(
ConnectionState.CANCELED, ConnectionState.INVALID, 5000);
//******************************************************************/
// STATE CLOSING /
//******************************************************************/
fsm.createTransition(ConnectionTransition.CLOSE,
ConnectionState.CLOSING, ConnectionState.CLOSING);
//signal from server
fsm.createTransition(ConnectionTransition.CLOSED,
ConnectionState.CLOSING, ConnectionState.INVALID);
//failure signal from server (TODO: try to resent signal again)
fsm.createTransition(ConnectionTransition.FAILURE,
ConnectionState.CLOSING, ConnectionState.INVALID);
//no signals from server
fsm.createTimeoutTransition(
ConnectionState.CLOSING, ConnectionState.INVALID, 5000);
//******************************************************************/
// STATE FAILED /
//******************************************************************/
fsm.createTransition(ConnectionTransition.CLOSE,
ConnectionState.FAILED, ConnectionState.CLOSING);
//******************************************************************/
// STATE INVALID /
//******************************************************************/
fsm.createTransition(ConnectionTransition.CLOSE,
ConnectionState.INVALID, ConnectionState.INVALID);
}
protected ConnectionIdentifier getConnectionID() {
return connectionID;
}
protected void setConnectionID(ConnectionIdentifier connectionID) {
this.connectionID = connectionID;
}
public SdpPortManager getSdpPortManager() throws MsControlException {
return sdpPortManager;
}
public void confirm() throws MsControlException {
throw new MsControlException("Operation not yet supported");
}
public MediaConfig getConfig() {
return this.config;
}
public <R> R getResource(Class<R> paramClass) throws MsControlException {
// TODO Auto-generated method stub
return null;
}
public void triggerRTC(Action paramAction) {
// TODO Auto-generated method stub
}
public Iterator<MediaObject> getMediaObjects() {
// TODO Auto-generated method stub
return null;
}
public <T extends MediaObject> Iterator<T> getMediaObjects(Class<T> paramClass) {
// TODO Auto-generated method stub
return null;
}
public void release() {
info("Releasing....");
//send signal to all local connections
try {
this.unjoin();
} catch (Exception e) {
e.printStackTrace();
}
//send signal to network connection
try {
fsm.signal(ConnectionTransition.CLOSE);
} catch (UnknownTransitionException e) {
e.printStackTrace();
}
}
public void addListener(AllocationEventListener listener) {
}
public void removeListener(AllocationEventListener listener) {
// TODO Auto-generated method stub
}
public void triggerAction(Action action) {
throw new UnsupportedOperationException("Not supported yet.");
}
}