
en-US.Chapter-Source_Code_Overview.xml Maven / Gradle / Ivy
The 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 - 2025 Weber Informatics LLC | Privacy Policy