All Downloads are FREE. Search and download functionalities are using the official Maven repository.

en-US.Chapter-Source_Code_Overview.xml Maven / Gradle / Ivy

There is a newer version: 7.1.13
Show newest version
<?xml version='1.0'?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "JAIN_SLEE_Example_User_Guide.ent">
%BOOK_ENTITIES;
]>

<chapter
	id="source_code_overview">

	<title>Source Code Overview</title>

	<para>The example application is defined by a service descriptor, which refers the included root SBB. </para>

	<important>
		<para>
			To obtain the example's complete source code please refer to
			<xref
				linkend="source_code" />
			.
		</para>
	</important>

	<section
		id="service_descriptor">

		<title>Service Descriptor</title>

		<para>The service descriptor is plain simple, it just defines the service ID, the ID of the root SBB and its default priority. The
			complete XML is:</para>

		<programlisting
			language="XML"
			role="XML"><![CDATA[
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE service-xml PUBLIC 
	"-//Sun Microsystems, Inc.//DTD JAIN SLEE Service 1.1//EN"
    "http://java.sun.com/dtd/slee-service-xml_1_1.dtd">
<service-xml>
    <service>
        <service-name>MsControlDemo</service-name>
        <service-vendor>org.restcomm</service-vendor>
        <service-version>1.0</service-version>
        <root-sbb>
            <sbb-name>CallSbb</sbb-name>
            <sbb-vendor>org.restcomm</sbb-vendor>
            <sbb-version>1.0</sbb-version>
        </root-sbb>
        <default-priority>0</default-priority>
    </service>
</service-xml>

		]]>
		</programlisting>

	</section>
	<section
		id="root_sbb_descriptor">
		<title>Root SBB XML Descriptor</title>
		<para>The Root SBB XML Descriptor has to be provided and match the abstract class code.</para>

		<para>
			First relevant part is the declaration of the
			<literal>sbb-classes</literal>
			element, where the sbb class abstract name must be specified, along with the cmp fields and child relation.:
		</para>
		<programlisting
			language="XML"
			role="XML"><![CDATA[

        <sbb-classes>
            <sbb-abstract-class>
                <sbb-abstract-class-name>CallSbb</sbb-abstract-class-name>
                <cmp-field>
					<cmp-field-name>serverTransactionACI</cmp-field-name>
				</cmp-field>
				<cmp-field>
					<cmp-field-name>dialogACI</cmp-field-name>
				</cmp-field>
				<cmp-field>
					<cmp-field-name>mediaSessionACI</cmp-field-name>
				</cmp-field>
				<cmp-field>
					<cmp-field-name>networkConnectionACI</cmp-field-name>
				</cmp-field>
				<cmp-field>
					<cmp-field-name>mediaGroupACI</cmp-field-name>
				</cmp-field>
            </sbb-abstract-class>
        </sbb-classes>
			]]>
			</programlisting>

		<para>Then the events handled by the SBB must be specified too:</para>
		<programlisting
			language="XML"
			role="XML"><![CDATA[
<event event-direction="Receive" initial-event="True">
            <event-name>Invite</event-name>
            <event-type-ref>
                <event-type-name>javax.sip.message.Request.INVITE</event-type-name>
                <event-type-vendor>net.java.slee</event-type-vendor>
                <event-type-version>1.2</event-type-version>
            </event-type-ref>
            <initial-event-select variable="ActivityContext" />
        </event>
        <event event-direction="Receive" initial-event="False">
            <event-name>AnswerGenerated</event-name>
            <event-type-ref>
                <event-type-name>javax.media.mscontrol.networkconnection.
                	SdpPortManagerEvent.ANSWER_GENERATED</event-type-name>
                <event-type-vendor>org.restcomm</event-type-vendor>
                <event-type-version>1.0</event-type-version>
            </event-type-ref>
        </event>
        <event event-direction="Receive" initial-event="False">
            <event-name>StreamFailure</event-name>
            <event-type-ref>
                <event-type-name>javax.media.mscontrol.networkconnection.
                	SdpPortManagerEvent.NETWORK_STREAM_FAILURE</event-type-name>
                <event-type-vendor>org.restcomm</event-type-vendor>
                <event-type-version>1.0</event-type-version>
            </event-type-ref>
        </event>
        
        <event event-direction="Receive" initial-event="False">
            <event-name>Joined</event-name>
            <event-type-ref>
                <event-type-name>javax.media.mscontrol.join.
                	JoinEvent.JOINED</event-type-name>
                <event-type-vendor>org.restcomm</event-type-vendor>
                <event-type-version>1.0</event-type-version>
            </event-type-ref>
        </event>
        
        <event event-direction="Receive" initial-event="False">
            <event-name>AnnouncementCompleted</event-name>
            <event-type-ref>
                <event-type-name>javax.media.mscontrol.mediagroup.
                	PlayerEvent.PLAY_COMPLETED</event-type-name>
                <event-type-vendor>org.restcomm</event-type-vendor>
                <event-type-version>1.0</event-type-version>
            </event-type-ref>
        </event>
        
        <event event-direction="Receive" initial-event="False">
            <event-name>Disconnect</event-name>
            <event-type-ref>
                <event-type-name>javax.sip.Dialog.BYE</event-type-name>
                <event-type-vendor>net.java.slee</event-type-vendor>
                <event-type-version>1.2</event-type-version>
            </event-type-ref>
        </event>
			]]>
			</programlisting>

		<para>Finally, the  Resource Adaptors must be specified also, otherwise SLEE won't put its SBB Interface in the SBB's JNDI Context:
		</para>
		<programlisting
			language="XML"
			role="XML"><![CDATA[
 <resource-adaptor-type-binding>
            <resource-adaptor-type-ref>
                <resource-adaptor-type-name>
					JAIN SIP
                </resource-adaptor-type-name>
                <resource-adaptor-type-vendor>
					javax.sip
                </resource-adaptor-type-vendor>
                <resource-adaptor-type-version>
					1.2
                </resource-adaptor-type-version>
            </resource-adaptor-type-ref>
            <activity-context-interface-factory-name>
				slee/resources/jainsip/1.2/acifactory
            </activity-context-interface-factory-name>
            <resource-adaptor-entity-binding>
                <resource-adaptor-object-name>
					slee/resources/jainsip/1.2/provider
                </resource-adaptor-object-name>
                <resource-adaptor-entity-link>
					SipRA
                </resource-adaptor-entity-link>
            </resource-adaptor-entity-binding>
        </resource-adaptor-type-binding>
        <resource-adaptor-type-binding>
            <resource-adaptor-type-ref>
                <resource-adaptor-type-name>
					MSC-1.0-RA
                </resource-adaptor-type-name>
                <resource-adaptor-type-vendor>
					org.restcomm
                </resource-adaptor-type-vendor>
                <resource-adaptor-type-version>
					1.0
                </resource-adaptor-type-version>
            </resource-adaptor-type-ref>
            <activity-context-interface-factory-name>
				slee/resources/media/1.0/acifactory
            </activity-context-interface-factory-name>
            <resource-adaptor-entity-binding>
                <resource-adaptor-object-name>
					slee/resources/media/1.0/provider
                </resource-adaptor-object-name>
                <resource-adaptor-entity-link>
					MSCRA
                </resource-adaptor-entity-link>
            </resource-adaptor-entity-binding>
        </resource-adaptor-type-binding>
			]]>
			</programlisting>

	</section>


	<section
		id="root_sbb_abstract_class">
		<title>The Root SBB Abstract Class</title>
		<para>
			The class
			<literal>CallSbb</literal>
			includes all the service logic for the example.
		</para>

		<section
			id="root_sbb_abstract_class_setSbbContext">
			<title>The setSbbContext(SbbContext) method</title>
			<para>
				The
				<literal>javax.slee.SbbObject</literal>
				's
				<literal>setSbbContext(SbbContext)</literal>
				is used by SBBs to store the SBB's context into a class field. The SBB should take the opportunity to also store objects, such as SLEE
				facilities, which are reused by all service logic entities, a.k.a. SbbEntities, and are stored in the JNDI environment.
			</para>

			<para>
				The class fields and
				<literal>setSbbContext(SbbContext)</literal>
				method's and related code:
			</para>
			<programlisting
				language="Java"
				role="JAVA"><![CDATA[
	private SbbContext sbbContext;
	private Tracer tracer;
	private SleeSipProvider sipRaSbbInterface;
	private SipActivityContextInterfaceFactory sipRaAciFactory;
	private MsControlFactory msRaSbbInterface;
	private MsActivityContextInterfaceFactory mscRaAciFactory;
	
	public void setSbbContext(SbbContext sbbContext) {
		this.sbbContext = sbbContext;
		this.tracer = sbbContext.getTracer("MS-Control-DEMO");
		try {
			Context ctx = (Context) new InitialContext()
					.lookup("java:comp/env");
			sipRaSbbInterface = (SleeSipProvider) ctx
					.lookup("slee/resources/jainsip/1.2/provider");
			sipRaAciFactory = (SipActivityContextInterfaceFactory) ctx
					.lookup("slee/resources/jainsip/1.2/acifactory");
			msRaSbbInterface = (MsControlFactory) ctx
					.lookup("slee/resources/media/1.0/provider");
			mscRaAciFactory = (MsActivityContextInterfaceFactory) ctx
					.lookup("slee/resources/media/1.0/acifactory");
		} catch (Exception ne) {
			tracer.severe("Could not set SBB context:", ne);
		}
	}
            	]]>
            	</programlisting>
		</section>

		

		<section
			id="root_sbb_abstract_class_message_event_handler">
			<title>The SIP INVITE event handler</title>
			<para>The SIP INVITE is the starting point of each this example, its responsibility is:</para>

			<itemizedlist>
				<listitem>
					<para>Do the initial SIP session setup, which means create the SIP Dialog and send provisional response.</para>
				</listitem>
				<listitem>
					<para>Do the initial Media session setup, which means create the <literal>MediaSession</literal> object (the session is container for all <literal>MS Control</literal> objects) and create the <literal>NetworkConnection</literal>, which is then provided with the SIP client SDP.</para>
				</listitem>
			</itemizedlist>

			<para>The event handler code:</para>
			<programlisting
				language="Java"
				role="JAVA"><![CDATA[
	/**
	 * Handles the event notifying new SIP session invitation.
	 * 
	 * @param event
	 * @param aci
	 */
	public void onInvite(RequestEvent event, ActivityContextInterface aci) {
		tracer.info("Received new SIP session invitation.");
		try {
			initialSipSessionSetup(event, aci);
		} catch (Exception e) {
			tracer.severe("Failed to do initial sip session setup.", e);
			abortSipSessionSetup();
			return;
		}
		try {
			initialMediaSessionSetup(event.getServerTransaction());
		} catch (Exception e) {
			tracer.severe("Failed to process sip invite", e);
			abortSipSessionSetup();
			abortMediaSessionSetup();
		}
	}
	
	/*
	 * Setup of the media session: creates the media session, creates a network
	 * connection on it and process the client sdp received on SIP
	 */
	private void initialMediaSessionSetup(ServerTransaction serverTransaction)
			throws MsControlException {
		// create media session
		MediaSession session = msRaSbbInterface.createMediaSession();
		ActivityContextInterface mediaSessionACI = mscRaAciFactory
				.getActivityContextInterface(session);
		SbbLocalObject sbbLocalObject = sbbContext.getSbbLocalObject();
		mediaSessionACI.attach(sbbLocalObject);
		// store the media session aci in a cmp shortcut
		setMediaSessionACI(mediaSessionACI);
		tracer.info("Created media session: " + session);
		// create network connection
		NetworkConnection connection = session
				.createNetworkConnection(NetworkConnection.BASIC);
		ActivityContextInterface connectionACI = mscRaAciFactory
				.getActivityContextInterface(connection);
		connectionACI.attach(sbbLocalObject);
		// store the network connection aci in a cmp shortcut
		setNetworkConnectionACI(connectionACI);
		tracer.info("Created network connection: " + connection);
		// process the received sdp
		SdpPortManager sdpManager = connection.getSdpPortManager();
		tracer.info("Created SDP Manager, sending client sdp...");
		sdpManager.processSdpOffer((byte[]) serverTransaction.getRequest()
				.getContent());
	}
	
	/*
	 * Aborts the media session: releases the network connection and the media
	 * session.
	 */
	private void abortMediaSessionSetup() {
		releaseMediaSession();
	}
	
	/*
	 * 
	 */
	private void releaseMediaSession() {
		// get sbb entity local object
		SbbLocalObject sbbLocalObject = sbbContext.getSbbLocalObject();
		// release media group (the ivr) if exists
		ActivityContextInterface mediaGroupACI = getMediaGroupACI();
		if (mediaGroupACI != null) {
			mediaGroupACI.detach(sbbLocalObject);
			try {
				MediaGroup mediaGroup = (MediaGroup) mediaGroupACI
						.getActivity();
				if (mediaGroup != null) {
					mediaGroup.release();
				}
			} catch (Exception e) {
				tracer.severe("failed to abort media network connection.", e);
			}
		}
		// release network connection if exists
		ActivityContextInterface networkConnectionACI = getNetworkConnectionACI();
		if (networkConnectionACI != null) {
			networkConnectionACI.detach(sbbLocalObject);
			try {
				NetworkConnection networkConnection = (NetworkConnection) networkConnectionACI
						.getActivity();
				if (networkConnection != null) {
					networkConnection.release();
				}
			} catch (Exception e) {
				tracer.severe("failed to abort media network connection.", e);
			}
		}
		// release media session if exists
		ActivityContextInterface mediaSessionACI = getMediaSessionACI();
		if (mediaSessionACI != null) {
			mediaSessionACI.detach(sbbLocalObject);
			try {
				MediaSession mediaSession = (MediaSession) mediaSessionACI
						.getActivity();
				if (mediaSession != null) {
					mediaSession.release();
				}
			} catch (Exception e) {
				tracer.severe("failed to abort media session.", e);
			}
		}
	}
            	]]>
				</programlisting>
		</section>

		<section
			id="root_sbb_abstract_class_answer_generated_handler">
			<title>The AnswerGenerated handler</title>
			<para>The <literal>MS Control</literal> AnswerGenerated is sent when Media Server successfully processes <literal>SDP</literal> offer. Event handler code responsibilities are:</para>

			<itemizedlist>
				<listitem>
					<para>Finish the SIP session setup, that is, send the received <literal>SDP</literal> offer back to the sip client.</para>
				</listitem>
				<listitem>
					<para>Finish the Media session setup, that is, create the <literal>MediaGroup IVR</literal> and join it with the <literal>NetworkConnection</literal>.</para>
				</listitem>
			</itemizedlist>

			<para>The event handler code:</para>
			<programlisting
				language="Java"
				role="JAVA"><![CDATA[
	/**
	 * Event with the media server generated sdp, send it back to the sip
	 * client.
	 * 
	 * @param event
	 * @param aci
	 */
	public void onAnswerGenerated(SdpPortManagerEvent event,
			ActivityContextInterface aci) {
		tracer.info("Received SDP answer.");
		try {
			finishSipSessionSetup(event.getMediaServerSdp());
		} catch (Exception e) {
			tracer.severe("Unable to send OK response with generated SDP", e);
			abortSipSessionSetup();
			abortMediaSessionSetup();
			return;
		}
		try {
			finishMediaSessionSetup(aci);
		} catch (Exception e) {
			tracer.severe("Unable to initiate join.", e);
			terminateSipSession();
			abortMediaSessionSetup();
		}
	}
	
	/*
	 * End of the media session setup: creates ivr and make it join the session
	 * with the sip client.
	 */
	private void finishMediaSessionSetup(
			ActivityContextInterface networkConnectionAci)
			throws MsControlException {
		NetworkConnection connection = (NetworkConnection) networkConnectionAci
				.getActivity();
		MediaSession session = connection.getMediaSession();
		MediaGroup mediaGroup = session
				.createMediaGroup(MediaGroup.PLAYER_RECORDER_SIGNALDETECTOR);
		connection.joinInitiate(Direction.DUPLEX, mediaGroup, "context");
		ActivityContextInterface mediaGroupACI = mscRaAciFactory
				.getActivityContextInterface(mediaGroup);
		mediaGroupACI.attach(sbbContext.getSbbLocalObject());
		setMediaGroupACI(mediaGroupACI);
	}
            	]]>
				</programlisting>
		</section>
		<section
			id="root_sbb_abstract_class_join_event_handler">
			<title>The JoinEvent handler</title>
			<para>The <literal>MS Control</literal> JoinEvent is sent when Media Server controller joins resources . Event handler code responsibilities are:</para>

			<itemizedlist>
				<listitem>
					<para>Request media playback from group player.</para>
				</listitem>
			</itemizedlist>

			<para>The event handler code:</para>
			<programlisting
				language="Java"
				role="JAVA"><![CDATA[
   /**
	 * Event notifying the connection between the sip client and the media
	 * server.
	 * 
	 * @param event
	 * @param aci
	 */
	public void onJoined(JoinEvent event, ActivityContextInterface aci) {
		tracer.info("SIP client and media server connected, requesting play of announcement...");
		try {
			ActivityContextInterface mediaGroupACI = getMediaGroupACI();
			MediaGroup mediaGroup = (MediaGroup) mediaGroupACI.getActivity();
			mediaGroup.getPlayer().play(new URI(WELCOME), null, null);
		} catch (Exception e) {
			tracer.severe(
					"Unexpected error playing annoucenment, terminating sip and media sessions.",
					e);
			terminateSipSession();
			terminateMediaSession();
		}
	}
	
	/*
	 * Terminates the media session: releases the network connection and the
	 * media session.
	 */
	private void terminateMediaSession() {
		releaseMediaSession();
	}
            	]]>
				</programlisting>
		</section>
	</section>

</chapter>





© 2015 - 2024 Weber Informatics LLC | Privacy Policy