JBoss.orgCommunity Documentation

Chapter 2. Resource Adaptor Type

2.1. Activities
2.2. Events
2.3. Activity Context Interface Factory
2.4. Resource Adaptor Interface
2.5. Restrictions
2.6. Sbb Code Examples

MGCP Resource Adaptor Type is defined by Mobicents team as part of effort to standardize RA Types.

An MGCP activity object represents a set of related events in an MGCP resource. This Ra Type defines the following Activity objects:

MgcpConnectionActivity

The set of MGCP events regarding the managing (creation, modification, destruction and state audit) of a MGCP connection is represented by this activity object. This activity ends implicitly when a DeleteConnection (MGCP server role) or DeleteConnectionResponse (MGCP Call Agent role) event is received. MGCP events related to Signal generation or Event detection request for specific connection are also represented by this Activity. Class name is net.java.slee.resource.mgcp.MgcpConnectionActivity

New MgcpConnectionActivity Activity objects are created by calling JainMgcpProvider.getConnectionActivity(int transactionHandle, EndpointIdentifier endpointIdentifier) or JainMgcpProvider.getConnectionActivity(ConnectionIdentifier connectionIdentifier, EndpointIdentifier endpointIdentifier)

JainMgcpProvider.getConnectionActivity(int transactionHandle, EndpointIdentifier endpointIdentifier) is mostly used by Application behaving as Media Gateway Controller or MGCP call Agent Role. The above method is called to create a new MgcpConnectionActivity for unknown ConnectionIdentifier , to be used when sending CreateConnection events and receive further related messages from a MGCP Server.

MgcpConnectionActivity Activity objects are created automatically when the resource adaptor receives an incoming MGCP request (MGCP server role).

MgcpEndpointActivity

The set of MGCP events regarding a MGCP endpoint, such as event detecting/signal generation or configuration/state audit, is represented by this activity object. Since a MGCP endpoint doesn't have a lifecyle this activity does not end implicitly on MGCP events. Class name is net.java.slee.resource.mgcp.MgcpConnectionActivity

New MgcpEndpointActivity Activity objects is created by calling JainMgcpProvider.public MgcpEndpointActivity getEndpointActivity(EndpointIdentifier endpointIdentifier);

MgcpEndpointActivity Activity objects are created automatically when the resource adaptor receives an incoming MGCP request on an Endpoint (MGCP server role).

Events represent MGCP Requests or Responses received by the MGCP stack (incoming requests and responses) and Timer expiry. Each MGCP Requests is fired as different event types. Each MGCP Response is fired as different event types. Events are fired on MgcpConnectionActivity or MgcpEndpointActivity activities. There are several event types defined. Following is the table that describes event-type (name, vendor and version), event-class and whether its fired on MgcpConnectionActivity or MgcpEndpointActivity or both.

Table 2.1. Events fired by MGCP

NameEvent ClassConnEnpComments
CREATE_ CONNECTION Create Connection YesNo Received by application acting as MGCP Server.
CREATE_ CONNECTION_ RESPONSE Create Connection Respone YesNo Received by application acting as MGCP Call Agent
MODIFY_ CONNECTION Modify Connection YesNo Received by application acting as MGCP Server
MODIFY_ CONNECTION_ RESPONSE Modify Connection Response YesNo Received by application acting as MGCP Call Agent
DELETE_ CONNECTION Delete Connection YesYes Received by application acting as MGCP Server
DELETE_ CONNECTION_ RESPONSE Delete Connection Response YesYes Received by application acting as MGCP Call Agent
AUDIT_ CONNECTION Audit Connection YesNo Received by application acting as MGCP Server
AUDIT_ CONNECTION_ RESPONSE Audit Connection Response YesNo Received by application acting as MGCP Call Agent
NOTIFICATION_ REQUEST Notification Request YesYes Received by application acting as MGCP Server. Whether this event will be fired on MgcpConnectionActivity or MgcpEndpointActivity Activity is decided by RA depending on if EventName (Request/Signal) has ConnectionIdentifier included or not. If Request/Signal has list of EventName's with few having ConnectionIdentifier set and few without ConnectionIdentifier, then this event will be fired on both the Activities. However please note that new Activity Object/s will not be created unless initial-event="True" is specified in sbb-jar.xml for this event-type.
NOTIFICATION_ REQUEST_ RESPONSE Notification Request Response YesYes Received by application acting as MGCP Call Agent. If EventName (Signal/Request) in original NotificationRequest fired by this Application had ConnectionIdentifier set, then this event will be fired on MgcpConnectionActivity. If Request/Signal has list of EventName's with few having ConnectionIdentifier set and few without ConnectionIdentifier, then this event will be fired on both the Activities. However please note that event's will be fired only on existing Activty Object and no new Activity Object will be created unless initial-event="True" is specified in sbb-jar.xml.
NOTIFY Notify YesYes Received by application acting as MGCP Call Agent. Whether this event will be fired on MgcpConnectionActivity or MgcpEndpointActivity Activity is decided by RA depending on if event is detected on connection or endpoint (ConnectionIdentifier included or not)
NOTIFY_ RESPONSE Notify Response YesYes Received by application acting as MGCP Server. Whether this event will be fired on MgcpConnectionActivity or MgcpEndpointActivity Activity is decided by RA depending on if original Notify event is detected on connection or endpoint (ConnectionIdentifier included or not)
TRANSACTION_ TIMEOUT event. Transaction Timeout YesYes Received by application acting as MGCP Server or MGCP Call Agent. Basically this is fired when Application sends the MGCP Request but there is no response. The activity ends automatically.
AUDIT_ ENDPOINT Audit Endpoint NoYes Received by application acting as MGCP Server.
AUDIT_ ENDPOINT_ RESPONSE Audit Endpoint Response NoYes Received by application acting as MGCP Call Agent.
ENDPOINT_ CONFIGURATION Endpoint Configuration NoYes Received by application acting as MGCP Server.
ENDPOINT_ CONFIGURATION_ RESPONSE Endpoint Configuration Response NoYes Received by application acting as MGCP Call Agent.
RESTART_ IN_ PROGRESS Restart In Progress NoYes Received by application acting as MGCP Call Agent.
RESTART_ IN_ PROGRESS_ RESPONSE Restart In Progress Response NoYes Received by application acting as MGCP Server.

