Go Back   kirupaForum > Flash > ActionScript 3

Reply
 
Thread Tools Display Modes
Old 02-15-2008, 11:10 AM   #1
krdr
Registered User
Sockets, security and classes problem (<policy-file-request/> hell)

Last few months I experienced lot pain of due to Flash Player 9 version 3 (I thought that 9 is version no.).

Last thing is new socket policy files and all the new security "improvements". We finally forced sockets to works, thanks to:
http://ammonlauritzen.com/blog/category/flash/,
and no thanks to:
http://www.adobe.com/devnet/flashpla..._security.html
http://www.adobe.com/devnet/flashpla..._swf_apps.html
Especially
http://www.adobe.com/devnet/flashpla...icy_files.html.
BUT, when I tried to wrap socket class in other class, or to load movie with socket class in other movie, things didn't work. Ol' good <policy-file-request/> are sent.

How I can wrap socket class and avoid
<policy-file-request/>?
krdr is offline   Reply With Quote

Sponsored Links (Guests Only) - Register | Need Help?

Old 02-15-2008, 02:18 PM   #2
Jerryscript
Registered User
Location Las Vegas

Posts 820
I didn't know there was any way to get around the policy-file-request.

However, it is easy to implement in your socket server. Just send the policy file on socket_accept.

As you probably found out, when connecting to a socket server with AS3, flash will first send a request for the policy file, then disconnect, and if the appropriate policy file was received, it will connect again. Since the policy file is an xml format, you can strip it out of your received messages in the flash client.

Here's my basic chat solution, which sends the policy file both times the client connects: (it's only a few bytes, so it doesn't really affect bandwidth):

AS3:
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="127.0.0.1"// change to your IP
            
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); // change 9999 to your port
            
}else{
                if (
inputMsg.text != '') { 
                    
socket.send(inputMsg.text); 
                } 
            }
            
inputMsg.text ''
        }

    }

AS2 implementation:
PHP Code:
createTextField('msgArea'getNextHighestDepth(), 1517450150);
with(msgArea){
border=background=html=wordWrap=mulitline=selectable=multiline=wordWrap=true;
}

createTextField('inputMsg'getNextHighestDepth(), 1517041520);
with(inputMsg){
border=background=true;
multiline=false;
type='input';
text='192.168.2.4';
}

createEmptyMovieClip('pushMsg',getNextHighestDepth());
pushMsg.createTextField('buttonText'pushMsg.getNextHighestDepth(), 45517000);
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) { 
  var 
elapsedTime getTimer() - timer;
  
msgArea.htmlText lastMessage '\n' msg '\n' elapsedTime;
  
lastMessage msg
}; 
  
msgArea.text lastMessage 'Enter IP address of the server, then click the \"Send\" button';
  
//--- Handle button click -------------------------------------- 

timer 0;
  
function 
msgGO() { 
if(!
connected){
msgArea.htmlText lastMessage '<b>Contacting Server...</b>';
mySocket.connect(inputMsg.text9999); 
}else{
if (
inputMsg.text != '') { 
timer getTimer();
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();
}
}; 
Basic PHP socket server (use as a basis, NOT FOR PRODUCTION!):
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 = '192.168.2.4';
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);
          }
        }
      }
    }
      }
    }
  }
}

?>

__________________
JerryScript
http://jerryscript.hostrocket.com
Events Calendar | Samples
Jerryscript is offline   Reply With Quote
Old 02-15-2008, 05:50 PM   #3
krdr
Registered User
Thanks Jerryscript.
We already did that. We even wrote xml socket server in c++ just for that purpose. Your earlier posts was very helpful.

This is our situation: We have main swf, that serves as login form and preloader. Then, that swf loads other swf. That other swf does all the communication stuff trough the binary socket. In flash player 9r45 it worked like charm, but in 9,0,115,0 not. If I do plain socket calls in main swf (preloader) things works, but that will sent 3 months of work to dump.

Now I'm waiting for new update of flash player which will put all our work to dump
krdr is offline   Reply With Quote
Old 02-15-2008, 06:48 PM   #4
Jerryscript
Registered User
Location Las Vegas

Posts 820
Sounds as if the security is set per swf file, so loading after gaining security is probably the issue. Do you have to have the server login done during preload?

If not, I'm not sure what your architecture is, but maybe you just wrap the needed commands from the loaded file into your preloader (wouldn't take much in terms of code or bandwidth), and then pass parsed data around. I know it's an ugly hack, but until Adobe irons out the new sandbox, hacks are probably the only F9 solution.

__________________
JerryScript
http://jerryscript.hostrocket.com
Events Calendar | Samples
Jerryscript is offline   Reply With Quote
Old 02-15-2008, 07:56 PM   #5
krdr
Registered User
Robot1

Quote:
Originally Posted by Jerryscript View Post
Do you have to have the server login done during preload?

If not, I'm not sure what your architecture is,
Architecture in brief:

