TeleStax.orgCommunity Documentation
The bellow source code is from IVRSbb, it hides SIP related logic and highlights MGCP specific code. In case if you want to look at complete source, please get the source code as explained in Section 2.2.
package org.restcomm.mgcp.demo; ...... public abstract class IVRSbb implements Sbb { public final static String ENDPOINT_NAME = "/restcomm/media/IVR/$"; public final static String JBOSS_BIND_ADDRESS = System.getProperty("jboss.bind.address", "127.0.0.1"); public final static String WELCOME = "http://" + JBOSS_BIND_ADDRESS + ":8080/mgcpdemo/audio/RQNT-ULAW.wav"; ...... private SbbContext sbbContext; ...... // 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 IVRSbb() { } public void onCallCreated(RequestEvent evt, ActivityContextInterface aci) {....... //SIP Related handling ....... // 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 });
} ... .... }
| |
New instance of | |
New instance of | |
New instance of | |
Setting the SDP of User Agent. This is not mandatory. If this is set the Connection created on Endpoint on media gateway will
start sending the media (depending on | |
Set a new transaction for this MGCP Request. | |
Create a new | |
Finally send this |
Once the MGCP command reaches Media Gateway, it replies back and MGCP RA will fire corresponding event.
public void onCreateConnectionResponse(CreateConnectionResponse event, ActivityContextInterface aci) {logger.info("Receive CRCX response: " + event.getTransactionHandle()); ...... .... ReturnCode status = event.getReturnCode();
switch (status.getValue()) { case ReturnCode.TRANSACTION_EXECUTED_NORMALLY: this.setEndpointName(event.getSpecificEndpointIdentifier().getLocalEndpointName());
ConnectionIdentifier connectionIdentifier = event.getConnectionIdentifier();
this.setConnectionIdentifier(connectionIdentifier.toString()); String sdp = event.getLocalConnectionDescriptor().toString();
//Send OK to UA with SDP from media gateway ..... ....... //Play Announcement sendRQNT(WELCOME, false);
..... ...... break; default: //CRCX failed at Media Gateway. Take necessary action
..... } }
MGCP RA will fire the | |
| |
If connection created successfully, | |
If connection created successfully, | |
If connection created successfully, | |
Since the RTP connection is established between UA and Media Gateway, | |
If creation of connection failed for some reason indicated by |
Let us see how NotificationRequest
is used to request Media Gateway to play an Announcement
private void sendRQNT(String mediaPath, boolean createActivity) { EndpointIdentifier endpointID = new EndpointIdentifier(this.getEndpointName(), JBOSS_BIND_ADDRESS + ":" + MGCP_PEER_PORT);NotificationRequest notificationRequest = new NotificationRequest(this, endpointID, mgcpProvider .getUniqueRequestIdentifier());
ConnectionIdentifier connectionIdentifier = new ConnectionIdentifier(this.getConnectionIdentifier());
EventName[] signalRequests = { new EventName(PackageName.Announcement, MgcpEvent.ann.withParm(mediaPath), connectionIdentifier) }; notificationRequest.setSignalRequests(signalRequests);
RequestedAction[] actions = new RequestedAction[] { RequestedAction.NotifyImmediately }; RequestedEvent[] requestedEvents = {
new RequestedEvent(new EventName(PackageName.Announcement, MgcpEvent.oc, connectionIdentifier), actions), new RequestedEvent(new EventName(PackageName.Announcement, MgcpEvent.of, connectionIdentifier), actions), new RequestedEvent(new EventName(PackageName.Dtmf, MgcpEvent.dtmf0, connectionIdentifier), actions), new RequestedEvent(new EventName(PackageName.Dtmf, MgcpEvent.dtmf1, connectionIdentifier), actions), new RequestedEvent(new EventName(PackageName.Dtmf, MgcpEvent.dtmf2, connectionIdentifier), actions), new RequestedEvent(new EventName(PackageName.Dtmf, MgcpEvent.dtmf3, connectionIdentifier), actions), new RequestedEvent(new EventName(PackageName.Dtmf, MgcpEvent.dtmf4, connectionIdentifier), actions), new RequestedEvent(new EventName(PackageName.Dtmf, MgcpEvent.dtmf5, connectionIdentifier), actions), new RequestedEvent(new EventName(PackageName.Dtmf, MgcpEvent.dtmf6, connectionIdentifier), actions), new RequestedEvent(new EventName(PackageName.Dtmf, MgcpEvent.dtmf7, connectionIdentifier), actions), new RequestedEvent(new EventName(PackageName.Dtmf, MgcpEvent.dtmf8, connectionIdentifier), actions), new RequestedEvent(new EventName(PackageName.Dtmf, MgcpEvent.dtmf9, connectionIdentifier), actions), new RequestedEvent(new EventName(PackageName.Dtmf, MgcpEvent.dtmfA, connectionIdentifier), actions), new RequestedEvent(new EventName(PackageName.Dtmf, MgcpEvent.dtmfB, connectionIdentifier), actions), new RequestedEvent(new EventName(PackageName.Dtmf, MgcpEvent.dtmfC, connectionIdentifier), actions), new RequestedEvent(new EventName(PackageName.Dtmf, MgcpEvent.dtmfD, connectionIdentifier), actions), new RequestedEvent(new EventName(PackageName.Dtmf, MgcpEvent.dtmfStar, connectionIdentifier), actions), new RequestedEvent(new EventName(PackageName.Dtmf, MgcpEvent.dtmfHash, connectionIdentifier), actions) }; notificationRequest.setRequestedEvents(requestedEvents); notificationRequest.setTransactionHandle(mgcpProvider.getUniqueTransactionHandler()); NotifiedEntity notifiedEntity = new NotifiedEntity(JBOSS_BIND_ADDRESS, JBOSS_BIND_ADDRESS, MGCP_PORT); notificationRequest.setNotifiedEntity(notifiedEntity); if (createActivity) {
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(); } } // if (createActivity) mgcpProvider.sendMgcpEvents(new JainMgcpEvent[] { notificationRequest });
logger.info(" NotificationRequest sent"); }
The | |
Create a new | |
The | |
The | |
The | |
Since none of the Signals/Events are fired/detected on Endpoint, Endpoint Activity is not created. The above Events when detected would be fired on Connection Activity. | |
Finally send the request to Media Gateway. |
Once Media Gateway receives the NotificationRequest
, it will process the Signals / Events and send back NotificationRequestResponse
which carries ReturnCode
indicating if Signals can be applied or not and Events can be detected or not.
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()); //Send DLCX to MMS. Send BYE to UA break; } }
The Media Gateway will fire the Notify
command to Application when ever it detects any of the above Events
requested by NotificationRequest
public void onNotifyRequest(Notify event, ActivityContextInterface aci) { logger.info("onNotifyRequest"); NotifyResponse response = new NotifyResponse(event.getSource(), ReturnCode.Transaction_Executed_Normally); response.setTransactionHandle(event.getTransactionHandle()); mgcpProvider.sendMgcpEvents(new JainMgcpEvent[] { response });EventName[] observedEvents = event.getObservedEvents();
for (EventName observedEvent : observedEvents) { switch (observedEvent.getEventIdentifier().intValue()) { case MgcpEvent.REPORT_ON_COMPLETION: logger.info("Announcemnet Completed NTFY received"); break; case MgcpEvent.REPORT_FAILURE: logger.info("Announcemnet Failed received"); // TODO : Send DLCX and Send BYE to UA break; case MgcpEvent.DTMF_0: logger.info("You have pressed 0"); sendRQNT(DTMF_0, false); break; case MgcpEvent.DTMF_1: logger.info("You have pressed 1"); sendRQNT(DTMF_1, false); break; case MgcpEvent.DTMF_2: logger.info("You have pressed 2"); sendRQNT(DTMF_2, false); break; case MgcpEvent.DTMF_3: logger.info("You have pressed 3"); sendRQNT(DTMF_3, false); break; case MgcpEvent.DTMF_4: logger.info("You have pressed 4"); sendRQNT(DTMF_4, false); break; case MgcpEvent.DTMF_5: logger.info("You have pressed 5"); sendRQNT(DTMF_5, false); break; case MgcpEvent.DTMF_6: logger.info("You have pressed 6"); sendRQNT(DTMF_6, false); break; case MgcpEvent.DTMF_7: logger.info("You have pressed 7"); sendRQNT(DTMF_7, false); break; case MgcpEvent.DTMF_8: logger.info("You have pressed 8"); sendRQNT(DTMF_8, false); break; case MgcpEvent.DTMF_9: logger.info("You have pressed 9"); sendRQNT(DTMF_9, false); break; case MgcpEvent.DTMF_A: logger.info("You have pressed A"); sendRQNT(A, false); break; case MgcpEvent.DTMF_B: logger.info("You have pressed B"); sendRQNT(B, false); break; case MgcpEvent.DTMF_C: logger.info("You have pressed C"); sendRQNT(C, false); break; case MgcpEvent.DTMF_D: logger.info("You have pressed D"); sendRQNT(D, false); break; case MgcpEvent.DTMF_STAR: logger.info("You have pressed *"); sendRQNT(STAR, false); break; case MgcpEvent.DTMF_HASH: logger.info("You have pressed C"); sendRQNT(POUND, false); break; } } }
Send the | |
The |
Finally when user hangs-up, we need to delete the connection on Endpoint and free the resources
public void onCallTerminated(RequestEvent evt, ActivityContextInterface aci) {EndpointIdentifier endpointID = new EndpointIdentifier(this.getEndpointName(), JBOSS_BIND_ADDRESS + ":" + MGCP_PEER_PORT); DeleteConnection deleteConnection = new DeleteConnection(this, 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) { logger.severe("Error while sending DLCX ", e); } }
The SIP11 RA fires BYE event, slee container calls onCallTerminated method on SBB | |
New |