Deploying Flash P2P app on Facebook
October 14th, 2009
The magic of P2P apps is definitely their distribution and deployment. In this article we are going to deploy our Stratus P2P Flash video-chat to Facebook using Facebook ActionScript API and fingerprint exchange service in PHP and MySQL.
This article is a follow-up of my Adobe MAX 2009 session: Social Media Experiences with Flash Media and RTMFP.

If you are not familiar with programming P2P apps in Flash - please follow my video-tutorial.
Prerequisites:
- Flash Builder 4
- Facebook ActionScript 3.0 API
- PHP 5 server
- Zend_AMF running on PHP server (Zend Framework can be installed from Flash Builder 4)
- MySQL database
Source and example:
- download source-code (including Flex files, changed index.html, database structure SQL file, PHP backend files)
- view example (run in two different browsers [e.g. Firefox and Safari], so you can login to different Facebook accounts/sessions)
- Try Flash P2P app deployed on Facebook
I’ve split the whole connection and login process into 4 basics steps.
- First we connect to Facebook via our account and get user info + all friends using the same application.
- Second we connect to Adobe Stratus rendezvous service and get unique fingerprint
- Third we pair P2P fingerprint with our Facebook UID (user ID)
- Finally we establish connection between two peers and add other util functions like keepConnectionAlive
Step 1: Connect to Facebook
If our app is already deployed on Facebook - it just passes loaderInfo fb_sig_session_key to the app and you can verifySession. If you are debugging in Flash Builder - then you’d need wait until new window opens and hit OK in Alert.
private function connectToFacebook():void{ fsession=new FacebookSessionUtil(apiKey,apiSecret,loaderInfo); fsession.addEventListener(FacebookEvent.CONNECT,onConnect); fbook=fsession.facebook; if(loaderInfo.parameters.fb_sig_session_key){ fsession.verifySession(); }else{ fsession.login(); Alert.show("Click OK after you log into Facebook","Login",Alert.OK,this,alertClickHandler); } txtStatus.text = "Facebook Login"; }
Once we get successfully connected to Facebook API, we can retrieve information about our user:
var call:FacebookCall=fbook.post(new GetInfo([fbook.uid],[GetInfoFieldValues.ALL_VALUES])); call.addEventListener(FacebookEvent.COMPLETE,onGetInfo);
Then you can work with user values like first_name, last_name
myUser=(e.data as GetInfoData).userCollection.getItemAt(0) as FacebookUser; txtTitle.text=myUser.first_name+" "+myUser.last_name;
Next step is to retrieve all friends using the app. The effective way is to use FQL (Facebook Query Language) - similar to SQL. Also have a look at Sample FQL Queries to understand FQL better.
Our code for this will look like:
private function getAllAppFriends():void{ var query:String = "SELECT uid,name FROM user WHERE is_app_user = 1 AND uid IN (SELECT uid2 FROM friend WHERE uid1 = "+fbook.uid+")"; var fql:FqlQuery = new FqlQuery(query); var call:FacebookCall=fbook.post(fql); call.addEventListener(FacebookEvent.COMPLETE,onFQL); CursorManager.setBusyCursor(); }
Once you get onFQL result, you have to work with the data right way. It returns XML with namespaces, which you have to consider in your code.
private function onFQL(e:FacebookEvent):void{ var fbData:FacebookData = e.data; if(fbData == null){ Alert.show(e.error.reason); return; } namespace ns = "http://api.facebook.com/1.0/"; use namespace ns; var result:XML = XML(fbData.rawResult); var users:XMLList = result.user; myAppFriends = new ArrayCollection(); for(var i:uint=0;i<users.length();i++){ var user:XML = users[i]; trace(user.name); myAppFriends.addItem({name:user.name,uid:user.uid}); } if(myAppFriends.length>0){ connectToP2P(); }else{ Alert.show("None of your friends is using this app. Tell some friends and reload"); } }
Now - you have your app connected to Facebook, retrieved info about your user and all your friends using this app.
Step 2 - connecting to Adobe Stratus
I am not going to dive into this step - all info you need to know is explained in the tutorial about P2P in Flash + in this tutorial we have added Camera and Microphone.
Step 3 - fingerprint exchange
Fingerprint exchange is a Zend_AMF service running on top of PHP server with MySQL database.
The important thing here is that we pair UID from Facebook (facebook_uid) with Fingerprint ID from Stratus (fingerprint) with timestamp last_update
MySQL table will then look like this:
CREATE TABLE `connection` ( `id` int(11) NOT NULL AUTO_INCREMENT, `facebook_uid` int(11) NOT NULL, `fingerprint` varchar(260) NOT NULL, `last_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `facebook_uid` (`facebook_uid`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;
You can easily create your own service using Data/Services panel in Flash Builder 4.
The class should contain 4 important methods:
- createConnection
- updateConnection
- aliveConnection (for keeping connection alive, just updates the last_update field with CURRENT_TIMESTAMP every 5 seconds using Timer)
- getAvailableFriends
getAvailableFriends retrieves all your friends with their Stratus fingerprint being alive for last 5 seconds. This is the SQL statement. We are using keyword IN, which enables you to search in an array. As array, we pass all our friends using our app - basically, the array of UIDs, we have retrieved from Facebook in the previous FQL statement.
SELECT * FROM $this->databasename.$this->tablename WHERE facebook_uid IN (".implode(',',$friendUIDs).") AND last_update>NOW()-INTERVAL 5 SECOND;
Once you get all your available friends on Stratus, you can list them and by choosing one of them establish finally P2P connection.
Deploying on Facebook
Set up new application - give it some name, open settings and tab Canvas. Upload your compiled project to your server and set Required URLs in a similar way:

On the same page set Render method as iFrame.
Your settings should now point to index.html file located on your server. It’s a bit changed embed from default generated, so it can pass through the fb_sig_session_key parameter to SWF.
<html> <head> <title>P2P app on Facebook</title> <!-- include swfobject library --> <script type="text/javascript" src="swfobject.js"></script> </head> <body> <script type="text/javascript"> //define your flashVars from the URL GET string var flashVars = {}; var strHref = window.location.href; if ( strHref.indexOf("?") > -1 ) { var strQueryString = strHref.substr(strHref.indexOf("?")+1); var aQueryString = strQueryString.split("&"); for ( var iParam = 0; iParam < aQueryString.length; iParam++ ) { var aParam = aQueryString[iParam].split("="); flashVars[aParam[0]] = aParam[1]; } } //create your instance of your SWF swfobject.embedSWF("P2PFacebookChat.swf", "flashContent", "100%", "100%", "9.0.0", "expressInstall.swf", flashVars); </script> <!-- this is where your flash content will be placed when created --> <div id="flashContent"></div> </body> </html>
I wish you good luck! Please leave me comments if you are having any difficulties with running the demo.
My session from MAX 2009: Social Media Experiences with Flash Media and RTMFP
22 Comments »
RSS feed for comments on this post. / TrackBack URL



Really nice!! Does Stratus still beta?
Comment by Gil Beyruth — October 14, 2009 @ 5:20 pm
Stratus is meant to be always beta - it’s emerging technology, where we put and test latest Adobe Flash Media technologies. Integration of P2P will be also officially integrated into future FMS server.
Comment by tom — October 14, 2009 @ 5:46 pm
I was able to make it to your session at MAX this year, nicely done Tom! It inspired me to dig into Facebook and multi-user integration myself.
Thanks for sharing, this was a big help!
Comment by Elliot James Chong — October 15, 2009 @ 1:39 am
Hi Tom,
can you plaese advice me somebody , who can help us in making a real p2p videochat on our WEB dating site ? We have it already on FMS , and wanted to upgrade to Stratus. Our concern is NAT and FIREWALL difficulties. I will appriciate your help. Thank you in advance.
Victor
Comment by Victor — October 15, 2009 @ 9:58 am
Hi Victor,
so for this purpose you have to do a failover solution - means, when people can connect via P2P, then do so, if not, use FMS.
This is e.g. nicely solved in LiveCycle Collaboration Service
http://www.adobe.com/products/livecycle/collaborationservice/
Comment by tom — October 15, 2009 @ 6:20 pm
Hi Victor, we are working allready on P2P videochat and works great, we still are researching about the capabilities and limits. SO far look so good and if u need a developer for your site we can do it!
maureyno@gmail.com
Mauricio
Comment by Maurice — October 21, 2009 @ 9:04 pm
my stratus attempts
http://apps.facebook.com/callbook/
Comment by Yoz — October 22, 2009 @ 5:39 pm
Have a look:
http://apps.facebook.com/friendlycam/
Comment by Jose Luis Ugia — October 23, 2009 @ 5:47 pm
I get, NetConnection event: NetConnection.Connect.Failed, I use proxy server in the organisation, is that blocking the communication?
Comment by Rishi — November 3, 2009 @ 8:55 am
Hello Tom, I have one question about NearID and FarID.
I call for the first time NetConnection.connect(developer key) etc. and get back the NetConnection event. When I look inside the event.target there is a farID and a nearID. I’m currently getting my program to work so that I publish my nearID to the other peers and they use it as the farID. This is correct, right? However, I’m curious to what is the first farID that we get and is it good for anything?
Best regards,
Pekka
Comment by Pekka Kuismanen — November 4, 2009 @ 5:01 pm
I think it’s the ID of Stratus service. As Stratus behaves also as peer client.
Comment by tom — November 4, 2009 @ 10:02 pm
OK Thanks! I had one question about ReceiveStream and its client. Let’s say I have 3 ReceiveStreams connected to 3 peers. I also have a client where all the functions are defined for receiving data. Now, can I use one instance of the client that will handle all the 3 ReceiveStreams or should I create 3 instances of the client, i.e., one client for every ReceiveStream? I couldn’t find any info about this so sorry to bother you :). Thanks again!
-Pekka
Comment by Pekka Kuismanen — November 8, 2009 @ 8:03 pm
Sorry, I meant NetStream that’s used for receiving when I wrote ReceiveStream.
Comment by Pekka Kuismanen — November 8, 2009 @ 10:50 pm
Pekka, I think you have to create 3 instances for two-way communication. But there might be probably one instance enough just for sending and 3 receiving. I am not 100% sure about this. Just go ahead and try, but anyway - All these kind of multi-user things will be solved in Flash Player 10.1, where you have Groups and Multicast available - so it’s going to be much easier to handle this.
Comment by tom — November 10, 2009 @ 5:42 pm
I meant 3 instances for 3 streams 3 way communication
Comment by tom — November 10, 2009 @ 6:39 pm
Yes for just sending to many peers one instance of sendStream seems to be enough. For both sending and receiving I can get 2 peers working, but when the third comes in it just becomes too hard to imagine how it goes haha. I’ll try to instanciate every receiveStream into a separate instance, take the farIDs from DB and start it that way. Any info when is the 10.1 coming? haha Thanks again! Pekka
Comment by Pekka Kuismanen — November 11, 2009 @ 6:59 pm
Just stay tuned .)
Comment by tom — November 12, 2009 @ 11:46 am
Got it working now. However, when the third peer enters, it starts to lag really badly. I have 1 sendStream and 2 receiveStream instances in the case of 3 peers. There’s only one client instance for the 2 receiveStreams. Could this be causing the lag? I’ll try next if I can get it to work by having one client instance for every receiveStream and combine the data myself. Not sure why it should lag like that.
-PK
Comment by Pekka Kuismanen — November 13, 2009 @ 12:07 am
I would rather wait till Flash Player 10.1 for Groups and Multicast stuff as it is going to be much clear and proper to do such things.
Btw: have a look at this article: http://blog.yoz.sk/2009/10/p2pmulticast/
Comment by tom — November 13, 2009 @ 12:33 am
test test comment
Comment by test — November 24, 2009 @ 3:24 pm
Hey guys ,
I was just starting on doing one of these. I have a problem , can you help please.
When I get my netconnection.nearID (nc.nearID) and try and display it in aan Alert box like , Alert.show(”This is ” + nc.nearID); I dont get anything ( Alert.show(”This is ” ); works fine)? Is this normal , I can see nc.uri or nc.toString(). So what is going on ?
Any help greatly appreciated.
Comment by davet — January 21, 2010 @ 2:10 pm
pure p2p video conferences on http://apps.facebook.com/onconference/
Comment by Yoz — February 9, 2010 @ 11:34 am