The Source for Java Technology Collaboration


Overview

The Media Gateway Control Protocol (MGCP) has been introduced to the IETF (MEGACO working group) for controlling (trunking) gateways that interconnect the Public Switched Telephone Network (PSTN) with packet networks and for controlling (residential) gateways that function as network interfaces for customer premise located equipment (e.g., phones with an RJ-11 jack). MGCP is the result of merging the Simple Gateway Control Protocol (SGCP) and Internet Protocol Device Control (IPDC).

Jain MGCP API implementation

The API specified by the JAIN Protocol Expert Group Java Community Process Participants for MGCP are based on the MGCP Internet Drafts and the Cable Labs PacketCableTM? Network-Based Call Signaling Protocol Specification. Instead of mapping the standard specifications to a Java interface, the JAIN MGCP API specification abstracts a functional definition into the variant protocol stacks.

Building from source code

The propritary implementation of the JAIN MGCP API can be found at https://slee-mgcp-ra.dev.java.net/source/browse/slee-mgcp-ra/slee-mgcp-ra/gateway. Make sure that you have ant installed, switch to project directory and type ant provider

MGCP Resource Adaptor

The resource adaptor is adopted for MGCP control protocol. Resource adaptor type identifier The resource adaptor type name is "JAIN MGCP". The resource adaptor type vendor is "javax.mgcp". The resource adaptor type version is "1.0".

Activity object.

The activity objects for MGCP resource adaptor are org.mobicents.slee.resources.mgcp.Call, org.mobicents.slee.resources.mgcp.Connection objects and org.mobicents.slee.resources.mgcp.Endpoint. The Call object belongs to call which handled by controller, Connection object belongs to connection created on the gateway's side and Endpoint belongs to gateway's endpoint which executes connection.

Events

The following table lists events emitted by Resource Adaptor:

Event Activity Remarks
Call Connection Transaction Identifier
Request Events
jain.protocol.ip.mgcp.message.AUDIT_ENDPOINT     x
jain.protocol.ip.mgcp.message.AUDIT_CONNECTION x
jain.protocol.ip.mgcp.message.CREATE_CONNECTION x
jain.protocol.ip.mgcp.message.MODIFY_CONNECTION x
jain.protocol.ip.mgcp.message.DELETE_CONNECTION x
jain.protocol.ip.mgcp.message.NOTIFICATION_REQUEST x
jain.protocol.ip.mgcp.message.NOTIFY_RESPONSE x
Response Events
jain.protocol.ip.mgcp.message.AUDIT_ENDPOINT_RESPONSE x
jain.protocol.ip.mgcp.message.AUDIT_CONNECTION_RESPONSE x
jain.protocol.ip.mgcp.message.CREATE_CONNECTION_RESPONSE x
jain.protocol.ip.mgcp.message.MODIFY_CONNECTION_RESPONSE x
jain.protocol.ip.mgcp.message.DELETE_CONNECTION_RESPONSE x
jain.protocol.ip.mgcp.message.NOTIFICATION_REQUEST_RESPONSE x
jain.protocol.ip.mgcp.message.NOTIFY x x x

Event types

The event type is a message name with package prefix jain.protocol.ip.mgcp.message, the event type vendor is jain.mgcp and version is 1.1

Event classes.

The JAIN MGCP define an event class for all avents.

Activity Context Interface Factory Interface

The Activity Context Interface Factory Interface looks :
import javax.slee.ActivityContextInterface;
import javax.slee.FactoryException;
import javax.slee.UnrecognizedActivityException;

public interface RadiusActivityContextInterfaceFactory {
    public ActivityContextInterface getActivityContextInterface(CallIdentifier callID)
        throws NullPointerException, UnrecognizedActivityException, FactoryException;
    
    public ActivityContextInterface getActivityContextInterface(ConnectionIdentifier connectionID)
        throws NullPointerException, UnrecognizedActivityException, FactoryException;

    public ActivityContextInterface getActivityContextInterface(Integer txID)
        throws NullPointerException, UnrecognizedActivityException, FactoryException;

}

Resource Adaptor object

