Flash Policy on same port as websocket server

877 views
Skip to first unread message

Hans Ahrens

unread,
Nov 13, 2012, 5:36:56 PM11/13/12
to ratch...@googlegroups.com
Hello,

For Internet Explorer 7,8 and a custom flash tool we need to have a flash policy.
At the moment i have a flash policy file running for port 843 but some clients block that por so i want to also run it on port 80  (same port as the websocket server) since flash will look there if it cant reach port 843 but then i get an error that the port is already occupied: 

PHP Fatal error:  Uncaught exception 'React\Socket\ConnectionException' with message 'Could not bind to tcp://0.0.0.0:80: Address already in use' in /websocket/vendor/react/socket/React/Socket/Server.php:23

Is there a solution so i can run the flash policy on the same port als the websocket server ? 
The code i use to start the websocket server + flash policy is the following : 

    $loop = Factory::create();

    // Setup our Ratchet ChatRoom application
    $webSock = new Reactor($loop);
    $webSock->listen(80, '0.0.0.0');
    $webSock->listen(8080, '0.0.0.0');
    $webServer = new IoServer(           // Basic I/O with clients, 
        new WsServer(                    // WebSockets
           new ServerProtocol(  // WAMP
               new wampserver
           )
        )
      , $webSock
    );

    // Allow Flash sockets (Internet Explorer) to connect to our app
    $flashSock = new Reactor($loop);
    $flashSock->listen(843, '0.0.0.0');
    $policy = new FlashPolicy;
    $policy->addAllowedAccess('*', 80);
    $policy->addAllowedAccess('*', 8080);
    $policy->addAllowedAccess('*', 443);
    $webServer = new IoServer($policy, $flashSock);

    // Start Event Loop
    $loop->run();


cboden

unread,
Nov 13, 2012, 11:04:41 PM11/13/12
to ratch...@googlegroups.com
Hi Hans,

First off, this reply is off the top of my head, so may be wildly incorrect.  I'll try to point you in the right direction and will test this out this weekend.  :)

What you'll need to do is have both your application ("wampserver"?) and a FlashPolicy instance running off your $webServer.  Now, I THINK after Flash fails to connect on 843 it will make a request to http://sameserver:80/crossdomain.xml -- You'll have to parse that on an onOpen inside the connection object: $conn->WebSocket->request->getPath() and pass that onOpen to FlashPolicy instead of your class.

Here is a bit of code on how to setup some (hackish) routing: https://gist.github.com/2953926 - I hope in the near future to implement good (Symfony) routing in Ratchet and in turn make supporting IE easier to set up.

Let me know if that helps/works.  If not, when I get the time this weekend I'll come up with a working and tested solution.

P.S. Any reason you're running your app on both port 80 and 8080?

Cheers!

Hans Ahrens

unread,
Nov 15, 2012, 8:23:23 AM11/15/12
to ratch...@googlegroups.com
Hi Chris,

Thank you for your quick response.

The reason that i am running my app on both port 80 and 8080 is because allot of time's ports are blocked by company's. So when the client detects that port 80 is blocked we will use port 8080.
For example on mobile phone networks port 80 for websockets only works with 1 of the 5 service providers so the client automatically switches to port 8080.
I have also setup Stunnel for SSL on port 443 for if both port 80 and 8080 are blocked this way we have the most change of getting a working connection. 
If you are interested i cant send you the JS code we use for testing if we have a working connection. ( It loops through an array of possible ports and if it has a connection it continues else it give's an error page.)

The link you gave me for setting up the routing helped me allot,i have a test setup running and everything looks te be working.
The code that i have is the following:

Code for starting the server:
    $loop = Factory::create();

    $webSock = new Reactor($loop);
    $webSock->listen(80, '0.0.0.0');
    $webSock->listen(8080, '0.0.0.0');
    $webSock->listen(843, '0.0.0.0');
    
    $router = new wampserverRouter;
    
    $webServer = new IoServer($router, $webSock);


Router Code:
<?php
namespace Ratchet\Website;
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
use Ratchet\Server\FlashPolicy;

use Ratchet\WebSocket\WsServer;
use Ratchet\Wamp\ServerProtocol;
use Ratchet\Website\wampserver;

class wampserverRouter implements MessageComponentInterface {    
    private $policy;
    private $wamp; 

    public function __construct() {        
        //Setup Flash Server
        $this->policy = new FlashPolicy;
        $this->policy->addAllowedAccess('*', 80);
        $this->policy->addAllowedAccess('*', 8080);
        $this->policy->addAllowedAccess('*', 443);
        
        //Setup Wamp Server
        $this->wamp = new WsServer(  // WebSockets
           new ServerProtocol(  // WAMP
               new wampserver
           )
        );
    }


    public function onOpen(ConnectionInterface $conn){
       //Set default route to the wamp server
       $conn->route = $this->wamp;
       $conn->route->onOpen($conn);
       
       //Set first message to true
       $conn->firstMessage = true;
    }

    public function onMessage(ConnectionInterface $from, $msg) {  
    //If first message is true check if we have a policy file request      
        if($from->firstMessage){
        $from->firstMessage = false;
$flashPolicyRequest = strpos($msg, 'policy-file-request');
if ($flashPolicyRequest !== false) {
                             //Send an onclose to websocket class
             $from->route->onClose($from);
   
                             //Change route to flash policy
    $from->route = $this->policy;
}
}
   $from->route->onMessage($from, $msg);
    }

    public function onClose(ConnectionInterface $conn){
        if (isset($conn->route)){
          $conn->route->onClose($conn);
        }
    }

    public function onError(ConnectionInterface $conn, \Exception $e) {
        $conn->route->onError($conn, $e);
    }
}


What i do is set the default onOpen event to websockets because with on open i cant see what for connection i am getting.
Then on the first onMessage i check if the message has the string  'policy-file-request'  if that is the case then i send an onclose to the websocket server and the route change's to the flash policy server and the on message event will be send to it.
I know it's a  hack to do it this way but i could not find another way. 

The reason that i use this is because i cant create the server with new WsServer(). If i do that then i wont recieve any message's from the flash policy request because it does not come as a websSocket request and because i can't start it with that i cant use conn->WebSocket->request->getPath(). 
I tried allot of other ways to detect if i had a websockets or a flash policy request in the on open but i could not find a way.

If you know a better way then i would gladly hear it,else i think that we are going to use this code if no new problems come up.

Best Regards,
Hans

Op woensdag 14 november 2012 05:04:41 UTC+1 schreef cboden het volgende:

cboden

unread,
Nov 17, 2012, 2:57:37 PM11/17/12
to ratch...@googlegroups.com
Hi Hans,

That is a glorious hack!  Well done!

That also would be the only way to server a crossover.xml file on the same port at the moment.  Right now handling HTTP connections and upgrading them to WebSocket connections happen in WsServer.php - These two actions need to be decoupled in order to allow more flexility.  That should let you serve the file based on a route.

Cheers.
Reply all
Reply to author
Forward
0 new messages