The Adobe Stratus Beta Sample App and PHP/MySQL
Posted by: Bob de Wit in AIR, ActionScript, Flex
There is a new ActionScript 3.0 API in Flash Player 10 to support RTMFP, allowing for some really exciting stuff with regard to C2C (Client-To-Client) communications between Flex apps. This requires you to set up an account and a callback URL with the Adobe Stratus beta. There’s a really cool Stratus sample application on Adobe Labs, unfortunately the callback script syntax and responses are not described in much detail. This article attempts to reconstruct this and provide some PHP/MySQL code to work with Stratus.
Introduction
Flash Player 10 and Adobe AIR 1.5 introduce a new communications protocol called the Real-Time Media Flow Protocol (RTMFP). The most important features of RTMFP include low latency, end-to-end peering capability, security and scalability. These properties make RTMFP especially well suited for developing real-time collaboration applications by not only providing superior user experience but also reducing cost for operators.
In order to use RTMFP, Flash Player endpoints must connect to an RTMFP-capable server, such as the Adobe Stratus service. Stratus is a beta, hosted rendezvous service that aids establishing communications between Flash Player endpoints. Unlike Flash Media Server, Stratus does not support media relay, shared objects, scripting, etc. So by using Stratus, you can only develop applications where Flash Player endpoints are directly communicating with each other.
Connecting to the Stratus service and creating end-to-end media streams are analogous to working with Flash Media Server. Please note that you must use ActionScript 3.0 with either Flash Professional CS4 or Flex Builder 3 targeting Flash Player 10 or AIR 1.5.
For details, check these resources:
Please read these carefully as I’m not going to repeat what’s described there.
The Callback Script
The python callback script (reg.cgi) included with the sample source is a bit cryptic:
So let’s see if we can make a better documented PHP/MySQL equivalent of this.
The Database
I’ve created a database in MySQL using the following script:
CREATE TABLE IF NOT EXISTS `registrations` ( `id` BIGINT(20) NOT NULL AUTO_INCREMENT, `appid` BIGINT(20) NOT NULL DEFAULT '0', `username` VARCHAR(60) NOT NULL DEFAULT '', `identity` VARCHAR(120) NOT NULL DEFAULT '', `updated` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00', PRIMARY KEY (`id`), KEY `updated` (`updated`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1;
The appid field is not really required, I plan to use it to distinghuish between connects from various apps.
Callback Scenarios
So far I’ve found three callback scenarios:
- The user connects
- The user disconnects
- The user calls another user (by passing the username)
The user connects
The REST-based call Stratus will make to your callback URL looks like this:
http://your.domain/reg.php?username=foo&identity=1234
Stratus expects you to return a simple XML document:
<result> <updated>true</updated> </result>
where updated is true or false depending on whether the database was updated.
The user disconnects
Exactly the same REST call as for a connect, except that the identity value will be ZERO.
The user calls another user
The REST-based call Stratus will make to your callback URL looks like this:
http://your.domain/reg.php?friends=foo
Stratus expects you to return a simple XML document:
<result> <friend> <user>foo</user> <identity>1234</identity> </friend> </result>
PHP Code
I’m using a fairly straightforward Database abstraction class here. There’s also a simple LogFile() function in the code that dumps the entire callback request to a text file. Zipped code with my database class and XML templates is here.
//**************************************************************************** // Database Configuration //**************************************************************************** require_once('Database.php'); define('DB_HOST', 'localhost'); define('DB_USER', 'stratus'); define('DB_PW', '******'); define('DB_DBNAME', 'db_stratus'); //**************************************************************************** // Validation of script call //**************************************************************************** //Log the entire request into a log file for easy inspection LogFile($_REQUEST); //Check if the request contains a value for "friends" or for "username/identity" $valid = false; if( isset( $_REQUEST['friends'] )) { $valid = true; ProcessFriendRequest(); } if( (isset($_REQUEST['username']) && (isset($_REQUEST['identity'])) )) { $valid = true; ProcessRegistration(); } if(! $valid ) { ProcessError(); } //**************************************************************************** // Process a friend request //**************************************************************************** function ProcessFriendRequest() { $db = new Database(); $query = sprintf("SELECT id, appid, username, identity, updated FROM registrations WHERE username='%s'", mysql_real_escape_string($_REQUEST['friends'])); LogFile($query); $result = $db->GetObject($query); if(! $result) { $update = 'false'; $reply = file_get_contents('update.xml'); $reply = str_replace('$update', $update, $reply); echo $reply; } else { //Get the XML Response Template file and format it $reply = file_get_contents('friends.xml'); $reply = str_replace('$user', $result->username, $reply); $reply = str_replace('$identity', $result->identity, $reply); LogFile($reply); echo $reply; } } //**************************************************************************** // Process a registration (identity will be 0 when disconnecting) //**************************************************************************** function ProcessRegistration() { $db = new Database(); $query = sprintf("SELECT id, appid, username, identity, updated FROM registrations WHERE username='%s'", mysql_real_escape_string($_REQUEST['username'])); LogFile($query); $result = $db->GetObject($query); if(! $result) { //Record does not exist yet $update = "true"; $sql = sprintf("INSERT INTO registrations (appid, username, identity, updated) VALUES ( 0, '%s', '%s', NOW())", mysql_real_escape_string($_REQUEST['username']), mysql_real_escape_string($_REQUEST['identity'])); $db->execute($sql); LogFile($sql); } else { //Record already exists $update = "true"; $sql = sprintf("UPDATE registrations SET updated = NOW(), identity = '%s' WHERE username = '%s'", mysql_real_escape_string($_REQUEST['identity']), mysql_real_escape_string($_REQUEST['username'])); $db->execute($sql); LogFile($sql); } //Get the XML Response Template file and format it $reply = file_get_contents('update.xml'); $reply = str_replace('$update', $update, $reply); LogFile($reply); echo $reply; } //**************************************************************************** // Process an error //**************************************************************************** function ProcessError() { $update = 'false'; $reply = file_get_contents('update.xml'); $reply = str_replace('$update', $update, $reply); LogFile($reply); echo $reply; } //**************************************************************************** // Log File function //**************************************************************************** function LogFile($msg) { $smsg = print_r($msg, true); $time = date("F jS Y, h:iA"); $ip = $REMOTE_ADDR; $referer = $HTTP_REFERER; $browser = $HTTP_USER_AGENT; $fp = fopen("log.txt", "a"); fputs($fp, "Time: $time IP: $ipReferer: $referer Browser: $browser | $smsg"); fclose($fp); }

Entries (RSS)
[...] Go here to see the original: Code! » The Adobe Stratus Beta Sample App and PHP/MySQL [...]
[...] Adobe Labs Stratus Sample Application w/source Tutorial and Downloadable Files from Influxis.com Stratus Application Using PHP/MySQL Stratus, Python, and File Sharing Stratus [...]