A Flash Developer Resource Site

Results 1 to 3 of 3

Thread: Sockets and policy-file-request [PHP-AS3]

  1. #1
    Senior Member
    Join Date
    Nov 2003
    Location
    Las Vegas
    Posts
    770

    Sockets and policy-file-request [PHP-AS3]

    I'm working on a multi-user app, and using sockets for communication. I can connect fine when using either localhost, 127.0.0.1, or my IP when running the swf from the harddrive. I need to be able to server a response to the <policy-file-request> to be able to connect across domains. I can't use the standard http method since the final socket server may be on a server with no http server (load balancing is still in the works).

    How do you format the response to the <policy-file-request> when using a PHP socket server? Do I need to send XML headers first, or just the XML itself?

    Here's the server code:
    PHP Code:
    #!/usr/bin/php -q
    <?php

    error_reporting
    (E_ALL);

    set_time_limit(0);

    ob_implicit_flush();

    $address '192.168.2.4';
    $port 9999;

    //---- Function to Send out Messages to Everyone Connected ----------------------------------------
    function send_Message($allclient$buf) {
      global 
    $client_list;
      foreach(
    $allclient as $client) {
        if(
    $client_list[$client]['state'] && $client_list[$client]['nick'] != ""){
          
    socket_write($clienttrim($buf).chr(0));
        }
      }
    }

    //---- Function to Send List of  Everyone Connected ----------------------------------------
    function who($allclient$socket) {
      global 
    $client_list;
      
    $buf "";
      
    $counter 0;
      foreach(
    $allclient as $client) {
        
    $buf.=$client_list[$client]['nick'].", ";
        
    $counter++;
      }
      
    socket_write($socket"There are $counter people in this room: $buf".chr(0));
    }

    //---- Function to Send out Messages to Individuals ----------------------------------------
    function send_Single($socket$buf) {
      
    socket_write($socket$buf.chr(0));
    }



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

    if (($master socket_create(AF_INETSOCK_STREAMSOL_TCP)) < 0) {
      echo 
    "socket_create() failed, reason: " socket_strerror($master) . "\n";
    }

    socket_set_option($masterSOL_SOCKET,SO_REUSEADDR1);


    if ((
    $ret socket_bind($master$address$port)) < 0) {
      echo 
    "socket_bind() failed, reason: " socket_strerror($ret) . "\n";
    }


    if ((
    $ret socket_listen($master5)) < 0) {
      echo 
    "socket_listen() failed, reason: " socket_strerror($ret) . "\n";
    }



    $read_sockets = array($master);
    $client_list = array($master);

    //---- Create Persistent Loop to continuously handle incoming socket messages ---------------------
    while (true) {
      
    $changed_sockets $read_sockets;

      
    $num_changed_sockets socket_select($changed_sockets$write NULL$except NULLNULL);

      foreach(
    $changed_sockets as $socket) {

        if (
    $socket == $master) {

          
    //---- Accept Incoming Connections and Request Nickname ----------------------------------------
          
    if (($client socket_accept($master)) < 0) {
            echo 
    "socket_accept() failed: reason: " socket_strerror($msgsock) . "\n";
            continue;
          } else {
        echo 
    "[connection]:$client\n";
            
    array_push($read_sockets$client);
        
    $client_list[$client]['state'] = false;
        
    send_Single($client"<b>Enter a nickname:<b>");
          }
        } else {

          
    //---- Grab Incoming Messages From all Users ----------------------------------------
          
    $bytes socket_recv($socket$buffer20480);

          
    //---- Handle User Disconnects ----------------------------------------
          
    if ($bytes == 0) {
        
    $nick $client_list[$socket]['nick'];
            
    $iindex array_search($socket$client_list);
            unset(
    $client_list[$iindex]);
            
    $index array_search($socket$read_sockets);
            unset(
    $read_sockets[$index]);
            
    socket_close($socket);
            
    $allclients $read_sockets;
            
    array_shift($allclients);
        if(
    $client_list[$socket]['nick'] != "" && $client_list[$socket]['nick'] != "<policy-file-request/>"){
              
    send_Message($allclients"$nick has left the room");
        }
          }else{
        if(
    $bytes){
              
    //---- Set Nickname ----------------------------------------
          
    if($client_list[$socket]['state'] === false){
            
    $client_list[$socket]['nick'] = $tempBuf trim(trim($buffer));
            echo 
    $tempBuf." test";
            
    send_Single($socket"Hello $tempBuf!  Welcome to the game!");
                
    $allclients $read_sockets;
                
    array_shift($allclients);
            
    who($allclients$socket);
            if(
    $client_list[$socket]['nick'] != "" && $tempBuf != "<policy-file-request/>"){
                  
    send_Message($allclients$client_list[$socket]['nick']." has entered the game.");
            }
            
    $client_list[$socket]['state'] = true;
          }else{
                
    //---- Check Message for Commands, and Respond or Broadcast Message ----------------------------------------
                
    $allclients $read_sockets;
                
    array_shift($allclients);
            if(
    trim($buffer) == "/who"){
              
    who($allclients$socket);
            }else{
                  
    send_Message($allclients$client_list[$socket]['nick']." wrote: ".$buffer);
            }
          }
        }
          }
        }
      }
    }

    ?>
    Here's the AS3 chat class (compiled with Flex/mxmlc):
    PHP Code:
    package{

        
    import flash.display.*;
        
    import flash.events.*;
        
    import flash.text.*;
        
    import flash.net.*;

        public class 
    chat extends Sprite {

            private var 
    socket:XMLSocket;
            private var 
    msgArea:TextField = new TextField();
            private var 
    inputMsg:TextField = new TextField();
            private var 
    lastMessage:String "";
            private var 
    connected:Boolean false;

            public function 
    chat() {
                
    msgArea.x=15;
                
    msgArea.y=15;
                
    msgArea.width=450;
                
    msgArea.height=150;
                
    msgArea.multiline=msgArea.border=msgArea.background=true;
                
    addChild(msgArea);

                
    inputMsg.x=15;
                
    inputMsg.y=170;
                
    inputMsg.width=415;
                
    inputMsg.height=20;
                
    inputMsg.type=TextFieldType.INPUT;
                
    inputMsg.multiline=false;
                
    inputMsg.selectable=inputMsg.border=inputMsg.background=true;
                
    inputMsg.text="192.168.2.4";
                
    addChild(inputMsg);

                var 
    pushMsg:Sprite = new Sprite();
                var 
    pushText:TextField = new TextField();
                
    pushText.x=400;
                
    pushText.y=170;
                
    pushText.selectable=false;
                
    pushText.autoSize='center';
                
    pushText.text='Send';
                
    pushText.border=pushText.background=true;
                
    pushMsg.useHandCursor=true;
                
    pushMsg.addChild(pushText);
                
    pushMsg.addEventListener(MouseEvent.MOUSE_DOWNmsgGo);
                
    addChild(pushMsg);

                
    socket = new XMLSocket();
                
    configureListeners(socket);
                
    msgArea.htmlText lastMessage "<b>Enter IP address of the server, then click the \"Send\" button</b>";

            }

                private function 
    configureListeners(dispatcher:IEventDispatcher):void {
                        
    dispatcher.addEventListener(Event.CLOSEcloseHandler);
                        
    dispatcher.addEventListener(Event.CONNECTconnectHandler);
                        
    dispatcher.addEventListener(DataEvent.DATAdataHandler);
                
    dispatcher.addEventListener(SecurityErrorEvent.SECURITY_ERRORsecurityErrorHandler);
                   }

            private function 
    securityErrorHandler(event:SecurityErrorEvent):void {
                
    msgArea.htmlText += "<br>securityErrorHandler: " event;
            }

            private function 
    connectHandler(success:Boolean):void 
                if (
    success) { 
                    
    msgArea.htmlText lastMessage '<br>' '<b>Server connection established!</b>'
                    
    lastMessage '<b>Server connection established!</b>';
                    
    connected true;
                } else { 
                    
    msgArea.htmlText lastMessage '<br>' '<b>Server connection failed!</b>'
                    
    lastMessage '<b>Server connection failed!</b>';
                } 
            } 

            private function 
    closeHandler(event:Event):void 
                
    msgArea.htmlText lastMessage '<br>' '<b>Server connection lost</b>'
                
    lastMessage '<b>Server connection lost</b>';
            } 

            private function 
    dataHandler(event:DataEvent):void 
                
    msgArea.htmlText lastMessage '<br>' event.data;
                
    lastMessage event.data
            } 

            private function 
    msgGo(event:MouseEvent):void{
                if(!
    connected){
                    
    msgArea.htmlText lastMessage "<b>Contacting Server...</b>";
                    
    socket.connect(inputMsg.text,9999);
                }else{
                    if (
    inputMsg.text != '') { 
                        
    socket.send(inputMsg.text); 
                    } 
                }
                
    inputMsg.text ''
            }

        }

    And here's the AS2 version (compiled with Ming/PHP):
    PHP Code:
    <?

    ming_useswfversion(7);
    $movie=new SWFMovie(7);
    $movie->setDimension(550,200);
    $movie->setBackground(255,255,255);
    $movie->setRate(30);

    $actions="

    createTextField('msgArea', getNextHighestDepth(), 15, 17, 450, 150);
    with(msgArea){
    border=background=html=wordWrap=mulitline=selectable=multiline=wordWrap=true;
    }

    createTextField('inputMsg', getNextHighestDepth(), 15, 170, 415, 20);
    with(inputMsg){
    border=background=true;
    multiline=false;
    type='input';
    text='192.168.2.4';
    }
    inputMsg.onKeyPress=function(){
    if(Key.isDown(Key.ENTER)){
    pushMsg.onRelease();
    }
    };

    createEmptyMovieClip('pushMsg',getNextHighestDepth());
    pushMsg.createTextField('buttonText', pushMsg.getNextHighestDepth(), 455, 170, 0, 0);
    with(pushMsg.buttonText){
    border=background=true;
    selectable=false;
    autoSize='center';
    text='Send';
    }

    mySocket = new XMLSocket(); 
    connected = false;

    mySocket.onConnect = function(success) { 
    if (success) { 
    msgArea.htmlText = lastMessage + '\n' + '<b>Server connection established!</b>'; 
    lastMessage = '<b>Server connection established!</b>';
    connected = true;
    } else { 
    msgArea.htmlText = lastMessage + '\n' + '<b>Server connection failed!</b>'; 
    lastMessage = '<b>Server connection failed!</b>';

    }; 
      
    mySocket.onClose = function() { 
    msgArea.htmlText = lastMessage + '\n' + '<b>Server connection lost</b>'; 
    lastMessage = '<b>Server connection lost</b>';
    }; 
      
    var lastMessage = '';
    XMLSocket.prototype.onData = function(msg) { 
      msgArea.htmlText = lastMessage + '\n' + msg;
      lastMessage = msg; 
    }; 
      
    msgArea.text = lastMessage = 'Enter IP address of the server, then click the \"Send\" button';
      
    //--- Handle button click -------------------------------------- 
      
    function msgGO() { 
    if(!connected){
    msgArea.htmlText = lastMessage = '<b>Contacting Server...</b>';
    mySocket.connect(inputMsg.text, 9999); 
    }else{
    if (inputMsg.text != '') { 
    mySocket.send(inputMsg.text); 
    }
    }
    inputMsg.text = '';

      
    pushMsg.onRelease = function() { 
    msgGO(); 
    Selection.setFocus(inputMsg);
    }; 

    _keyListener = new Object();
    Key.addListener(_keyListener);
    _keyListener.onKeyDown=function(){
    if(Key.getCode()==Key.ENTER){
    pushMsg.onRelease();
    }
    };
      
    ";
    $movie->add(new SWFAction($actions));

    // save swf with same name as filename
    $swfname = basename(__FILE__,".php");
    $movie->save($outswf="$swfname.swf",9);
    // open movie and set version to 8 
    // (hack until it can be set in ming)
    $ftmp=fopen($outswf,"r"); 
    $stmp=fread($ftmp,filesize($outswf));
    $ftmp=fopen($outswf,"w"); 
    fwrite($ftmp,substr_replace($stmp,chr(8),3,1));

    $revitalizer=rand();
    print "<html><body bgColor=\"#c6c6c6\"><center>
    <OBJECT classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\" codebase=\"http://active.macromedia.com/flash2/cabs/swflash.cab#version=8,0,0,0\" ID=objects WIDTH=\"550\" HEIGHT=\"200\">
    <PARAM NAME=movie VALUE=\"$outswf?r=$revitalizer\">
    <EMBED src=\"$outswf?r=$revitalizer\" WIDTH=\"550\" HEIGHT=\"200\" TYPE=\"application/x-shockwave-flash\" PLUGINSPAGE=\"http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash\">
    </OBJECT>
    <br><br>
    <OBJECT classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\" codebase=\"http://active.macromedia.com/flash2/cabs/swflash.cab#version=9,0,0,0\" ID=objects WIDTH=\"550\" HEIGHT=\"200\">
    <PARAM NAME=movie VALUE=\"../flex/bin/chat.swf?r=$revitalizer\">
    <EMBED src=\"../flex/bin/chat.swf?r=$revitalizer\" WIDTH=\"550\" HEIGHT=\"200\" TYPE=\"application/x-shockwave-flash\" PLUGINSPAGE=\"http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash\">
    </OBJECT>
    </center></body></html>
    ";
    ?>
    Note- the above code outputs HTML to display both AS2 & AS3 versions on the same page, but only compiles the AS2 version via Ming.

  2. #2
    Senior Member
    Join Date
    Nov 2003
    Location
    Las Vegas
    Posts
    770
    There is alot of confusing information about the AS3 socket security sandbox. I seem to have found a solution, but haven't tested it completely yet, just thought I would share.

    As soon as the flash app connects to the server, it will send "<policy-file-request>". If you send the appropriate string, it will then disconnect and reconnect, otherwise it just disconnects. I'm currently sending the policy file on both connections, and it works, but I will figure out how to do it one time once I get my head around these sockets. Here's the new server code, which is built from a tutorial at kirupa.com:
    PHP Code:
    #!/usr/bin/php -q
    <?php

    error_reporting
    (E_ALL);

    set_time_limit(0);

    ob_implicit_flush();

    echo 
    "Enter Server IP:\n";
    $address trim(fgets(STDIN));
    //$address = '127.0.0.1';
    echo "Enter Port:\n";
    $port trim(fgets(STDIN));
    //$port = 9999;
    echo "Attempting to connect to $address:$port\n";

    //---- Function to Send out Messages to Everyone Connected ----------------------------------------

    function send_Message($allclient$buf) {
      global 
    $client_list;
      foreach(
    $allclient as $client) {
        if(
    $client_list[$client]['state'] && $client_list[$client]['nick'] != ""){
          
    socket_write($clienttrim($buf).chr(0));
        }
      }
    }

    function 
    who($allclient$socket) {
      global 
    $client_list;
      
    $buf "";
      
    $counter 0;
      foreach(
    $allclient as $client) {
        
    $buf.=$client_list[$client]['nick'].", ";
        
    $counter++;
      }
      
    socket_write($socket"There are $counter people in this room: $buf".chr(0));
    }

    function 
    send_Single($socket$buf) {
      
    socket_write($socket$buf.chr(0));
    }

    function 
    shutDown($allclients$master){
      global 
    $abort;
      
    $abort false;
      foreach(
    $allclients as $client){
        echo 
    "$client connection closed\n";
        
    socket_close($client);
      }
      echo 
    "$master connection closed\n";
      
    socket_close($master);
      echo 
    "Server shutdown complete\n";
    }

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

    if (($master socket_create(AF_INETSOCK_STREAMSOL_TCP)) < 0) {
      echo 
    "socket_create() failed, reason: " socket_strerror($master) . "\n";
    }else{
      echo 
    "$master socket created\n";
    }

    socket_set_option($masterSOL_SOCKET,SO_REUSEADDR1);


    if ((
    $ret socket_bind($master$address$port)) < 0) {
      echo 
    "socket_bind() failed, reason: " socket_strerror($ret) . "\n";
    }else{
      echo 
    "$ret socket bound to $address:$port\n";
    }


    if ((
    $ret socket_listen($master5)) < 0) {
      echo 
    "socket_listen() failed, reason: " socket_strerror($ret) . "\n";
    }else{
      echo 
    "$ret listening...\n";
    }



    $read_sockets = array($master);
    $client_list = array($master);
    $abort true;
    $policy_file 
        
    '<'.'?xml version="1.0" encoding="UTF-8"?'.'>'.
        
    '<cross-domain-policy xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.adobe.com/xml/schemas/PolicyFileSocket.xsd">'.
            
    '<allow-access-from domain="*" to-ports="*" secure="false" />'.
            
    '<site-control permitted-cross-domain-policies="master-only" />'.
        
    '</cross-domain-policy>';

    //---- Create Persistent Loop to continuously handle incoming socket messages ---------------------
    while ($abort) {
      
    $changed_sockets $read_sockets;

      
    $num_changed_sockets socket_select($changed_sockets$write NULL$except NULLNULL);

      foreach(
    $changed_sockets as $socket) {

        if (
    $socket == $master) {

          if ((
    $client socket_accept($master)) < 0) {
            echo 
    "socket_accept() failed: reason: " socket_strerror($msgsock) . "\n";
            continue;
          } else {
        echo 
    "[connection]:$client\n";
            
    array_push($read_sockets$client);
        
    $client_list[$client]['state'] = false;
        
    $client_list[$client]['nick'] = "";
        
    send_Single($client$policy_file);
        
    send_Single($client"<b>Enter a nickname:<b>");
          }
        } else {

          
    $bytes socket_recv($socket$buffer20480);

          if (
    $bytes == 0) {
        
    $nick $client_list[$socket]['nick'];
            
    $iindex array_search($socket$client_list);
            unset(
    $client_list[$iindex]);
            
    $index array_search($socket$read_sockets);
            unset(
    $read_sockets[$index]);
            
    $allclients $read_sockets;
            
    array_shift($allclients);
        if(
    $client_list[$socket]['nick'] != "" && $client_list[$socket]['nick'] != "<policy-file-request/>"){
          echo 
    "[connection-terminated]:$socket\n";
              
    send_Message($allclients"$nick has left the room");
        }
            
    socket_close($socket);
          }else{
        if(
    $bytes){
          if(
    $client_list[$socket]['state'] === false){
            
    $tempBuf trim($buffer);
            
    $testCase false;
            foreach(
    $read_sockets as $clients){
              if (
    $client_list[$clients]['nick'] == $tempBuf) {
                
    $testCase true;
                
    send_Single($socket"Sorry, \"$tempBuf\" is already in use!");
                
    send_Single($socket"Please choose another nickname:");
                break;
              }
            }
            if(!
    $testCase){
              
    $client_list[$socket]['nick'] = $tempBuf;
              echo 
    "$tempBuf assigned to $socket\n";
              
    send_Single($socket"Hello $tempBuf!  Welcome to the game!");
                  
    $allclients $read_sockets;
                  
    array_shift($allclients);
              
    who($allclients$socket);
              if(
    $client_list[$socket]['nick'] != "" && $tempBuf != "<policy-file-request/>"){
                    
    send_Message($allclients$client_list[$socket]['nick']." has entered the game.");
              }
              
    $client_list[$socket]['state'] = true;
            }
          }else{
                
    $allclients $read_sockets;
                
    array_shift($allclients);
            if(
    trim($buffer) == "shut-down-server"){
              
    shutDown($allclients$master);
            }else{
              if(
    trim($buffer) == "/who"){
                
    who($allclients$socket);
              }else{
                    
    send_Message($allclients$client_list[$socket]['nick']." wrote: ".$buffer);
              }
            }
          }
        }
          }
        }
      }
    }

    ?>
    Note- this uses a completely non-restrictive policy file, any domain can access the server with this file!

  3. #3
    Junior Member
    Join Date
    Nov 2008
    Posts
    1
    This was SO helpful. So many people on the web seem to have encountered this problem, but you're the first that I've seen who has posted a solution. Thanks.

    A follow up question:

    I copied and pasted your code and it worked beautifully. But now I'm trying to edit it to fit my needs. But, apparently, simply editing the php and uploading doesn't work when you're dealing with code at this level of the server.

    If you, or anyone, knows how to edit the code, and is willing to explain it, I'd sure appreciate it. I have a lot of experience using PHP/MySQL to create web pages, but I'm a complete tyro with sockets and ssh.

    Thanks so much.

    UPDATE: I figured it out. It was a permissions problem. The file had to be 777 in order for me to edit it. So I'm all set and just want to thank JerryScript for his very useful code.
    Last edited by tugboat; 11-12-2008 at 07:45 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  




Click Here to Expand Forum to Full Width

HTML5 Development Center