Friday, September 26, 2008

Flash loadPolicyFile() - how to impliment loadPolicyFile in proper way / correct way and how to host loadPolicyFile using PHP

For those people who are searching for XMLSocket function to work properly, I will tell you step by step on how to create PHP socket server to support XMLSocket function in Flash, and also how to host your crossdomain.xml so it can be use by the Flash 9 loadPolicyFile function.

Step 1:

Since Flash 9 do not support loading the crossdomain.xml file directly by url, we must first create a socket to host the crossdomain.xml.

PHP (policySocketServer.php):

#!/usr/bin/php -q
<?php
error_reporting(E_ALL);
set_time_limit(0);
ob_implicit_flush();
function __autoload ($className)
{
$fileName = "Classes/".str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';
$status = (@include_once $fileName);
if ($status === false) {
eval(sprintf('class %s {func' . 'tion __construct(){throw new Project_Exception_AutoLoad("%s");}}', $className, $className));
}
}
$ip = '127.0.0.1'; //change it to your webserver path
$port = 9996; //any port no you wish and it must be greater than 1024

//new SocketServer($ip, $port);
try{
$mySocketServer = new SocketServer($ip, $port);
} catch (Project_Exception_AutoLoad $e) {
//echo "FATAL ERROR: CAN'T FIND SOCKET SERVER CLASS.";
}
?>


Create a folder named Classes, and inside the folder create Logger.php and SocketServer.php

PHP (Logger.php):

<?php
class Logger
{
private static $instance;
public static function getInstance()
{
if(!isset($instance))
$instance = new Logger();
return $instance;
}
function __construct()
{
}

function log($message)
{
//echo "[".date('Y-m-d')."] ".$message."\n";
}
}

?>


PHP (SocketServer.php):

<?php
class SocketServer
{
var $ip;
var $port;
var $masterSocket;
var $logger;
private $currentSockets;

function __construct($ip, $port)
{
$this->ip = $ip;
$this->port = $port;
$this->logger = Logger::getInstance();
$this->initSocket();
$this->currentSockets = array();
$this->currentSockets[] = $this->masterSocket;
$this->listenToSockets();
}

private function initSocket()
{

//---- Start Socket creation for PHP 5 Socket Server -------------------------------------

if (($this->masterSocket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) < 0)
{
$this->logger->log("[SocketServer] "."socket_create() failed, reason: " . socket_strerror($this->masterSocket));
}
socket_set_option($this->masterSocket, SOL_SOCKET,SO_REUSEADDR, 1);
if (($ret = socket_bind($this->masterSocket, $this->ip, $this->port)) < 0) {
$this->logger->log("[SocketServer] "."socket_bind() failed, reason: " . socket_strerror($ret));
}

if (($ret = socket_listen($this->masterSocket, 5)) < 0) {
$this->logger->log("[SocketServer] "."socket_listen() failed, reason: " . socket_strerror($ret));
}
}

private function parseRequest($socket, $data)
{
if(substr($data,0, 22) == "<policy-file-request/>")
{
//echo "POLICY FILE REQUEST\n";
$crossFile = file("http://localhost/crossdomain.xml"); //put your domain url where you uploaded the crossdomain.xml, it can also be any online webserver path
$crossFile = join('',$crossFile);
$this->sendMessage(array($socket),$crossFile);
return;
}
}

public function sendMessage($sockets, $message)
{
$message .= "\0";
if(!is_array($sockets))
$sockets = array($sockets);
foreach($sockets as $socket)
{
if($socket === NULL)
continue;
socket_write($socket, $message, strlen($message));
//$this->logger->log("[SocketServer] Wrote : ".$message." to ".$socket);
}
}

private function listenToSockets()
{
//---- Create Persistent Loop to continuously handle incoming socket messages ---------------------
while (true) {
$changed_sockets = $this->currentSockets;
$num_changed_sockets = socket_select($changed_sockets, $write = NULL, $except = NULL, NULL);
foreach($changed_sockets as $socket)
{
if ($socket == $this->masterSocket) {
if (($client = socket_accept($this->masterSocket)) < 0) {
$this->logger->log("[SocketServer] "."socket_accept() failed: reason: " . socket_strerror($socket));
continue;
} else {
// NEW CLIENT HAS CONNECTED
$this->currentSockets[] = $client;
socket_getpeername($client, $newClientAddress);
$this->logger->log("[SocketServer] "."NEW CLIENT ".$client." [IP: ".$newClientAddress."]");
}
} else {
$bytes = socket_recv($socket, $buffer, 4096, 0);
if ($bytes == 0) {
// CLIENT HAS DISCONNECTED
$this->logger->log("[SocketServer] "."REMOVING CLIENT ".$socket);
$index = array_search($socket, $this->currentSockets);
// Remove Socket from List
unset($this->currentSockets[$index]);
socket_close($socket);
}else{
// CLIENT HAS SENT DATA
$this->parseRequest($socket, $buffer);
}
}
}
}
}
}
?>


Create the crossdomain.xml file and put it in your webserver root:

XML (crossdomain.xml):

<cross-domain-policy>
<allow-access-from domain="*" to-ports="*"/>
</cross-domain-policy>


Step 2 (if you're running on local server):

Create a batch file in your desktop named runPolicyFile.bat:

Bat (runPolicyFile.bat):

c:/wamp/bin/php/php5.2.5/php.exe -q c:/wamp/www/policySocketServer.php

Click the batch file to run the script (make sure you have your webserver is up and running).

Alternative way is to run the policySocketServer.php straight away in your web browser.


Step 3:

In your flash file, include this script:

System.security.allowDomain("*");
System.security.loadPolicyFile("xmlsocket://127.0.0.1:9996"); //your webserver path and the port number you choose


You're done

You should be able to see that your XMLSocket function working now in the web browser :)

Check out the demo here . I have successfully implement PURE PHP SOCKET SERVER to build this chat application in Flash through XMLSocket function.
Any comment appreciated..

No comments: