Posted
over 16 years
ago
by
amit.bhayani
Just few days back MMS CR6 was released with much improvements on performance. I did a quick performance test of CR6 using SipP tool for load generation, a wonderful tool called sysstat for CPU recording
... [More]
http://pagesperso-orange.fr/sebastien.godard/tutorial.html#section1 and our own tool for RTP Jitter recording.The test was run for approximately 10 min with intention to measure the jitter at load of 100 ~ 110 concurrent announcements and at same time measure the CPU usage on MMS Server.While the Jitter was under control the CPU never crossed more than 25%. The attached graph shows the idle% CPU recorded after every 5 secs.Here are the jitter graphs taken randomly while running the test tool.Further details here [Less]
|
Posted
over 16 years
ago
by
amit.bhayani
The focus of this release has been the performance. CR6 is by far one of the best performing MMS! MMS now can easily have 200 concurrent Announcement or IVR. Details hereOne of the major issue was Buffer was created too frequently and not reused
... [More]
which caused frequent GC. Other issue was with Inband Dtmf detection which is based on Goertzel Algorithm was consuming too much of CPU. The algorithm is modified in CR6 to have all the costly operation done at MMS start time and just use comparison's and other simple calculations at runtime.The announcement for CR6 release is hereDownload hereCheers! [Less]
|
Posted
over 16 years
ago
by
Ivelin
|
Posted
over 16 years
ago
by
Jean Deruelle
As part of the scheduled 0.9 version of Mobicents Sip Servlets, one of our tasks is to add telco features to JRuby on Rails applications so that it becomes quite easy to create click 2 dial or ipbx kind of apps in Rails.Adhearsion, a framework
... [More]
written in Ruby by Jay Philips, allows Rails applications to control various functions in Asterisk servers. Our goal here is a bit different we would like to enable current Rails application to leverage the Sip Servlets specification and be able to handle all the best parts of it. Not sure yet if we will try to integrate into JRuby-Rack or create a similar adapter for the Sip Servlets Specification... so stay tuned !As I'm still a newbie on all the ruby world, feel free to comment to help us out or chime in with ideas on how to achieve this goal...So since I'm a (J)Ruby-Rails-newbie, I started where all people start at the ruby home and documentation with their excellent tutorials. If you're a newbie as well please familiarize yourself with ruby before going farther. As my grandma said : "Learn to walk before you run!"So after I felt like I grasped the basics of ruby I went on to play with the famous new kid in town that is getting all the hype these days (or is it already old fashionned and Scala, Haskell and such is getting the hype now ?) : Ruby on Rails. Same thing here, I followed their simple tutorial that gets you started and off I went with my first rails app. Then I wanted to get a bit farther and started with their blogging application tutorial.I decided that this was enough for now and that I'll dig deeper as I go and since my objective was JRuby on Rails, I will retry to create the blogging app on JRuby.So first download the JRuby version 1.1.6 and installed it in my home directory on my linux box under java/jruby-1.1.6. Set the JRUBY_HOME environment variable to the location where you installed it and add the JRUBY_HOME/bin directory to your PATH variable so that all commands are available from the command line. On linux this would be adding this to your ~/.bashrc file :$ export JRUBY_HOME=/path/to/your/jruby/installation$ export PATH=$PATH:$JRUBY_HOME/binYou can test it out from the command line to issue the version by typing this$ jruby -vThis will give the following output :jruby 1.1.6 (ruby 1.8.6 patchlevel 114) (2008-12-17 rev 8388) [i386-java]Ok let's install Rails now :$ jruby -S gem install railsThis will produce the following output :JRuby limited openssl loaded. gem install jruby-openssl for full support.http://wiki.jruby.org/wiki/JRuby_Builtin_OpenSSLSuccessfully installed activesupport-2.2.2Successfully installed activerecord-2.2.2Successfully installed actionpack-2.2.2Successfully installed actionmailer-2.2.2Successfully installed activeresource-2.2.2Successfully installed rails-2.2.26 gems installedInstalling ri documentation for activesupport-2.2.2...Installing ri documentation for activerecord-2.2.2...Installing ri documentation for actionpack-2.2.2...Installing ri documentation for actionmailer-2.2.2...Installing ri documentation for activeresource-2.2.2...Installing RDoc documentation for activesupport-2.2.2...Installing RDoc documentation for activerecord-2.2.2...Installing RDoc documentation for actionpack-2.2.2...Installing RDoc documentation for actionmailer-2.2.2...Installing RDoc documentation for activeresource-2.2.2...Since JRuby doesn't support SQLite, we will use mySQL as the database (I assume it is already installed on your machine) so we install the jdbc mysql adapter for activerecord (if you don't know what activerecord, check the Rails documentation).$ jruby -S gem install activerecord-jdbcmysql-adapterThis will produce the following output :JRuby limited openssl loaded. gem install jruby-openssl for full support.http://wiki.jruby.org/wiki/JRuby_Builtin_OpenSSLSuccessfully installed activerecord-jdbc-adapter-0.9Successfully installed jdbc-mysql-5.0.4Successfully installed activerecord-jdbcmysql-adapter-0.93 gems installedInstalling ri documentation for activerecord-jdbc-adapter-0.9...Installing ri documentation for jdbc-mysql-5.0.4...Installing ri documentation for activerecord-jdbcmysql-adapter-0.9...Installing RDoc documentation for activerecord-jdbc-adapter-0.9...Installing RDoc documentation for jdbc-mysql-5.0.4...Installing RDoc documentation for activerecord-jdbcmysql-adapter-0.9...Let's create the blog application backed by mySQL now :$ jruby -S rails blog -d mysqlGo into the “blog” directory, then modify the config/database.yml.Adjust the adapter name, and instead of ‘mysql’ put ‘jdbcmysql’. You might also want to delete the lines starting with “socket:” or set it to tmp dir. Here’s a simple example for the development environment:development:adapter: jdbcmysqlencoding: utf8database: blog_developmentpool: 5username: rootpassword:socket: /tmp/mysqld.sockAlso edit the config/environment.rb to specify the gem dependency we have on the jdbcmysql adapter (this step is mandatory for freezing the dependencies in your app later on)Rails::Initializer.run do |config| ...config.gem "activerecord-jdbcmysql-adapter", :version => '0.9', :lib => 'active_record/connection_adapters/jdbcmysql_adapter'...endNow, it’s time to create our database:$ jruby -S rake db:create:allThe next step is to create some minimal scaffolding so that you could actually play with some dynamic functionality and database access:$ jruby script/generate scaffold Post name:string title:string content:textWe need to update the database after that:$ jruby -S rake db:migrateLet's the application now :$ jruby script/serverand go to http://localhost:3000/postsNow let's freeze the rails version and the associated gems dependencies we are using into our application so that if rails or a dependency is upgraded in the system, our application will always use the version we freezed and not the newly upgraded version of rails from the system. Note: this is highly recommended for production env and really is a best practice (google freeze rails for more information)Note that freezing is mandatory if you wish to deploy your application to JBoss 5 with the jboss-rails plugin.It is a 2 steps process, first freeze rails then the dependencies (in our case the jdbcmysql adapter)Here is the command to freeze your rails application :$ jruby -S rake rails:freeze:gemsHere is the command$ jruby -S rake gems:unpack:dependenciesYou can verify that it worked by issuing this command$ jruby -S rake gemsThat will produce the following output : - [F] activerecord-jdbcmysql-adapter = 0.9 - [F] activerecord-jdbc-adapter = 0.9 - [F] jdbc-mysql = 5.0.4I = InstalledF = FrozenR = Framework (loaded before rails starts)Ok now I can restart the app and play with again (nothing will have changed but if you modify your rails installation to a newer version the app will keep using the version you froze with it).Let's deploy our application to JBoss 5 now :First grab a JBoss AS 5.0.0.GA zip and unzip to the location of your choice then set the JBOSS_HOME env variable to itNow let's get the jboss-rails plugin from the all too famous Bob McWhirter's github repo by issuing the following command (don't forget to move to another directory than your blog application) :$ git clone git://github.com/bobmcwhirter/jboss-rails.gitfrom the newly created jboss-rails directory (note that JDK6 is needed for it to compile) :$ mvn clean installcopy the content of the target/jboss-rails.deployer directory to JBOSS_HOME/server/default/deployers/jboss-rails.deployers.Congratulations, We just installed the jboss-rails deployer into our jboss installation. Now let's tell the jboss deployers that we want to deploy a rails application by creating a blog-rails.yml file into JBOSS_HOME/server/default/deploy directory as explained by Bob that contain the following :application: RAILS_ROOT: /home/deruelle/ruby/rails/blog RAILS_ENV: developmentweb: context: /blog host: *ok we are all set up now, you can start your JBoss 5 application server :$ cd JBOSS_HOME/bin$ sh run.shand go to http://localhost:8080/blog/posts, there you go your JRuby-rails application working in jboss without the need to create a war and we are able to modify it at runtime, isn't that great !Thanks Bob for you thesis, plugin and help !Feel free to comment and let me know how well it worked for you !
[Less]
|
Posted
over 16 years
ago
by
amit.bhayani
|
Posted
over 16 years
ago
by
Jean Deruelle
Here is our new feature packed Mobicents Sip Servlets release !The focus of this release has been to be able to run Mobicents Sip Servlets on top of JBoss 5, it has been better than expected since we already pass the Sip Servlets 1.1 TCK for JBoss
... [More]
5.We also wanted to be able to act as a SIP Application Server in the IMS architecture and push the limits of Seam integration and showcasing it with a Media IPBX based on the Seam Sip Servlets framework to demonstrate the technology and eventually become a real useful PBX productWe also continued to add new carrier grade features to Mobicents Sip Servlets by adding more Congestion Control mechanisms and we created a jopr plugin for Mobicents Load Balancer so that it can be more easily monitored and managed.Our Mobicents Sip Servlets implementation run on top of Apache Tomcat 6.0.14, JBoss AS 4.2.3.GA and now on JBoss AS 5.0.0.GA and is shipped with Mobicents Media Server 1.0.0.CR5The other highlights of this release are :a Diameter Sh support showing integration between Mobicents Sip Servlets acting as a SIP Application Server in OpenIMS Core, using the Diameter Sh interface to receive profile updates and SIP.Concurrency control at application levelMobicents Sip Servlets User Guide : http://hudson.jboss.org/ hudson/job/ MobicentsDocumentation/ lastSuccessfulBuild/artifact/ html_single/index.html# chapter-Mobicents_SIP_ Servlets_Server More SIP Extensions supported : Join - Replaces - PATHDownloads are here, online documentation is here, User Guide is here, the 0.8 changelog and roadmap is here and the Mobicents Google Group for feedback and questions is here.Thanks to Alex from Mobicents Diameter team, Joel Soderstrom from Telmi Communication and Alex Sova for their contributions to this release.Enjoy !CheersMobicents Sip Servlets Team
[Less]
|
Posted
over 16 years
ago
by
amit.bhayani
The Mobicents MGCP stack has cleared the TCK listed on JSR 23 http://jcp.org/aboutJava/communityprocess/final/jsr023/index.html, though it wasn't one of the most challenging task we kept delaying the TCK compliance as least priority as MGCP TCK is
... [More]
not one of the best one can rely on. Rather we created our own test-suite for MGCP which is more reliable in terms of encoding/decoding command,testing retransmission, regression test and proper flow of command.To understand more about TCK look at README.txt at http://code.google.com/p/mobicents/source/browse/trunk/servers/media/jain-mgcp/tck/README.txtThe test output (this may vary in your environment)[abhayani@localhost tck]$ mvn exec:exec[INFO] Scanning for projects...[INFO] Searching repository for plugin with prefix: 'exec'.[INFO] ------------------------------------------------------------------------[INFO] Building Mobicents MGCP TCK[INFO] task-segment: [exec:exec][INFO] ------------------------------------------------------------------------[INFO] [exec:exec][INFO] JAIN MGCP TCK[INFO] This instance is a Gateway.[INFO] Using org.mobicents.mgcp.stack as the path name for JainMgcpStackImpl.[INFO] Remote entity is 127.0.0.1:2727.[INFO] Verbose trace selected.[INFO][INFO] Testing Bandwidth parameter class.[INFO] Testing single parameter constructor. Succeeded![INFO] Testing two parameter constructor. Succeeded![INFO][INFO] Testing BearerInformation parameter class. Succeeded![INFO][INFO] Testing CallIdentifier parameter class.[INFO] Invoking constructor with valid hexadecimal string. Succeeded![INFO] Calling constructor with empty string (should throw exception). Succeeded![INFO] Calling constructor with string of more than 32 characters (should throw exception). Succeeded![INFO] Calling constructor with string that contains non-hexadecimal characters (should throw exception). Succeeded![INFO] Invoking setCallIdentifier() with valid hexadecimal string. Succeeded![INFO] Invoking setCallIdentifier() with empty string (should throw exception). Succeeded![INFO] Invoking setCallIdentifier() with string of more than 32 characters (should throw exception). Succeeded![INFO] Invoking setCallIdentifier() with string that contains non-hexadecimal characters (should throw exception). Succeeded![INFO][INFO] Testing ConnectionIdentifier parameter class.[INFO] Invoking constructor with valid hexadecimal string. Succeeded![INFO] Calling constructor with empty string (should throw exception). Succeeded![INFO] Calling constructor with string of more than 32 characters (should throw exception). Succeeded![INFO] Calling constructor with string that contains non-hexadecimal characters (should throw exception). Succeeded![INFO] Invoking setConnectionIdentifier() with valid hexadecimal string. Succeeded![INFO] Invoking setConnectionIdentifier() with empty string (should throw exception). Succeeded![INFO] Invoking setConnectionIdentifier() with string of more than 32 characters (should throw exception). Succeeded![INFO] Invoking setConnectionIdentifier() with string that contains non-hexadecimal characters (should throw exception). Succeeded![INFO][INFO] Testing ConnectionMode parameter class. Succeeded![INFO][INFO] Testing EchoCancellation parameter class. Succeeded![INFO][INFO] Testing EventName parameter class. Succeeded![INFO][INFO] Testing ExtendedConnectionParm parameter class. Succeeded![INFO][INFO] Testing GainControl parameter class. Succeeded![INFO][INFO] Testing InfoCode parameter class. Succeeded![INFO][INFO] Testing EncryptionMethod parameter class. Succeeded![INFO][INFO] Testing PacketizationPeriod parameter class.[INFO] Testing single parameter constructor. Succeeded![INFO] Testing two parameter constructor. Succeeded![INFO][INFO] Testing ResourceReservation parameter class. Succeeded![INFO][INFO] Testing SilenceSuppression parameter class. Succeeded![INFO][INFO] Testing TypeOfNetwork parameter class. Succeeded![INFO][INFO] Testing TypeOfService parameter class. Succeeded![INFO][INFO] Testing LocalOptionExtension parameter class. Succeeded![INFO][INFO] Testing NotifiedEntity parameter class. Succeeded![INFO][INFO] Testing QuarantineHandling parameter class. Succeeded![INFO][INFO] Testing ReasonCode parameter class. Succeeded![INFO][INFO] Testing RegularConnectionParm parameter class. Succeeded![INFO][INFO] Testing RequestedAction parameter class. Succeeded![INFO][INFO] Testing PackageName parameter class. Succeeded![INFO][INFO] Testing PackageName parameter class. Succeeded![INFO][INFO] Testing SupportedModes parameter class. Succeeded![INFO][INFO] Testing SupportedPackages parameter class. Succeeded![INFO][INFO] Testing LocalOptVal parameter class. Succeeded![INFO][INFO] Test of Gateway API succeeded![INFO][INFO] Continuing with messaging tests.[INFO] Getting an instance of JainIPFactory.[INFO] Setting path name for stack implementation to org.mobicents.mgcp.stack.[INFO] Creating a JainMgcpStack object.[INFO] Setting port to Gateway default port 2427[INFO] Creating a JainMgcpProvider object[INFO] 0 [main] INFO org.mobicents.mgcp.stack.JainMgcpStackImpl - mgcp-stack.properties read successfully![INFO] executorTableSize = 80[INFO] executorQueueSize = -1[INFO] messageReaderThreadPriority = 10[INFO] messageDispatcherThreadPriority = 7[INFO] messageExecutorThreadPriority = 5[INFO] 46 [main] INFO org.mobicents.mgcp.stack.JainMgcpStackImpl - Jain Mgcp stack bound to IP 0.0.0.0/0.0.0.0 and UDP port 2427[INFO] Jain Mgcp stack bound to IP 0.0.0.0/0.0.0.0 and UDP port 2427[INFO] Creating a JainMgcpListener object[INFO] Adding JainMgcpListener object to JainMgcpProvider's list[INFO] Received AuditConnectionResponse with transaction ID 1[INFO] Received AuditEndpointResponse with transaction ID 2[INFO] Received CreateConnectionResponse with transaction ID 3[INFO] Received AuditConnection with transaction ID 5[INFO] Sent AuditConnectionResponse with transaction ID 5[INFO] message =[INFO] DLCX 4 [email protected]:2727 MGCP 1.0[INFO] C:FFFF[INFO][INFO] local Tx ID = 4 Remote Tx ID = 4 Sending the Command 2[INFO] Received DeleteConnectionResponse with transaction ID 4[INFO] Received AuditEndpoint with transaction ID 7[INFO] Sent AuditEndpointResponse with transaction ID 7[INFO] Received DeleteConnectionResponse with transaction ID 4[INFO] Received EndpointConfigurationResponse with transaction ID 5[INFO] Received CreateConnection with transaction ID 9[INFO] Sent CreateConnectionResponse with transaction ID 9[INFO] message =[INFO] EPCF 8 [email protected]:2727 MGCP 1.0[INFO] B:e:mu[INFO][INFO] local Tx ID = 8 Remote Tx ID = 6 Sending the Command 2[INFO] Received EndpointConfigurationResponse with transaction ID 6[INFO] message =[INFO] MDCX 10 [email protected]:2727 MGCP 1.0[INFO] C:FFFF[INFO] I:FFFF[INFO][INFO] local Tx ID = 10 Remote Tx ID = 7 Sending the Command 2[INFO] Received ModifyConnectionResponse with transaction ID 7[INFO] Received EndpointConfigurationResponse with transaction ID 6[INFO] Received ModifyConnectionResponse with transaction ID 7[INFO] Received ModifyConnectionResponse with transaction ID 8[INFO] Received NotificationRequestResponse with transaction ID 9[INFO] Received DeleteConnection with transaction ID 16[INFO] Sent DeleteConnectionResponse with transaction ID 16[INFO] message =[INFO] MDCX 13 [email protected]:2727 MGCP 1.0[INFO] C:FFFF[INFO] I:FFFF[INFO][INFO] local Tx ID = 13 Remote Tx ID = 10 Sending the Command 2[INFO] Received ModifyConnectionResponse with transaction ID 10[INFO] message =[INFO] RQNT 14 [email protected]:2727 MGCP 1.0[INFO] X:FFFF[INFO][INFO] local Tx ID = 14 Remote Tx ID = 11 Sending the Command 2[INFO] Received NotificationRequestResponse with transaction ID 11[INFO] message =[INFO] RQNT 15 [email protected]:2727 MGCP 1.0[INFO] X:FFFF[INFO][INFO] local Tx ID = 15 Remote Tx ID = 12 Sending the Command 2[INFO] Received NotificationRequestResponse with transaction ID 12[INFO] message =[INFO] NTFY 17 [email protected]:2727 MGCP 1.0[INFO] X: FFFF[INFO] O: */AllEvents[INFO][INFO] local Tx ID = 17 Remote Tx ID = 13 Sending the Command 2[INFO] Received NotifyResponse with transaction ID 13[INFO] Received ModifyConnectionResponse with transaction ID 10[INFO] Received NotificationRequestResponse with transaction ID 11[INFO] Received EndpointConfiguration with transaction ID 24[INFO] message =[INFO] RQNT 18 [email protected]:2727 MGCP 1.0[INFO] X:FFFF[INFO][INFO] local Tx ID = 18 Remote Tx ID = 14 Sending the Command 2[INFO] message =[INFO] NTFY 19 [email protected]:2727 MGCP 1.0[INFO] X: FFFF[INFO] O: */AllEvents[INFO][INFO] local Tx ID = 19 Remote Tx ID = 15 Sending the Command 2[INFO] message =[INFO] NTFY 20 [email protected]:2727 MGCP 1.0[INFO] X: FFFF[INFO] O: */AllEvents[INFO][INFO] local Tx ID = 20 Remote Tx ID = 16 Sending the Command 2[INFO] message =[INFO] RSIP 21 [email protected]:2727 MGCP 1.0[INFO] RM:disconnected[INFO][INFO] local Tx ID = 21 Remote Tx ID = 17 Sending the Command 2[INFO] Sent EndpointConfigurationResponse with transaction ID 24[INFO] Received NotificationRequestResponse with transaction ID 14[INFO] Received NotifyResponse with transaction ID 15[INFO] Received NotifyResponse with transaction ID 16[INFO] Received RestartInProgressResponse with transaction ID 17[INFO] Test of messaging capability succeeded! [Less]
|
Posted
over 16 years
ago
by
amit.bhayani
We are happy to announce the first independent binary release of Mobicents JAIN MGCP Stack implementation 2.0.0.CR1 !Before this MGCP implementation was always part of Mobicents Media Server. However MGCP is a industry standard and can be used by
... [More]
applications to control Media Server's other than Mobicents Media Server. To learn more about MGCP please refere to RFC 3435 and JSR 23.Where to download from?The distribution can be found on SourceForge.net. The binary package is mobicents-mgcp-impl-2.0.0.RC1. zip:https://sourceforge.net/ project/showfiles.php?group_ id=102670&package_id=308747& release_id=658531Source repositories:-------------------SVNhttp://mobicents.googlecode. com/svn/trunk/servers/media/ jain-mgcpSVN TAGhttp://code.google.com/p/ mobicents/source/browse/#svn/ tags/servers/media/2.x.y/jain- mgcp/mobicents-mgcp-impl-2.0. 0.RC1How to get started & Media Server Documentation------------------------------ -----------------http://groups.google.com/ group/mobicents-public/web/ user-guide - Chapter 8Looking forward to your feedbackhttp://groups.google.com/group/mobicents-public/browse_thread/thread/4944fde3177f813e [Less]
|
Posted
over 16 years
ago
by
amit.bhayani
The SVN structure for Mobicents Media Server 2.x.y Source is changed a lot as compared to version 1.x.y. The new SVN structure will now look
... [More]
likemediajain-mgcpjain-megacomscmljsr-309coreserver-spiserver-implserver-sarserver-standalonemgcp-controllermegaco-controllerexamples - All standalone examples here (not depending on SLEE or Sip Servlets)sleeramgcpmegacojsr-309examples - All SLEE examples hereconverged-democall-controllermgcp-demoThe protocol stacks jain-mgcp, jain-meagco, mscml and jsr-309 are independent of MMS components and depends on mobicents parent.The core/server-spi is core api design of MMS and core/server-impl is implementation of server-spi. MMS 2.x.y can be build as standalone server (server-standalone) or service in JBoss AS 5.x (server-sar). The controllers mgcp-controller and megaco-controller will be an integration of respective stack and server-spi.The slee is special node for JAIN SLEE. slee/ra will have all the JSLEE RA's for respective stacks and slee/examples demonstrating the usage of these RA's [Less]
|
Posted
over 16 years
ago
by
Vladimir Ralev
UPDATE: The post was edited for clarity.The Mobicents Seam-based Sip Servlets framework was extended with Media functions and now goes beyond SIP to unify the component models for Telco and Web applications. With this move, we are addressing the need
... [More]
to build quickly Media-intensive applications like PBX, conferencing, Interactive Voice Response (IVR), transaction confirmation and others.With the help of the Seam development tools these applications can be written and tested in no time, so even if you don't want to use the Seam model in your production applications, you will find it useful for smaller "disposable" applications, or for rapid prototyping and proof-of-concept applications.Need a conferencing application?@Name("conference")@Scope(ScopeType.STATELESS)public class Conference { @Logger Log log; @In MediaController mediaController; @In SipSession sipSession; @In(scope=ScopeType.APPLICATION, required=false) @Out(scope=ScopeType.APPLICATION, required=false) String conferenceEndpointName; @Observer("INVITE") public void doInvite(SipServletRequest request) throws Exception { String sdp = new String((byte[]) request.getContent()); request.createResponse(180).send(); sipSession.setAttribute("inviteRequest", request); if (conferenceEndpointName == null) conferenceEndpointName = "media/trunk/Conference/$"; mediaController.createConnection(conferenceEndpointName).modify("$", sdp); } @Observer("connectionOpen") public void doConnectionOpen(MsConnectionEvent event) throws IOException { conferenceEndpointName = event.getConnection().getEndpoint() .getLocalName(); SipServletRequest request = (SipServletRequest) sipSession .getAttribute("inviteRequest"); SipServletResponse response = request.createResponse(200); response.setContent(event.getConnection().getLocalDescriptor(), "application/sdp"); response.send(); } @Observer( { "BYE", "REGISTER" }) public void sayOK(SipServletRequest request) throws Exception { request.createResponse(200).send(); }}That's all. No cheating.What is happening here is that when an INVITE comes (i.e. when you dial the server), we connect the call to a conference endpoint in Mobicents Media Server. If this is the first call, the conference endpoint is not assigned yet (null) and we allocate a new endpoint (with .../Conference/$) for the application. Once the connection is established, the connectionOpen event occurs, then we store the conference endpoint name at the application scope and when the subsequent calls in this application see it they will connect to the same endpoint. We can easily extend this application to work with multiple conferences or add other media functionality. All SIP and Media events occur in a SIP Session, which is basically one call from one user (or one phone). If you want to share data in the SIP session scope simply inject the SipSession as shown in the application or create a SESSION-scoped Seam component. This conference example is available here. If you want to understand Mobicents Media Server and the MSC API you should read the Mobicents Media Server Guide.In addition to the basic media support we are aiming to simplify the most common use-cases for media applications. While developing media applications I noticed that one SIP call is always constructed like this:or the more simple chain:In both chains the call is terminated at some media endpoint - IVR or Conference or an Announcement endpoint (which is not shown in the diagrams). After the call is established, the user agent is connected to exactly one media endpoint at any time, either directly or through a Packet Relay endpoint. This means that we can safely store all these links and endpoints related to the call right into the SIP session and never worry again about how to pass them to another method or component. If you need to switch to another chain just keep the session data updated. That's why we are looking into reserving a special place in the SIP session for the media objects.To understand it better let's look at another example:@Name("mediaFrameworkDemo")@Scope(ScopeType.STATELESS)public class MediaFrameworkDemo { @Logger Log log; @In MediaController mediaController; @In SipSession sipSession; @In MediaSessionStore mediaSessionStore; @In ConnectionIVRHelper connectionIVRHelper; @In MediaEventDispatcher mediaEventDispatcher; @In(scope=ScopeType.APPLICATION, required=false) @Out(scope=ScopeType.APPLICATION, required=false) String conferenceEndpointName; private final String announcement = "http://mobicents.googlecode.com/svn/branches/servers/media/1.x.y/examples/" + "mms-demo/web/src/main/webapp/audio/welcome.wav"; @Observer("INVITE") public void doInvite(SipServletRequest request) throws Exception { // Extract SDP from the SIp message String sdp = new String((byte[]) request.getContent()); // Tell the other side to ring (status 180) request.createResponse(SipServletResponse.SC_RINGING).send(); // Store the INVITE request in the sip session sipSession.setAttribute("inviteRequest", request); // If this is the first INVITE in the app, then we must start a new conference if (conferenceEndpointName == null) conferenceEndpointName = "media/trunk/Conference/$"; // Create a connection between the UA and the conference endpoint mediaController.createConnection(conferenceEndpointName).modify("$", sdp); // also updates the SDP in Media Server to match capabilities of UA } @Observer("connectionOpen") public void doConnectionOpen(MsConnectionEvent event) throws IOException { // Save this connection where the framework can read it mediaSessionStore.setMsConnection(event.getConnection()); // The conference endpoint is now assiged after we are connected, so save it too conferenceEndpointName = event.getConnection().getEndpoint() .getLocalName(); // Recall the INVITE request that we saved in doInvite SipServletRequest request = (SipServletRequest) sipSession .getAttribute("inviteRequest"); // Make OK (status 200) to tell the other side that the call is established SipServletResponse response = request.createResponse(SipServletResponse.SC_OK); // Put the SDP inside the OK message to tell what codecs and so on we agree with response.setContent(event.getConnection().getLocalDescriptor(), "application/sdp"); // Now actually send the message response.send(); // And start listening for DTMF signals connectionIVRHelper.detectDtmf(); } @Observer("DTMF") public void dtmf(String button) { // If the other side presses the button "0" stop the playback if("0".equals(button)) { connectionIVRHelper.endAll(); } else { // otherwise play announcement connectionIVRHelper.playAnnouncementWithDtmf(announcement); } // Also log the DTMF buttons pressed so far in this session log.info("Current DTMF Stack for the SIP Session: " + mediaEventDispatcher.getDtmfArchive(sipSession)); } // Just say OK to these messages. @Observer( { "BYE", "REGISTER" }) public void sayOK(SipServletRequest request) throws Exception { request.createResponse(200).send(); // And clean up the connections MsConnection connection = mediaSessionStore.getMsConnection(); connection.release(); }}This is almost the same conference application with some IVR capabilities and some comments between the lines. The MediaSessionStore stores the call-related media objects (the MsConnection in this case) and ConnectionIVRHelper will read it from there when it is doing DTMF detection or playing announcement.Once you are connected to the conference the application works like this - when you press a button 1-9 it will play a personal announcement (only the user who pressed the button can hear it). If the users presses "0" the announcement will be stopped. Note that MediaSessionStore, MediaEventDispatcher and ConnectionIVRHelper are not part of the framework right now, but you can copy and paste them into your own application from the media framework demo application in SVN (the discussed example). Eventually the classes from the org.mobicents.servlet.sip.seam.session.framework package will be moved into the main framework jar.DevelopmentIf you've read the previous post about the Seam framework, you would already know that these applications can use almost all Seam features including hot-deployment and JBoss Tools-assisted development. Note that you don't need JBoss Tools, you can use your own IDE or no IDE with Ant or Maven or whatever you want.Here is what you need to get started with JBoss Tools:Mobicents Sip Servlets 0.7.2 with JBoss AS 4.2.3 or Mobicents Sip Servlets 0.8 with JBoss AS 4.2.3 (please do not use it with JBoss AS 5.0 for now, since the Media support there is still in technology preview stage)Install the latest nightly build of JBoss Tools in Eclipse 3.4 (this is the update site) - you need JBoss Seam, JBoss AS Tools and Richfaces plug-ins as minimum. You must use the nightly builds for Seam 2.1 support. Soon, a new JBoss Developer Studio will be released with official Seam 2.1 support.Get Seam 2.1.1.GA and configure it as Seam runtime in JBoss Tools when asked.Once you create a Seam 2.1 project you can extend it with the Telco framework by following these steps:Get the sip-servlet-seam-entrypoint.jar and put in the Web App lib folder (under WebContent/WEB-INF/lib)Put this sip.xml in WebContent/WEB-INF/ :<?xml version="1.0" encoding="utf-8"?><sip-app> <app-name>PUT_SOME_APPLICATION_NAME_HERE</app-name> <display-name>SeamEntryPointApplication</display-name> <description>SeamEntryPointApplication</description> <main-servlet> SeamEntryPointServlet </main-servlet> <servlet> <servlet-name>SeamEntryPointServlet</servlet-name> <display-name>SeamEntryPointServlet</display-name> <description>Seam Entry Point Servlet</description> <servlet-class> org.mobicents.servlet.sip.seam.entrypoint.SeamEntryPointServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> <listener> <listener-class> org.mobicents.servlet.sip.seam.entrypoint.SeamEntryPointServlet </listener-class> </listener></sip-app>Now you are done. Just start adding Seam components.Another way to get started is to checkout one of the examples mentioned above and play with them without IDE support (but it requires Maven).Some guidelinesDo not subscribe methods to SIP and media events in Seam components with SESSION or CONVERSATION scopes! The reason is that each of these SESSION or CONVERSATION scoped components is likely to have multiple instances (depending on the number of the sessions) and they all will be called, which is probably not what you want.Always subscribe public methods to SIP and media events. Any other access modifier will cause you method not to be called.When dealing with JPA, always use your own EntityManager. Either EVENT or METHOD scoped or manage it manually through the EntityManagerFactory. The default CONVERSATION-scoped entityManager might produce "EntityManager closed" errors.When initiating a SIP request from a Web session, do it in another thread! Seam uses thread-local storage and the Web contexts will collide with the SIP contexts. We are working on solving this issue and will probably be addressed in the future.Keep in mind that outjection occurs at the end of a method call. If you attempt to use an outjected variable from a nested method call, it will fail.Any feedback or contributions are welcome! [Less]
|