First, visitor logs on web app. Web app loads preload swf. Preload swf authorizes itself trough URLLoad and loads bunch of xml's (settings and localization).

If everything is ok, main swf is loaded. After main swf is loaded, preload swf call init method in main swf, which initalize socket connection.

Socket class is wrapped in other class, called Dispatcher. That class encapsulates all functionality related to communication with socket, prepares data to be send and parses received data.

Main swf also communicate with web app, which serves xml's. Web app and socket server are on different domains.

One of solutions I have on my mind is to connect to socket in preload swf, using plain socket, and then to pass that socket to Dispatcher class. That solution is not clean, but worth of trying, and can be easly implemented by adding "externalSocket" method to Dispatcher class:

MainMovie.Dispatcher.externalSocket = new Socket(host,port);
krdr is offline   Reply With Quote
Old 02-16-2008, 12:31 AM   #6
Jerryscript
Registered User
Location Las Vegas

Posts 820
The error your getting is 2048?

__________________
JerryScript
http://jerryscript.hostrocket.com
Events Calendar | Samples
Jerryscript is offline   Reply With Quote
Old 02-16-2008, 04:24 AM   #7
krdr
Registered User
Quote:
Originally Posted by Jerryscript View Post
The error your getting is 2048?
No, just <policy-file-request/> is sent to socket server not to xml "policy" server on port 843
krdr is offline   Reply With Quote
Old 02-16-2008, 11:55 AM   #8
Jerryscript
Registered User
Location Las Vegas

Posts 820
So maybe Adobe listened and got rid of the need for a sub http level socket policy server?!? I sure hope so!

__________________
JerryScript
http://jerryscript.hostrocket.com
Events Calendar | Samples
Jerryscript is offline   Reply With Quote
Old 02-16-2008, 01:26 PM   #9
krdr
Registered User
Quote:
Originally Posted by Jerryscript View Post
So maybe Adobe listened and got rid of the need for a sub http level socket policy server?!? I sure hope so!
Yeah, sure...

Did you, or anyone else, had similar situation as I?
krdr is offline   Reply With Quote
Old 02-16-2008, 06:48 PM   #10
Jerryscript
Registered User
Location Las Vegas

Posts 820
I haven't ready anything about such an issue recently. I haven't tried your method, and I haven't been using my test server much lately. I just fired it up and it connected fine in both AS2 and AS3.

Sorry I can't help more on this one.

__________________
JerryScript
http://jerryscript.hostrocket.com
Events Calendar | Samples
Jerryscript is offline   Reply With Quote
Old 02-18-2008, 10:59 AM   #11
krdr
Registered User
Thanks on your help.

I tried to pass socket to other class, and that didn't give any result. We made test app and noticed that sometime socket call xml server on 843, and sometimes not. Our next shot will be to serve policy file from our app server if xml fails.
krdr is offline   Reply With Quote
Old 03-05-2008, 12:16 PM   #12
looping
Registered User
Hello

Krdr, have you a solution for your problem. I'm asking that because we're having the same trouble.
It sounds like the first connection on the port 843 is correctly handled and then after that it doesn't check anymore the policy file on port 843 but it requests the policy file request on our server which is an IRC server
looping is offline   Reply With Quote
Old 03-17-2008, 08:57 AM   #13
looping
Registered User
Hello


We find the problem, it sounds it's due to the way Adobe Handles the policy file request.
The message <Policy File Request/> is sent with the null character at the end and the anwser returned by your server on port 843, must include also the null character to terminate the message. that's why the problem seems to be random because it depends on the memory on you client. So you'll have to developp you own server because i don't know any program which will send the null character at the end of a message
looping is offline   Reply With Quote
Old 04-12-2008, 05:14 AM   #14
gp_svn
Registered User
Quote:
Originally Posted by looping View Post
Hello


We find the problem, it sounds it's due to the way Adobe Handles the policy file request.
The message <Policy File Request/> is sent with the null character at the end and the anwser returned by your server on port 843, must include also the null character to terminate the message. that's why the problem seems to be random because it depends on the memory on you client. So you'll have to developp you own server because i don't know any program which will send the null character at the end of a message
Even after sending the policy-file with null termination character this problem is seem to be intermittently reproducible. Let me know whether it happens on your side or not
gp_svn is offline   Reply With Quote
Old 04-21-2008, 12:01 AM   #15
gp_svn
Registered User
Quote:
Originally Posted by gp_svn View Post
Even after sending the policy-file with null termination character this problem is seem to be intermittently reproducible. Let me know whether it happens on your side or not

Finally!!! we were able to make it work by opening master socket port 843 on the server and listening to <policy-file-request/> and then responding the master socket policy data
gp_svn is offline   Reply With Quote
Reply


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 10:25 AM.

SHARE:

SUPPORTERS:

cdn
content delivery network (cdn)

Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd. Copyright 2010 - kirupa.com Copyright 2010 - kirupa.com