The JAIN MGCP requeires one object for creating and sendong messages: JainMgcpProvider

Source code

The source code for RA Type can be found at https://slee-mgcp-ra.dev.java.net/source/browse/slee-mgcp-ra/slee-mgcp-ra/ratype

The source code for RA can be found at https://slee-mgcp-ra.dev.java.net/source/browse/slee-mgcp-ra/slee-mgcp-ra/ra

Examples

Conference service for this example is a preset telephone number that multiples callers can access simultaneously. Conference calls for participants are handled via the conference bridge deployed on the media gateway. In this example MGCP will be used for conference management. We will assume that ConfSBB? wich handles is not a root sbb and receive initial event related to preset number 800.

The Activity objects for this service will be SIP tx, Conference session, and MGCP tx. When user dial a conference service number , the incoming call causes SIP tx to be created. The SBB should construct a new CallIdentifier? object and invoke a media gateway's conference brige to create a new conference call. Sinse the invocation process is asynchronous, SBB should create MGCP transaction handle activity object also.

Joining to a conference

First, the conference service relays set up progress messages -- Trying, then constructs uniquie name of the conference using the header "To". Next step it looks up this name in int Activity Context Name Facility.

    public void onInviteEvent(RequestEvent evt, ActivityContextInterface aci) {
        ...
        String confName = getConfName(evt.getRequest());
        ConfSbbActivityContextInterface conf = getConfActivityContext(confName);
        ... 
    }

If this name is not ready bound to an Activity Context, then the ConfSbb? creates a new CallIdentifier? object which will reperesent conference session and invokes the MgcpActivityContextFactory? to obtain Activity Context for the conference. Then SBB entity bind Activity Context using unique name of the conference session. This activity starts when first participant is connected to a conference bridge and will end when last participant leave conference. It means that this activity may hold attributes related to the conference session. When SBB obtain Activity Context for conference session it is ready to create a new connection.

    private void sendCreateConnection(ConfSbbActivityContextInterface conf, RequestEvent invite) {
        CallIdentifier callID = conf.getCallID();
        EndpointIdentifier endpointID = conf.getEndpoint();
        
        CreateConnection createConnection = new CreateConnection(this,
                callID, endpointID, ConnectionMode.SendRecv);
        
        try {
            String sdp = new String(invite.getRequest().getRawContent());
            createConnection.setRemoteConnectionDescriptor(new ConnectionDescriptor(sdp));
        } catch (ConflictingParameterException e) {
            //should never happen
        }
        
        int txID = GEN++;
        createConnection.setTransactionHandle(txID);
        
        ActivityContextInterface tx = null;
        try {
            tx = mgcpAcif.getActivityContextInterface(new Integer(txID));
        } catch (FactoryException ex) {
            ex.printStackTrace();
        } catch (NullPointerException ex) {
            ex.printStackTrace();
        } catch (UnrecognizedActivityException ex) {
            ex.printStackTrace();
        }
        
        asSbbActivityContextInterface(tx).setRequestEvent(invite);
        asSbbActivityContextInterface(tx).setConfActivityContextInterface(conf);
        
        tx.attach(sbbContext.getSbbLocalObject());
        logger.info("Attach SBB to MGCP TX activity");
        
        mgcpProvider.sendMgcpEvents(new JainMgcpEvent[]{createConnection});
    }

Here SBB creates MGCP tx activity object wich is of type Integer and attach itself to transaction's activity activity context. Media gateway receive this request, create new connection and reply back with identifier of created connection and session descriptior. SBB handles response:

    public void onCreateConnectionResponse(CreateConnectionResponse event, ActivityContextInterface aci) throws ParseException {
        logger.info("Receive CRCX response: " + event.getTransactionHandle());
        
        RequestEvent invite = asSbbActivityContextInterface(aci).getRequestEvent();
        ConfSbbActivityContextInterface conf = asSbbActivityContextInterface(aci).getConfActivityContextInterface();
        
        ReturnCode status = event.getReturnCode();
        
        switch (status.getValue()) {
            case ReturnCode.TRANSACTION_EXECUTED_NORMALLY :
                sendOk(invite, event.getLocalConnectionDescriptor().toString());
                logger.info("Sent OK response");
                
                ConnectionIdentifier connectionID = event.getConnectionIdentifier();
                
                append(conf, getLegID(invite.getRequest()), connectionID);
                conf.setEndpoint(event.getSpecificEndpointIdentifier());
                
                break;
            default :
                sendReject(invite);
        }
    }

