- Requirements
User level
Adobe offers two different services for building and managing peer-to-peer (P2P) applications: Adobe Cirrus (previously codenamed Stratus) and Adobe LiveCycle Collaboration Service. The two serve different purposes. Cirrus is a service on Adobe Labs that allows you to preview the latest prerelease capabilities of Flash. LiveCycle Collaboration Service is a commercially supported service with an easy-to-use development framework.
This article will help you understand the two different platforms and teach you how to migrate applications you have developed on Cirrus to a commercial service with LiveCycle Collaboration Service (LCCS).

Note: The Cirrus service discussed in this article is not to be confused with the "Cirrus" code name for Adobe Flash Builder for Force.com – Developer Preview, which is a development tool for building cloud-based RIAs.

Comparing Cirrus and LiveCycle Collaboration Service

The basic differences between using Adobe Cirrus (a P2P rendezvous service) and LiveCycle Collaboration Service boil down to control and support. With Cirrus, you have limited control over managing your P2P applications from the server, because the service is solely a rendezvous service responsible for helping applications running in Adobe Flash Player connect with one another. Moreover, because it is an Adobe Labs technology, Cirrus will always have the latest pre-release capabilities of Adobe Flash built in. Our goal with Cirrus is to provide you with access to these new features so we can collect your collective feedback. Cirrus is for non-commercial use only.
Adobe LiveCycle Collaboration Service is a commercial service that provides an easy-to-use development model supported by Adobe's hosted service. It includes a framework to se P2P—so you don't have to care whether it's using P2P or hub-and-spoke communication. Together with this, it has automatic failover from P2P to hub-and-spoke for clients who don't have a UDP-enabled network.
Advantages of Cirrus
  • Showcases future Flash media technology to enable you to test-drive emerging technologies (like Groups and Multicast in Flash Player 10.1, announced at Adobe MAX 2009)
  • Lets you start exploring the benefits of P2P on the Flash Platform
  • Enables you to send audio, video, and byte data through P2P over UDP (UDP protocol is lossy and is widely used across VoIP and video services)
  • Available for free on Adobe Labs for non-commercial usage
