JBoss.orgCommunity Documentation

JBoss Communications JAIN SLEE MGCP Resource Adaptor User Guide


This manual uses several conventions to highlight certain words and phrases and draw attention to specific pieces of information.

In PDF and paper editions, this manual uses typefaces drawn from the Liberation Fonts set. The Liberation Fonts set is also used in HTML editions if the set is installed on your system. If not, alternative but equivalent typefaces are displayed. Note: Red Hat Enterprise Linux 5 and later includes the Liberation Fonts set by default.

Four typographic conventions are used to call attention to specific words and phrases. These conventions, and the circumstances they apply to, are as follows.

Mono-spaced Bold

Used to highlight system input, including shell commands, file names and paths. Also used to highlight key caps and key-combinations. For example:

The above includes a file name, a shell command and a key cap, all presented in Mono-spaced Bold and all distinguishable thanks to context.

Key-combinations can be distinguished from key caps by the hyphen connecting each part of a key-combination. For example:

The first sentence highlights the particular key cap to press. The second highlights two sets of three key caps, each set pressed simultaneously.

If source code is discussed, class names, methods, functions, variable names and returned values mentioned within a paragraph will be presented as above, in Mono-spaced Bold. For example:

Proportional Bold

This denotes words or phrases encountered on a system, including application names; dialogue box text; labelled buttons; check-box and radio button labels; menu titles and sub-menu titles. For example:

The above text includes application names; system-wide menu names and items; application-specific menu names; and buttons and text found within a GUI interface, all presented in Proportional Bold and all distinguishable by context.

Note the > shorthand used to indicate traversal through a menu and its sub-menus. This is to avoid the difficult-to-follow 'Select Mouse from the Preferences sub-menu in the System menu of the main menu bar' approach.

Mono-spaced Bold Italic or Proportional Bold Italic

Whether Mono-spaced Bold or Proportional Bold, the addition of Italics indicates replaceable or variable text. Italics denotes text you do not input literally or displayed text that changes depending on circumstance. For example:

Note the words in bold italics above username, domain.name, file-system, package, version and release. Each word is a placeholder, either for text you enter when issuing a command or for text displayed by the system.

Aside from standard usage for presenting the title of a work, italics denotes the first use of a new and important term. For example:

If you find a typographical error in this manual, or if you have thought of a way to make this manual better, we would love to hear from you! Please submit a report in the the Issue Tracker, against the product JBoss Communications JAIN SLEE MGCP Resource Adaptor, or contact the authors.

When submitting a bug report, be sure to mention the manual's identifier: JAIN_SLEE_MGCP_RA_User_Guide

If you have a suggestion for improving the documentation, try to be as specific as possible when describing it. If you have found an error, please include the section number and some of the surrounding text so we can find it easily.

This resource adaptor provides a MGCP API for JAIN SLEE applications, adapting the JAIN MGCP specification - JSR 23. JAIN MGCP is a Java specification for the Media Gateway Control Protocol, as defined by the protocol specs done by the IETF RFC3435.

MGCP assumes a connection model where the basic constructs are endpoints and connections. Endpoints are sources and/or sinks of data and can be physical or virtual.

Connections may be either point to point or multipoint. A point to point connection is an association between two endpoints with the purpose of transmitting data between these endpoints. Once this association is established for both endpoints, data transfer between these endpoints can take place. A multipoint connection is established by connecting the endpoint to a multipoint session.

Both endpoints and connection constructs are available to support all type of MGCP Applications.

Events represent MGCP Request/Response received by the MGCP stack, or failure use cases such as timeouts.

The Activities are the MGCP Connections and Endpoints, which applications in the SLEE may use to send MGCP Requests and Responses, and to receive the events related with incoming Request/Response.

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


}		
		

The RA implementation uses the Mobicents JAIN MGCP Implementation.

There is a single Resource Adaptor Entity created when deploying the Resource Adaptor, named MGCPRA. The MGCPRA entity uses the default Resource Adaptor configuration, specified in Section 3.1, “Configuration”. The MGCPRA entity is also bound to Resource Adaptor Link Name MGCPRA, to use it in an Sbb add the following XML to its descriptor:.



    
        <resource-adaptor-type-binding>
            <resource-adaptor-type-ref>
                <resource-adaptor-type-name>
                    jain-mgcp
                </resource-adaptor-type-name>
                <resource-adaptor-type-vendor>
                    net.java
                </resource-adaptor-type-vendor>
                <resource-adaptor-type-version>
                    2.0
                </resource-adaptor-type-version>
            </resource-adaptor-type-ref>
            <activity-context-interface-factory-name>
                slee/resources/jainmgcp/2.0/acifactory/demo
            </activity-context-interface-factory-name>
            <resource-adaptor-entity-binding>
                <resource-adaptor-object-name>
                    slee/resources/jainmgcp/2.0/provider/demo
                </resource-adaptor-object-name>
                <resource-adaptor-entity-link>
                    MGCPRA
                </resource-adaptor-entity-link>
            </resource-adaptor-entity-binding>
        </resource-adaptor-type-binding>
    
    
    

  1. Downloading the source code

    Use SVN to checkout a specific release source, the base URL is ?, then add the specific release version, lets consider 2.4.0.CR1.

    [usr]$ svn co ?/2.4.0.CR1 slee-ra-mgcp-2.4.0.CR1
  2. Building the source code

    Important

    Maven 2.0.9 (or higher) is used to build the release. Instructions for using Maven2, including install, can be found at http://maven.apache.org

    Use Maven to build the deployable unit binary.

    						[usr]$ cd slee-ra-mgcp-2.4.0.CR1
    						[usr]$ mvn install
    					

    Once the process finishes you should have the deployable-unit jar file in the target directory, if JBoss Communications JAIN SLEE is installed and environment variable JBOSS_HOME is pointing to its underlying JBoss Enterprise Application Platform directory, then the deployable unit jar will also be deployed in the container.

Revision History
Revision 1.0Mon Feb 08 2010Amit Bhayani
Creation of the JBoss Communications JAIN SLEE MGCP RA User Guide.