/*
* 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.NotificationRequest;
import jain.protocol.ip.mgcp.message.NotificationRequestResponse;
import jain.protocol.ip.mgcp.message.Notify;
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.EventName;
import jain.protocol.ip.mgcp.message.parms.NotifiedEntity;
import jain.protocol.ip.mgcp.message.parms.RequestedAction;
import jain.protocol.ip.mgcp.message.parms.RequestedEvent;
import jain.protocol.ip.mgcp.message.parms.ReturnCode;
import jain.protocol.ip.mgcp.pkg.MgcpEvent;
import jain.protocol.ip.mgcp.pkg.PackageName;
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.mgcp.MgcpEndpointActivity;
import net.java.slee.resource.sip.DialogActivity;
import net.java.slee.resource.sip.SipActivityContextInterfaceFactory;
import net.java.slee.resource.sip.SleeSipProvider;
/**
*
* @author amit.bhayani
*/
public abstract class RQNTSbb implements Sbb {
public final static String ENDPOINT_NAME = "/mobicents/media/IVR/$";
public final static String JBOSS_BIND_ADDRESS = System.getProperty("jboss.bind.address", "127.0.0.1");
public final static String HELLO_WORLD = "http://" + JBOSS_BIND_ADDRESS + ":8080/mgcpdemo/audio/RQNT-ULAW.wav";
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;
public static final int MGCP_PEER_PORT = 2427;
public static final int MGCP_PORT = 2727;
private Tracer logger;
/** Creates a new instance of CallSbb */
public RQNTSbb() {
}
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 = mgcpProvider.getUniqueCallIdentifier();
this.setCallIdentifier(callID.toString());
EndpointIdentifier endpointID = new EndpointIdentifier(ENDPOINT_NAME, JBOSS_BIND_ADDRESS + ":" + MGCP_PEER_PORT);
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 = mgcpProvider.getUniqueTransactionHandler();
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.setEndpointName(event.getSpecificEndpointIdentifier().getLocalEndpointName());
logger.info("***&& " + this.getEndpointName());
ConnectionIdentifier connectionIdentifier = event.getConnectionIdentifier();
this.setConnectionIdentifier(connectionIdentifier.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);
EndpointIdentifier endpointID = new EndpointIdentifier(this.getEndpointName(), JBOSS_BIND_ADDRESS + ":"
+ MGCP_PEER_PORT);
NotificationRequest notificationRequest = new NotificationRequest(this, endpointID, mgcpProvider
.getUniqueRequestIdentifier());
EventName[] signalRequests = { new EventName(PackageName.Announcement, MgcpEvent.ann.withParm(HELLO_WORLD)) };
notificationRequest.setSignalRequests(signalRequests);
RequestedAction[] actions = new RequestedAction[] { RequestedAction.NotifyImmediately };
RequestedEvent[] requestedEvents = {
new RequestedEvent(new EventName(PackageName.Announcement, MgcpEvent.oc), actions),
new RequestedEvent(new EventName(PackageName.Announcement, MgcpEvent.of), actions) };
notificationRequest.setRequestedEvents(requestedEvents);
notificationRequest.setTransactionHandle(mgcpProvider.getUniqueTransactionHandler());
NotifiedEntity notifiedEntity = new NotifiedEntity(JBOSS_BIND_ADDRESS, JBOSS_BIND_ADDRESS, MGCP_PORT);
notificationRequest.setNotifiedEntity(notifiedEntity);
MgcpEndpointActivity endpointActivity = null;
try {
endpointActivity = mgcpProvider.getEndpointActivity(endpointID);
ActivityContextInterface epnAci = mgcpAcif.getActivityContextInterface(endpointActivity);
epnAci.attach(sbbContext.getSbbLocalObject());
} catch (FactoryException ex) {
ex.printStackTrace();
} catch (NullPointerException ex) {
ex.printStackTrace();
} catch (UnrecognizedActivityException ex) {
ex.printStackTrace();
}
mgcpProvider.sendMgcpEvents(new JainMgcpEvent[] { notificationRequest });
logger.info(" NotificationRequest sent");
Response response = null;
try {
response = messageFactory.createResponse(Response.OK, request, contentType, sdp.getBytes());
} catch (ParseException ex) {
logger.severe("ParseException while trying to create OK Response", ex);
}
response.setHeader(contact);
try {
txn.sendResponse(response);
} catch (InvalidArgumentException ex) {
logger.severe("InvalidArgumentException while trying to send OK Response", ex);
} catch (SipException ex) {
logger.severe("SipException while trying to send OK Response", ex);
}
break;
default:
try {
response = messageFactory.createResponse(Response.SERVER_INTERNAL_ERROR, request);
txn.sendResponse(response);
} catch (Exception ex) {
logger.severe("Exception while trying to send SERVER_INTERNAL_ERROR Response", ex);
}
}
}
public void onNotificationRequestResponse(NotificationRequestResponse event, ActivityContextInterface aci) {
logger.info("onNotificationRequestResponse");
ReturnCode status = event.getReturnCode();
switch (status.getValue()) {
case ReturnCode.TRANSACTION_EXECUTED_NORMALLY:
logger.info("The Announcement should have been started");
break;
default:
ReturnCode rc = event.getReturnCode();
logger.severe("RQNT failed. Value = " + rc.getValue() + " Comment = " + rc.getComment());
// TODO : Send DLCX to MMS. Send BYE to UA
break;
}
}
public void onNotifyRequest(Notify event, ActivityContextInterface aci) {
logger.info("onNotifyRequest");
NotificationRequestResponse response = new NotificationRequestResponse(event.getSource(),
ReturnCode.Transaction_Executed_Normally);
response.setTransactionHandle(event.getTransactionHandle());
mgcpProvider.sendMgcpEvents(new JainMgcpEvent[] { response });
EventName[] observedEvents = event.getObservedEvents();
for (EventName observedEvent : observedEvents) {
if (observedEvent.getEventIdentifier().intValue() == MgcpEvent.REPORT_ON_COMPLETION) {
logger.info("Announcemnet Completed NTFY received");
} else if (observedEvent.getEventIdentifier().intValue() == MgcpEvent.REPORT_FAILURE) {
logger.info("Announcemnet Failed received");
// TODO : Send DLCX and Send BYE to UA
}
}
}
// public void onTransactionTimeout(TransactionTimeout event, ActivityContextInterface aci) {
// logger.info("onTransactionTimeout");
// }
public void onCallTerminated(RequestEvent evt, ActivityContextInterface aci) {
EndpointIdentifier endpointID = new EndpointIdentifier(this.getEndpointName(), JBOSS_BIND_ADDRESS + ":"
+ MGCP_PEER_PORT);
DeleteConnection deleteConnection = new DeleteConnection(this, new CallIdentifier(this.getCallIdentifier()),
endpointID);
deleteConnection.setTransactionHandle(mgcpProvider.getUniqueTransactionHandler());
mgcpProvider.sendMgcpEvents(new JainMgcpEvent[] { deleteConnection });
ServerTransaction tx = evt.getServerTransaction();
Request request = evt.getRequest();
try {
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;
}
public void setSbbContext(SbbContext sbbContext) {
this.sbbContext = sbbContext;
this.logger = sbbContext.getTracer(RQNTSbb.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 abstract String getCallIdentifier();
public abstract void setCallIdentifier(String CallIdentifier);
public abstract String getRemoteSdp();
public abstract void setRemoteSdp(String remoteSdp);
public abstract String getEndpointName();
public abstract void setEndpointName(String endpointName);
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) {
}
}