2 Replies Latest reply on Nov 28, 2009 10:49 PM by msakrejda

    Socket and Security Policy

    msakrejda Level 4

      I've tried to set experiment with Socket communication in Flex, but I keep hitting problems. Approach 1: in a Flex web app, I load a crossdomain security policy from a server. I then open a socket and write a few bytes to the server. In my server, I do not get the expected output on the stream--in fact, I get nothing at all--until I close the Flex application, at which point I get a seemingly inifinite stream of the bytes '0xEFBFBF'. Here's a hexdump view of a fragment of the data Flash Player sends to the server after I close the Flex app:


      00000130  ef bf bf ef bf bf ef bf  bf ef bf bf ef bf bf ef  |................|
      00000140  bf bf ef bf bf ef bf bf  ef bf bf ef bf bf ef bf  |................|
      00000150  bf ef bf bf ef bf bf ef  bf bf ef bf bf ef bf bf  |................|


      Approach 2: I then tried it in air, but although the connection seems to initiate properly and I can go through the above trivial client-server interaction, after a few seconds, I get a SecurityErrorEvent. From what I've been able to follow of the docs, Air applications are trusted in this respect, and should not need to load security policy, right? I tried to add a call to Security.loadPolicy(), but it seems to be ignored. This is the message flow:


      Received [class Event] connect
      Received [class ProgressEvent] socketData
      Received [class Event] close
      Received [class SecurityErrorEvent] securityError
      Security error: Error #2048: Security sandbox violation: app:/main.swf cannot load data from localhost:5432.



      The Air version of my client code is below:


      <?xml version="1.0" encoding="utf-8"?>
      <mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
              var str:Socket;


              private function handleClick(e:Event):void {




                  str = new Socket('localhost', 5555);
                  var message:String = 'hello';
                  for (var i:int = 0; i < message.length; i++) {


                  str.addEventListener(Event.ACTIVATE, handleEvent);
                  str.addEventListener(Event.CLOSE, handleEvent);
                  str.addEventListener(Event.CONNECT, handleEvent);
                  str.addEventListener(Event.DEACTIVATE, handleEvent);
                  str.addEventListener(IOErrorEvent.IO_ERROR, handleEvent);
                  str.addEventListener(ProgressEvent.SOCKET_DATA, handleEvent);
                  str.addEventListener(SecurityErrorEvent.SECURITY_ERROR, handleEvent);           


              private function handleEvent(e:Event):void {
                   trace("Received", Object(e).constructor, e.type);
                   if (e is ProgressEvent) {
                       var strBytes:Array = [];
                       while(str.bytesAvailable > 0) {
                           var byte:int = str.readByte();
                       trace(String.fromCharCode.apply(null, strBytes));
                   } else if (e is SecurityErrorEvent) {
                       trace("Security error:", SecurityErrorEvent(e).text);

      <mx:Button label="test" click="handleClick(event)"/>   


      The server is in Java and is as follows:


      import java.net.*;
      import java.io.*;


      public class DeadSimpleServer implements Runnable {


          public static void main(String[] args) throws Exception {
              if (args.length != 2) {
                  throw new Exception("Usage: DeadSimpleServer policy-port service-port");
              int policyPort = Integer.parseInt(args[0]);
              int servicePort = Integer.parseInt(args[1]);
              new Thread(new DeadSimpleServer(policyPort,
                                              "<?xml version=\"1.0\"?>\n" +
                                              "<cross-domain-policy>\n" +
                                              "<allow-access-from domain=\"*\" to-ports=\"" + servicePort + "\"/>\n" +
              new Thread(new DeadSimpleServer(servicePort, "world")).start();
              while (true) Thread.sleep(1000);


          private int port;
          private String response;


          public DeadSimpleServer(int port, String response) {
              this.port = port;
              this.response = response;


          public String getName() {
              return DeadSimpleServer.class.getName() + ":" + port;


          public void run() {
              try {
                  ServerSocket ss = new ServerSocket(port);
                  while (true) {
                      Socket s = ss.accept();
                      System.out.println(getName() + " accepting connection to " + s.toString());
                      OutputStream outStr = s.getOutputStream();
                      InputStream inStr = s.getInputStream();


                      int character;
                      System.out.print(getName() + " received request: ");
                      while ((character = inStr.read()) != 0) {
                          System.out.print((char) character);


                      Writer out = new OutputStreamWriter(outStr);
                      System.out.println(getName() + " sent response: ");
                      System.out.println(getName() + " closing connection");
              } catch (Exception e) {


      Am I missing something? From what I understand, either of these approaches should work, but I'm stuck with both. I have Flash Player 10,0,15,3 and am working with Flex / Air 3.0.0 under Linux.