/*
* CallSbb.java
*
* The source code contained in this file is in in the public domain.
* It can be used in any project or product without prior permission,
* license or royalty payments. There is NO WARRANTY OF ANY KIND,
* EXPRESS, IMPLIED OR STATUTORY, INCLUDING, WITHOUT LIMITATION,
* THE IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
* AND DATA ACCURACY. We do not warrant or make any representations
* regarding the use of the software or the results thereof, including
* but not limited to the correctness, accuracy, reliability or
* usefulness of the software.
*/
package org.mobicents.mgcp.demo;
import jain.protocol.ip.mgcp.JainMgcpEvent;
import jain.protocol.ip.mgcp.message.CreateConnection;
import jain.protocol.ip.mgcp.message.CreateConnectionResponse;
import jain.protocol.ip.mgcp.message.DeleteConnection;
import jain.protocol.ip.mgcp.message.parms.CallIdentifier;
import jain.protocol.ip.mgcp.message.parms.ConflictingParameterException;
import jain.protocol.ip.mgcp.message.parms.ConnectionDescriptor;
import jain.protocol.ip.mgcp.message.parms.ConnectionIdentifier;
import jain.protocol.ip.mgcp.message.parms.ConnectionMode;
import jain.protocol.ip.mgcp.message.parms.EndpointIdentifier;
import jain.protocol.ip.mgcp.message.parms.ReturnCode;
import java.text.ParseException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sip.Dialog;
import javax.sip.InvalidArgumentException;
import javax.sip.RequestEvent;
import javax.sip.ServerTransaction;
import javax.sip.SipException;
import javax.sip.address.Address;
import javax.sip.address.AddressFactory;
import javax.sip.header.ContactHeader;
import javax.sip.header.ContentTypeHeader;
import javax.sip.header.FromHeader;
import javax.sip.header.HeaderFactory;
import javax.sip.header.ToHeader;
import javax.sip.message.MessageFactory;
import javax.sip.message.Request;
import javax.sip.message.Response;
import javax.slee.ActivityContextInterface;
import javax.slee.CreateException;
import javax.slee.FactoryException;
import javax.slee.RolledBackContext;
import javax.slee.Sbb;
import javax.slee.SbbContext;
import javax.slee.UnrecognizedActivityException;
import javax.slee.facilities.Tracer;
import net.java.slee.resource.mgcp.JainMgcpProvider;
import net.java.slee.resource.mgcp.MgcpActivityContextInterfaceFactory;
import net.java.slee.resource.mgcp.MgcpConnectionActivity;
import net.java.slee.resource.sip.DialogActivity;
import net.java.slee.resource.sip.SipActivityContextInterfaceFactory;
import net.java.slee.resource.sip.SleeSipProvider;
/**
* On INVITE this example creates the Connection on endpoint media/test/Loopback/1. On BYE it calls DeleteConnection on
* endpoint media/test/Loopback/1 without passing the ConnectionIdentifier
*
* @author amit.bhayani
*/
public abstract class CRCXEndpointSbb implements Sbb {
private static int CALL_ID_GEN = 1;
private static int GEN = 1000;
public final static String JBOSS_BIND_ADDRESS = System.getProperty("jboss.bind.address", "127.0.0.1");
public final static String ENDPOINT_NAME = "media/test/trunk/Loopback/$";
private SbbContext sbbContext;
// SIP
private SleeSipProvider provider;
private AddressFactory addressFactory;
private HeaderFactory headerFactory;
private MessageFactory messageFactory;
private SipActivityContextInterfaceFactory acif;
// MGCP
private JainMgcpProvider mgcpProvider;
private MgcpActivityContextInterfaceFactory mgcpAcif;
private Tracer logger;
/** Creates a new instance of CallSbb */
public CRCXEndpointSbb() {
}
public void onCallCreated(RequestEvent evt, ActivityContextInterface aci) {
Request request = evt.getRequest();
FromHeader from = (FromHeader) request.getHeader(FromHeader.NAME);
ToHeader to = (ToHeader) request.getHeader(ToHeader.NAME);
logger.info("Incoming call " + from + " " + to);
// create Dialog and attach SBB to the Dialog Activity
ActivityContextInterface daci = null;
try {
Dialog dialog = provider.getNewDialog(evt.getServerTransaction());
dialog.terminateOnBye(true);
daci = acif.getActivityContextInterface((DialogActivity) dialog);
daci.attach(sbbContext.getSbbLocalObject());
} catch (Exception e) {
logger.severe("Error during dialog creation", e);
respond(evt, Response.SERVER_INTERNAL_ERROR);
return;
}
// respond(evt, Response.RINGING);
CallIdentifier callID = new CallIdentifier(Integer.toHexString(CALL_ID_GEN++));
EndpointIdentifier endpointID = new EndpointIdentifier(ENDPOINT_NAME, JBOSS_BIND_ADDRESS + ":2729");
CreateConnection createConnection = new CreateConnection(this, callID, endpointID, ConnectionMode.SendRecv);
try {
String sdp = new String(evt.getRequest().getRawContent());
createConnection.setRemoteConnectionDescriptor(new ConnectionDescriptor(sdp));
} catch (ConflictingParameterException e) {
// should never happen
}
int txID = GEN++;
createConnection.setTransactionHandle(txID);
MgcpConnectionActivity connectionActivity = null;
try {
connectionActivity = mgcpProvider.getConnectionActivity(txID, endpointID);
ActivityContextInterface epnAci = mgcpAcif.getActivityContextInterface(connectionActivity);
epnAci.attach(sbbContext.getSbbLocalObject());
} catch (FactoryException ex) {
ex.printStackTrace();
} catch (NullPointerException ex) {
ex.printStackTrace();
} catch (UnrecognizedActivityException ex) {
ex.printStackTrace();
}
mgcpProvider.sendMgcpEvents(new JainMgcpEvent[] { createConnection });
}
public void onCreateConnectionResponse(CreateConnectionResponse event, ActivityContextInterface aci) {
logger.info("Receive CRCX response: " + event.getTransactionHandle());
ServerTransaction txn = getServerTransaction();
Request request = txn.getRequest();
ReturnCode status = event.getReturnCode();
switch (status.getValue()) {
case ReturnCode.TRANSACTION_EXECUTED_NORMALLY:
this.setConnectionIdentifier(event.getConnectionIdentifier().toString());
String sdp = event.getLocalConnectionDescriptor().toString();
ContentTypeHeader contentType = null;
try {
contentType = headerFactory.createContentTypeHeader("application", "sdp");
} catch (ParseException ex) {
}
String localAddress = provider.getListeningPoints()[0].getIPAddress();
int localPort = provider.getListeningPoints()[0].getPort();
Address contactAddress = null;
try {
contactAddress = addressFactory.createAddress("sip:" + localAddress + ":" + localPort);
} catch (ParseException ex) {
}
ContactHeader contact = headerFactory.createContactHeader(contactAddress);
Response response = null;
try {
response = messageFactory.createResponse(Response.OK, request, contentType, sdp.getBytes());
} catch (ParseException ex) {
}
response.setHeader(contact);
try {
txn.sendResponse(response);
} catch (InvalidArgumentException ex) {
} catch (SipException ex) {
}
break;
default:
try {
response = messageFactory.createResponse(Response.SERVER_INTERNAL_ERROR, request);
txn.sendResponse(response);
} catch (Exception ex) {
}
}
}
public void onCallTerminated(RequestEvent evt, ActivityContextInterface aci) {
try {
// EndpointIdentifier endpointID = new EndpointIdentifier(ENDPOINT_NAME, JBOSS_BIND_ADDRESS+":2729");
EndpointIdentifier endpointID = getMgcpConnectionActivity().getEndpointIdentifier();
DeleteConnection deleteConnection = new DeleteConnection(this, endpointID);
int txID = GEN++;
deleteConnection.setTransactionHandle(txID);
mgcpProvider.sendMgcpEvents(new JainMgcpEvent[] { deleteConnection });
// Since DLCX is for Endpoint, we need to explicitly clean the
// MgcpConnectionActivity for each of the CRCX
MgcpConnectionActivity mgcpConnectionActivity = mgcpProvider.getConnectionActivity(
new ConnectionIdentifier(this.getConnectionIdentifier()), endpointID);
mgcpConnectionActivity.release();
ServerTransaction tx = evt.getServerTransaction();
Request request = evt.getRequest();
Response response = messageFactory.createResponse(Response.OK, request);
tx.sendResponse(response);
} catch (Exception e) {
}
}
private void respond(RequestEvent evt, int cause) {
Request request = evt.getRequest();
ServerTransaction tx = evt.getServerTransaction();
try {
Response response = messageFactory.createResponse(cause, request);
tx.sendResponse(response);
} catch (Exception e) {
logger.warning("Unexpected error: ", e);
}
}
private ServerTransaction getServerTransaction() {
ActivityContextInterface[] activities = sbbContext.getActivities();
for (ActivityContextInterface activity : activities) {
if (activity.getActivity() instanceof ServerTransaction) {
return (ServerTransaction) activity.getActivity();
}
}
return null;
}
private Dialog getDialog() {
ActivityContextInterface[] activities = sbbContext.getActivities();
for (ActivityContextInterface activity : activities) {
if (activity.getActivity() instanceof Dialog) {
return (Dialog) activity.getActivity();
}
}
return null;
}
private MgcpConnectionActivity getMgcpConnectionActivity() {
ActivityContextInterface[] activities = sbbContext.getActivities();
for (ActivityContextInterface activity : activities) {
if (activity.getActivity() instanceof MgcpConnectionActivity) {
return (MgcpConnectionActivity) activity.getActivity();
}
}
return null;
}
public void setSbbContext(SbbContext sbbContext) {
this.sbbContext = sbbContext;
this.logger = sbbContext.getTracer(CRCXEndpointSbb.class.getSimpleName());
try {
Context ctx = (Context) new InitialContext().lookup("java:comp/env");
// initialize SIP API
provider = (SleeSipProvider) ctx.lookup("slee/resources/jainsip/1.2/provider");
addressFactory = provider.getAddressFactory();
headerFactory = provider.getHeaderFactory();
messageFactory = provider.getMessageFactory();
acif = (SipActivityContextInterfaceFactory) ctx.lookup("slee/resources/jainsip/1.2/acifactory");
// initialize media api
mgcpProvider = (JainMgcpProvider) ctx.lookup("slee/resources/jainmgcp/2.0/provider/demo");
mgcpAcif = (MgcpActivityContextInterfaceFactory) ctx.lookup("slee/resources/jainmgcp/2.0/acifactory/demo");
} catch (Exception ne) {
logger.severe("Could not set SBB context:", ne);
}
}
public abstract String getConnectionIdentifier();
public abstract void setConnectionIdentifier(String connectionIdentifier);
public void unsetSbbContext() {
this.sbbContext = null;
this.logger = null;
}
public void sbbCreate() throws CreateException {
}
public void sbbPostCreate() throws CreateException {
}
public void sbbActivate() {
}
public void sbbPassivate() {
}
public void sbbLoad() {
}
public void sbbStore() {
}
public void sbbRemove() {
}
public void sbbExceptionThrown(Exception exception, Object object, ActivityContextInterface activityContextInterface) {
}
public void sbbRolledBack(RolledBackContext rolledBackContext) {
}
}