Advantages of LiveCycle Collaboration Service
  • Includes a prebuilt framework and hosted service
  • Provides easy-to-use Flex and Flash components (adding collaboration features to your app has never been easier)
  • Offers a commercial option to deploy P2P based solutions
  • Makes it easy to enable P2P by setting protocol="rtmfp" on ConnectSession or ConnectSessionContainer (even if you don't have a UDP-enabled network, it will try and then fall back to RTMPS)
  • Hides the details of its P2P implementation from the developer; you don't have to care about anything regarding P2P implementation details in order to use it
  • Always uses P2P when possible to help you reduce costs, as long as all people in the same room have a UDP-enabled network
  • Automatically switches all participants to hub-and-spoke communication via LiveCycle Collaboration Service infrastructure (in this case Flash Media Server RTMP/T) if someone in the room does not have a UDP enabled network (an auto-check function monitors room participants' network capabilities)
  • Provides usage monitoring and charts
  • Allows you to pay as you go for the service (just redeem credit for your account on the fly using a credit card)
  • Data transfer is free when P2P is available
LiveCycle Collaboration Service is very efficient when using P2P and uses it whenever possible. Together with this, it has automatic failover to hub-and-spoke when P2P is unavailable. On the other hand, when using LiveCycle Collaboration Service, only audio and video streams are sent using P2P—no byte/text data. In a video chat scenario, audio and video streams are transferred using P2P when possible, but text chat, whiteboard, or mouse position data are sent using hub-and-spoke.
This is the main difference between LiveCycle Collaboration Service and Cirrus in the area of data transfer:
  • Content management: For a case such as a whiteboard, if two people edit at the same time, there needs to be a point of contention resolution.
  • Security: Data messaging through LCCS is done in such a way that read/write permissions for various data streams can be managed. Clients cannot be the authoritative source of such management because someone may gain access to client-side routines. LiveCycle Collaboration Service provides management because developers don't have access to modify anything in the service cloud.
  • State awareness: When a client enters a collaborative environment as a participant, the client often needs to have access to the state of the environment before it arrives. For example, if I come in late to a whiteboarding session, I want to see what was already drawn. If data only comes from the client, then someone would need to rebroadcast the old shapes. LCCS becomes the repository for the state of the app and can update incoming clients automatically.
  • Low latency: Even with hub-and-spoke, data messaging distribution is fast (sub-100ms).
Use LiveCycle Collaboration Service if you need an easy-to-use, tested implementation with failover, support, and monitoring with a commercial service. LCCS will let you use guaranteed P2P commercially in your product.
In addition to Cirrus and LiveCycle Collaboration Service, the RTMFP protocol will also be available in a future release of Flash Media Server.

Customer success (OddCast.com)


OddCast, which provides and builds VoIP solutions on the Adobe Flash Platform, recently switched from Cirrus to LiveCycle Collaboration Service. As David Segal, Team Leader, Front-End Development, explained it:

The main reason we switched from Status to LCCS was we needed to make our application commercially available to our customers. Our goal was to create a P2P tool to connect small businesses with their clients using voice and text chat. I found LCCS to be a comprehensive, feature-rich set of tools for P2P communication. In comparison to Cirrus, I found working with the LCCS framework to be a huge upgrade both in terms of its feature set and its ease of implementation. Much of the code I had written to manage NetStreams with Status became redundant with the LCCS framework, as it was already built-in. I ended up with a more readable, usable, and easily expandable application. In addition, the admin tool is a nice addition that has been quite helpful for debugging and monitoring usage of the service.

Figure 1 depicts two aspects of the SitePal Communication Center. The two browser windows at the top of the image are the client-facing apps (SWFs). They can be embedded in the web pages of any of OddCast's clients and allow visitors of the site to voice- or text-chat with the site owner or his/her help desk. On the bottom right is the AIR application that the site owner runs to receive the connections from the SWFs above, as well as monitor traffic and usage of the site.

SitePal Communication Center
Figure 1. SitePal Communication Center

Exploring RTMFP connection routines between LCCS and Cirrus P2P connection routines

Given the differences between Cirrus and LiveCycle Collaboration Service and the different levels of control they offer the developer, connecting to these services for P2P applications is also very different. Following are two examples of different connection routines between LCCS and Cirrus. You can use these examples if you choose to migrate from Cirrus to LCCS.
LiveCycle Collaboration Service
Following is an example based on Adobe Flex 3 of a full-featured video chat application for multiple participants:
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" minWidth="1024" minHeight="768" xmlns:rtc="AfcsNameSpace"> <rtc:AdobeHSAuthenticator id="auth" userName="SOME-USERNAME" protocol="rtmfp" /> <rtc:ConnectSessionContainer authenticator="{auth}" width="100%" height="100%" id="session" roomURL="http://connectnow.acrobat.com/YOUR-ACCOUNT/YOUR-ROOM"> <rtc:WebCamera x="10" y="10"/> <rtc:AudioPublisher /> <rtc:AudioSubscriber /> <rtc:SimpleChat x="10" y="218" width="250"/> </rtc:ConnectSessionContainer> </mx:Application>
For more information about LiveCycle Collaboration Service, see the Flash Platform Collaboration Services page. Sign up for a developer account at afcs.acrobat.com.
Here is an example based on Adobe Flash Builder 4 illustrating a similar, basic video chat for two people. Notice in this example that you need to transfer P2P fingerprints manually. Automatic fingerprint exchange needs server-side scripting and database, and the app gets even more complicated (and it's not available with Cirrus). However, you have full control over the connection routine implementation at the ActionScript level:
<?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/halo" minWidth="1024" minHeight="768"> <fx:Declarations> <!-- Place non-visual elements (e.g., services, value objects) here --> </fx:Declarations> <fx:Script> <![CDATA[ /** * * P2P * */ public const SERVER_ADDRESS:String = "rtmfp://stratus.adobe.com/"; public const DEVELOPER_KEY:String = "YOUR-DEVELOPER-KEY"; private var conn:NetConnection; private var streamOut:NetStream; private var streamIn:NetStream; [Bindable] private var myPeerID:String; private var farID:String; public function connect():void{ conn = new NetConnection(); conn.addEventListener(NetStatusEvent.NET_STATUS,connStatus); conn.addEventListener(AsyncErrorEvent.ASYNC_ERROR,asyncErr); conn.connect(SERVER_ADDRESS+DEVELOPER_KEY); } private function connStatus(event:NetStatusEvent):void{ trace(event.info.code); txtStatus.text = event.info.code; if(event.info.code=="NetConnection.Connect.Success"){ myPeerID = conn.nearID; initOutStream(); } } private function asyncErr(event:AsyncErrorEvent):void{ } private function initOutStream():void{ trace("initOutStream"); streamOut = new NetStream(conn,NetStream.DIRECT_CONNECTIONS); streamOut.addEventListener(NetStatusEvent.NET_STATUS,streamStatus); streamOut.publish("media"); // CAMERA var cam:Camera = Camera.getCamera(); camOut.videoObject.attachCamera(cam); streamOut.attachCamera(cam); streamOut.attachAudio(Microphone.getMicrophone()); var streamOutClient:Object = new Object(); streamOutClient.onPeerConnect = function(farStream:NetStream):Boolean{ // initInStream(farStream.farID); return true; } } private function initInStream(farID:String):void{ trace("initInStream: ") streamIn = new NetStream(conn,farID); streamIn.addEventListener(NetStatusEvent.NET_STATUS,streamStatus); streamIn.play("media"); streamIn.client = this; camIn.videoObject.attachNetStream(streamIn); } private function streamStatus(event:NetStatusEvent):void{ trace("streamStatus: "+event.info.code); } public function receiveMessage(msg:String):void{ trace("receiveMessage: "+msg) txtHistory.text = msg+"\n"+txtHistory.text; } public function sendMessage(msg:String):void{ streamOut.send("receiveMessage",msg); receiveMessage(msg); } protected function btnSend_clickHandler(event:MouseEvent):void{ trace("sendMessage: "+txtMessage.text) sendMessage(txtMessage.text); } ]]> </fx:Script> <s:TextInput x="10" y="10" width="201" id="txtStatus"/> <s:TextInput x="10" y="40" width="201" id="txtStatusStream"/> <s:TextInput x="9" y="151" width="157" id="txtFarPeerID"/> <s:TextInput x="9" y="124" width="250" id="txtMyPeerID" text="{myPeerID}"/> <s:Button x="10" y="75" label="Connect" click="connect()" id="btnConnect"/> <s:Button x="174" y="152" label="initInStream" click="initInStream(txtFarPeerID.text)" id="btnConnect0"/> <s:TextArea x="9" y="181" width="285" height="160" id="txtHistory"/> <s:Button x="232" y="351" label="Send" id="btnSend" click="btnSend_clickHandler(event)" width="62"/> <s:TextInput x="9" y="349" id="txtMessage" width="215" enter="{btnSend_clickHandler(null)}"/> <s:VideoElement id="camOut" width="141" height="112" x="221" y="8"/> <s:VideoElement id="camIn" width="141" height="112" x="365" y="8"/> </s:Application>

Where to go from here

Dive deeper into P2P by visiting the following resources:
LiveCycle Collaboration Service
General peer-to-peer