If transaction is executed normaly (connection created on the media gateway) SBB obtains session descriptor from received response and use this descriptor to create SIP OK message which then will be forwarded to caller. Caller is joined to a call. At this time the identifier of the connection related to the participant is stored in the conference session activity context.

Disconnecting

When one of the participants leave a conference session, the ConfSBB? should instruct the media gateway that it should release all resources previously acquired for the participant and rebuilt other connections to keep correct multiplexion. ConfSBB? obtains conference session Activity Context, extracts endpoint's name, connection identifier related to the participant and sends delete connection message. It is not necessary to handle delete connection response here and MGCP tx activity is not created.
    public void onByeEvent(RequestEvent evt, ActivityContextInterface aci) {        
        String confName = getConfName(evt.getRequest());
        ConfSbbActivityContextInterface conf = getConfActivityContext(confName);
        
        logger.info("Conference name: " +  confName);
        
        ConnectionIdentifier connectionID = remove(conf, getLegID(evt.getRequest()));
        EndpointIdentifier endpointID = conf.getEndpoint();
        CallIdentifier callID = conf.getCallID();
        
        DeleteConnection deleteConnection = new DeleteConnection(this, callID, endpointID, connectionID );
                
        int txID = GEN++;
        
        deleteConnection.setTransactionHandle(txID);
        mgcpProvider.sendMgcpEvents(new JainMgcpEvent[]{deleteConnection});
        
        logger.info("Delete connection " + connectionID + " on " + endpointID);
        
        if (conf.getConnections().isEmpty()) {
            try {
                namingFacility.unbind(confName);
                logger.info("Unbound conference activity: " + confName);
            } catch (Exception ex) {
                logger.warn("Unexpected error. Caused by", ex);
            } 
        }
    }

Media control scenarios with MGCPRA

Basics

Knowing what MGCP and this RA allow one to achieve is one thing. Other is to know how goal can be achieved. Basic use cases for media gateway (besides bridging) that are in our field of interests (as programmers) are:
  • voice mail
  • conferencing
  • tone services access
  • data flow control - for instance recording

Before we can make any decisions on how things should be done we need example deployment of our enviroment:

As You can see we have media gateway (stand alone on the same host or on different, mobicents mgw ). In it we have set of endpoints pairs:

  • IVR - capable of recording media stream
  • CONF - simple media mixer - it duplicates media it receives from one connection and sends it through other
In our SLEE container we have for instance two services - some simple 3PCC and service called ConnectionHijacker. Also we have set of SIP softphones.

Our goal here is to create application that is capable of recording ongoing calls, create conferences, provide voice mail , etc ... simply some kind of ip pbx. Here is diagram of connections we want to achieve for each call - conference or 1 on 1 call:

Softphones are connects to CONF/0 endpoint, which is connected to IVR/0. This is conections schema for scenario in which we record ongoing call. What happens is that CONF/0 is mixing incoming media and resends it. IVR/0 receives this media and records it . If we want to have possiblity to record media media gateway and a CONF/x endpoint has to always be in between communicating nodes.

Now what about creating connections so they have the same schema as on diagram? First we need realize that there are two scenarios for creating call - our 3pcc application does that or one of the participants calls second one. Here are two diagrams describing flow of commands/invocations . Elements shown on them are nto real, they are just an abstraction to help realizez what is going on under the hood.

First we have case where our application starts call:

First our application prepares enviroment ( for instance default behaviour is to record all calls). It creates connections between CONF and IVR endpoint. Later on it follows one of rfc3725 best practice for 3ppc sip flows (number 4) It ensures that participants are wiling to talk, gathers their SDP and uses it to create connections with MGW endpoint (how exactly it is done is described below)