The interface of the JAIN MGCP resource adaptor type specific Activity Context Interface Factory is defined as follows:

	

package net.java.slee.resource.mgcp;

import javax.slee.ActivityContextInterface;
import javax.slee.FactoryException;
import javax.slee.UnrecognizedActivityException;


public interface MgcpActivityContextInterfaceFactory {


    public ActivityContextInterface getActivityContextInterface(MgcpEndpointActivity activity)
        throws NullPointerException, UnrecognizedActivityException, FactoryException;
    

    public ActivityContextInterface getActivityContextInterface(MgcpConnectionActivity activity)
        throws NullPointerException, UnrecognizedActivityException, FactoryException;
    
}
	
	

The JAIN MGCP Resource Adaptor SBB Interface provides SBBs with access to the JAIN MGCP objects required for creating and sending Request/Response. It is defined as follows:

	package net.java.slee.resource.mgcp;

import jain.protocol.ip.mgcp.message.CreateConnection;
import jain.protocol.ip.mgcp.message.NotificationRequest;
import jain.protocol.ip.mgcp.message.parms.CallIdentifier;
import jain.protocol.ip.mgcp.message.parms.ConnectionIdentifier;
import jain.protocol.ip.mgcp.message.parms.EndpointIdentifier;
import jain.protocol.ip.mgcp.message.parms.RequestIdentifier;

import java.util.List;


public interface JainMgcpProvider extends jain.protocol.ip.mgcp.JainMgcpProvider {
	
	public MgcpConnectionActivity getConnectionActivity(ConnectionIdentifier connectionIdentifier, EndpointIdentifier endpointIdentifier);
	
	public MgcpConnectionActivity getConnectionActivity(int transactionHandle, EndpointIdentifier endpointIdentifier);
	
	public List MgcpConnectionActivity getConnectionActivities(EndpointIdentifier endpointIdentifier);
	
	public MgcpEndpointActivity getEndpointActivity(EndpointIdentifier endpointIdentifier);
	
	public int getUniqueTransactionHandler();
	
	public CallIdentifier getUniqueCallIdentifier();
	
	public RequestIdentifier getUniqueRequestIdentifier();
	
}
	
	

The resource adaptor implementation should prevent SBBs from adding themselves as MGCP listeners, or changing the MGCP network configuration. Any attempt to do so should be rejected by throwing a SecurityException.

The following code shows how MGCP Call Agent can send CreateConnection request to MGCP Server

public abstract class IVRSbb implements Sbb {

	public final static String ENDPOINT_NAME = "/mobicents/media/IVR/$";
	
	
	//SIP Invite received. Send CRCX to MGCP Server
	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);

		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;
		}

		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 });
	}
	
	//Received CRCX Response. Now Send RQNT for playing media file
	public void onCreateConnectionResponse(CreateConnectionResponse event, ActivityContextInterface aci) {

		ServerTransaction txn = getServerTransaction();
		Request request = txn.getRequest();

		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();

			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);

			sendRQNT(WELCOME, true);

			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);
			}
		}
	}

	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");
	}

	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());

			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) {
			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");
	
				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;
			}
		}
	}

	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);
		}
	}


}