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">
      <mx:Script>
          <![CDATA[
              var str:Socket;

       

              private function handleClick(e:Event):void {

       

                  Security.loadPolicyFile("xmlsocket://localhost:2525");           

       

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

       

                  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();
                           strBytes.push(byte);
                       }
                       trace(String.fromCharCode.apply(null, strBytes));
                   } else if (e is SecurityErrorEvent) {
                       trace("Security error:", SecurityErrorEvent(e).text);
                   }
               }


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

       

      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" +
                                              "</cross-domain-policy>\n"
                                              )
                         ).start();
              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);
                      }
                      System.out.println();

       

                      Writer out = new OutputStreamWriter(outStr);
                      out.write(response);
                      System.out.println(getName() + " sent response: ");
                      System.out.println(response);
                      System.out.println(getName() + " closing connection");
                      out.flush();
                      out.close();
                      s.close();
                  }               
              } catch (Exception e) {
                  System.out.println(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.