And here we have case when one of participants starts call:

Here situation is slightly different however only begining is different, after certain point flow is the same as in first scenario.

Connecting to endpoints

Now lets see exact flow of messages that creates those connections. Here are two flow diagrams, one for 3PCC case, other for voice mail recording scenario

Here are detailed steps of voice mail scenario:

  1. when service determine that party B is unavailable it creates connection on IVR endpoint.
  2. MGW reply that CRCX tx complted successfuly with SDP of the created connection.
  3. VMail app route OK message to A with SDP of the IVR connection.
  4. VMail app asks IVR endpoint to play a file on its connection. This messages has may params: URL of the file is one of them.
  5. VMail app report that tx is completed
  6. VMail app asks endpoint to notify when DTMF signal will be received (we assume that DTMF carried by media stream). One of the parameter of RQNT message is action - it is an instruction to endpoint what it should to do when requested event will be occured. There are predefined actions - notify imidiately, ignore, etc.
  7. endpoint detect DTMF digit and sends notification, VMail app confirm tx
  8. endpoint detect DTMF digit and sends notification, VMail app confirm tx
  9. VMail asks endpoint to record. URL of file specified as parameter. Endpoint can't determine when record is completed (does A keep silence or talk) but it can determine if the RTP stream broken so developer may request action "notify imidiately" to handle this situation.
  10. VMail asks endpoint to record. URL of file specified as parameter. Endpoint can't determine when record is completed (does A keep silence or talk) but it can determine if the RTP stream broken so developer may request action "notify imidiately" to handle this situation.
  11. A hungs up.
  12. VMail App delete connection.

*Steps 2,3 and 4,5 may be combined in a single tx.

One things needs propably to be cleared. How endpoints are connected to other resources. Each endpoint has a set of connections - each connection in endpoint represents place where endpoint sends media. Each connection is described by some SDP. When we are connection endpoint to for instance softphone we need to create only one connection, however when we connect endpoints with another enpoint , we have to create connection on each endpoint. Here is diagram that will propably make it a lot easier to understand, below is pseudocode (with actual MGCP API used):

TIP CODE: I

        EndpointIdentifier endpointID=new EndpointIdentifier("conf/0","MGW_IP:PORT");
        CreateConnection cc=new CreateConnection(this,callID,endpintID,ConnectionMode.SsendRecv);
        //No second endpoint is specified, we just want to receive ConnectionDescriptor (which has SDP for this connection)
        provider.fire(cc)
TIP CODE: II
        //onCCResponse
        ConnectionDescriptor localDesc=response.getLocalConnectionDescriptor();
        EndpontIdentifier endpointID=new EndpointIdentifier("ivr/0","MGW_IP:PORT");
        CreateConnection cc=new CreateConnection(this,callID,endpintID,ConnectionMode.SsendRecv);
        //Here we pass descrription of conf/0 connection to ivr/0 connection that is to be craeted
        cc.setRemoteConnectionDescriptor(localDesc.toString());

        provider.fire(cc);

        store.setFirstEvent(response);
TIP CODE: III
        //now onCCResponse is called again, now we got reponse from ivr/0, time to update conf/0 connection
        store.setSecondEvent(response);
        CreateConnectionResponse eventB=store.getFirstEvent();
        EndpointIdentifier endpointID=new EndpointIdentifier("conf/0","MGW_IP:PORT");

        ModifyConnection mc=new ModifyConnection(this, callID,endpointID,eventB,getConnectionID);
        mc.setRemoteConnectionDescriptor(response.getLocalConnectionDescriptor().toString());

        provider.fire(mc);

Related Resources

-- Main.kulikoff - 23 Apr 2007

-- Main.baranowb - 05 May 2007

Topic MGCPRA . { Edit | Ref-By | Printable | Diffs r22 < r21 < r20 < r19 < r18 | More }
 XML java.net RSS

Revision r22 - 06 May 2007 - 08:38:23 - Main.baranowb
Parents: WebHome > MobicentsOpenSLEE > MobicentsFAQ > MobicentsMediaGateway