Search Unity

PrefetchSocketPolicy

Discussion in 'Multiplayer' started by idealc, Mar 13, 2012.

  1. idealc

    idealc

    Joined:
    Mar 13, 2012
    Posts:
    19
    Have been stuck on this most of the day and pored through tons of pages of similar problems - but none of the solutions work.

    Am trying to connect a socket from Unity to Node.js server via port 50200, but the command
    Code (csharp):
    1. bool isOk = Security.PrefetchSocketPolicy(Host, Port, 500);
    always returns false, so then further socket commands fail with a crossdomain policy not found error.

    Tested in editor, web player etc and all same result.

    localhost:50200 is correctly serving crossdomain.xml as is locahost
    Code (csharp):
    1. <?xml version="1.0"?>
    2. <cross-domain-policy>
    3. <allow-access-from domain="*" to-ports="*"/>
    4. </cross-domain-policy>
    I know the node.js server is working ok as can send data to the sockets via a browser based javascript script.
    This is all taking place on a mac behind a router with mac firewall off.

    Any ideas? Have tried everything I can think of but cannot get PrefetchSocketPolicy to return true, which i assume is why the crossdomain policy then fails.
     
  2. tcarr9

    tcarr9

    Joined:
    Oct 11, 2010
    Posts:
    63
    What are you sending for the value of Host? Prefetch requires an IP address, not an actual hostname, so I bet that "localhost" would fail even if "127.0.0.1" worked.
     
  3. idealc

    idealc

    Joined:
    Mar 13, 2012
    Posts:
    19
    thanks for reply
    was using 192.168.0.100
    nothing will make PrefetchSocketPolicy return true
    can get everything else to communicate on this ip, just not unity
     
  4. Tomo-Games

    Tomo-Games

    Joined:
    Sep 20, 2010
    Posts:
    223
    These are two separate things...
    Above is for changing the default Socket Policy Port 843 to something else.
    What Port are you using here? Security.PrefetchSocketPolicy($ip, 843... // same as default port

    As the Socket Policy Port shouldn't match your Node.js port. And crossdomain.xml is NOT served over http... Read all about it here.

    Unity has code to run a standalone Socket Policy Server aka socpol.cs.

    Which you'll have to edit line 74 sockpol.cs if you changed client side:
    listen_socket.Bind (new IPEndPoint (IPAddress.Any, 843));

    to match what you used in PrefetchSocketPolicy(Host, Port above... Unless you don't plan to change port 843 ? As it's sole job is to return your Node.js server port specified in crossdomain.xml.

    example using default 843:
    HTML:
     
    $ cat ~/crossdomain.xml
    <?xml version="1.0"?>
    <cross-domain-policy>
            <allow-access-from domain="*" to-ports="50200-50500" />
    </cross-domain-policy>
     
     
    $ sudo mono /Applications/Unity/Unity.app/Contents/Tools/SocketPolicyServer/sockpol.exe --file ~/crossdomain.xml
    Password:
    
    Hit Return to stop the server.
    incoming connection
    got policy request, sending response
    
    Which you can test in a separate terminal using telnet...
    1. telnet localhost port [ENTER]
    2. <policy-file-request/>[ENTER]
    HTML:
    $ telnet localhost 843
    Trying 127.0.0.1...
    Connected to localhost.
    Escape character is '^]'.
    <policy-file-request/>
    <?xml version="1.0"?>
    <cross-domain-policy>
            <allow-access-from domain="*" to-ports="50200-50500" />
    </cross-domain-policy>
    Connection closed by foreign host. 
    
    note flag sockpol.exe --range does not exist. It's actually called --local with a permanent port range of 4500-4550 (not 50200)
    if you use mono sockpol.exe --local then expect Node.js to be listening somewhere on port 4500-4550. To change this edit the sockpol.cs code since you probably don't want to run as root with a port less than 1024 anyway.

    Well that's wrong too... The second part of needing a crossdomain.xml is for the WWW class. Like in downloading scene files. This is a separate policy file altogether which must be served over HTTP on port 80. Read the link above it will explain what you need to setup.
     
  5. idealc

    idealc

    Joined:
    Mar 13, 2012
    Posts:
    19
    thanks for this - didn't know there was a socpool.cs tool at all!
    Don't have time to test today, but will look into this at the weekend.
    Does sockpol.cs always need to be running on the server in order to return the node.js port?
     
  6. Tomo-Games

    Tomo-Games

    Joined:
    Sep 20, 2010
    Posts:
    223
    I suppose it does need to run. It is done to mimic Adobe's Flash Policy Server, a method to beaf up web security. But if you google around I'm sure there are some nice php scripts out there that can do the same thing.

    Hell I bet you can use Node.js as long as there's no http headers.

    Code (csharp):
    1.  
    2. var net = require("net"),
    3. domains = ["*:50000-50500"];
    4.  
    5. net.createServer(
    6.     function(socket)
    7.     {
    8.         socket.write("<?xml version=\"1.0\"?>\n");
    9.         socket.write("<cross-domain-policy>\n");
    10.  
    11.         domains.forEach(
    12.             function(domain)
    13.             {
    14.                 var parts = domain.split(':');
    15.                 socket.write("<allow-access-from domain=\""+parts[0]+"\"to-ports=\""+parts[1]+"\"/>\n");
    16.             }
    17.         );
    18.         socket.write("</cross-domain-policy>\n");
    19.         socket.end();  
    20.     }
    21. ).listen(843);
    22.  
    Update:
    See Here for a tested updated version of the above.
     
    Last edited: Apr 2, 2012
  7. idealc

    idealc

    Joined:
    Mar 13, 2012
    Posts:
    19
    already had node.js serving the crossdomain.xml, but to port 80
    will check on this asap.
    thanks again for your help!
     
  8. idealc

    idealc

    Joined:
    Mar 13, 2012
    Posts:
    19
    hmm, can't get anything working today
    "sudo mono /Applications/Unity/Unity.app/Contents/Tools/SocketPolicyServer/sockpol.exe --file ~/crossdomain.xml"
    won't run as says "can't find mono".
    I can't find mono either???

    node.js won't serve crossdomain.xml (or anything else for that matter) on port 843, it just crashes when asked to listen on port 843.
     
  9. idealc

    idealc

    Joined:
    Mar 13, 2012
    Posts:
    19
    ok got node.js serving crossdomain.xml to http://192.168.0.100:843/ using sudo
    and can see the file in the browser.

    but
    Code (csharp):
    1. bool isOk = Security.PrefetchSocketPolicy("192.168.0.100", 843, 500);
    still returns false

    this is all in editor mode
    what am I missing?:(
     
  10. Tomo-Games

    Tomo-Games

    Joined:
    Sep 20, 2010
    Posts:
    223
    Change your Prefetch Socket 843 port to something higher as I said earlier and you will not need sudo.

    On Mac make sure you have Mono 2.10.8 Mac Runtime installed if you want it to run mono sockpol.exe from the command line. Don't worry it won't interfere with MonoDevelop.
     
  11. Tomo-Games

    Tomo-Games

    Joined:
    Sep 20, 2010
    Posts:
    223
    FYI
    I had a post that was similar to your case using Lidgren.
     
  12. idealc

    idealc

    Joined:
    Mar 13, 2012
    Posts:
    19
    ok, got mono now, so sockpol runs ok, and receive crossdomain.xml when telnet to 192.168.0.100 port 843.
    makes no difference to PrefetchSocketPolicy which still returns false
     
  13. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    stupid question but is the port opened up ie even reachable?

    If you don't modify the ports anywhere and just run the sockpol, then you don't even need the prefetch (at least to test if its reachable - beyond that I would still do it if you use udp)
     
  14. idealc

    idealc

    Joined:
    Mar 13, 2012
    Posts:
    19
    not a stupid question. I would guess it is reachable as the browser can see 192.168.0.100:843 and gets the xml file.
    I'm new to Mac's and Unity so struggling to find my way round this aspect. Has anybody successfully got Unity working with Node.js? Or any other socket solution?
     
  15. Tomo-Games

    Tomo-Games

    Joined:
    Sep 20, 2010
    Posts:
    223
    Speaking of silly questions :eek:

    idealc
    May I ask one?

    Idealc did you try running Unity as a Standalone build to confirm your Node.js service even jives well with the Unity editor? If not all this is a wasted effort...

    Player settings -> Switch Platform - Mac / Windows

    Edit:
    Then run the game in the editor hitting Play. No need to publish.
     
    Last edited: Mar 19, 2012
  16. idealc

    idealc

    Joined:
    Mar 13, 2012
    Posts:
    19
    yes, I was originally using a build but gone back to editor. Is there any reason why editor would would not see it but build would? I got the feeling from other posts that editor was most likely to see it, certainly above web player build.
     
  17. Tomo-Games

    Tomo-Games

    Joined:
    Sep 20, 2010
    Posts:
    223
    The editor will try to mimic what your Player's Platform is set to. So you are saying that a Build standalone works fine, which also means your Editor in Standalone "Play" works fine too.

    If this is the case which client implementation of WebSocket are you using in Unity? I can try to reproduce a simple case on my end to test.
     
  18. andorov

    andorov

    Joined:
    Feb 10, 2011
    Posts:
    1,061
    Serving a socket policy on a webserver running on port 843 is not the same as serving it via a TCP socket, because the webserver will send response headers before sending the policy which is not valid.

    Sockpol.exe *should* serve your socket policy on TCP Port 843 and everything should be good; can you test sockpol by connecting to port 843 and reading the output? Is it serving the policy?
     
  19. Tomo-Games

    Tomo-Games

    Joined:
    Sep 20, 2010
    Posts:
    223
    No one said they were doing that if you read the whole trail...
     
  20. idealc

    idealc

    Joined:
    Mar 13, 2012
    Posts:
    19
    have tried all options.
    Have served via sockpol as well, and sockpol serves correctly, but unity editor still fails

    I working on other stuff at the moment, but this is the client code


    Code (csharp):
    1.  
    2.  
    3.  
    4. using UnityEngine;
    5. using System.Collections;
    6. using System;
    7. using System.IO;
    8. using System.Net.Sockets;
    9. using JsonFx.Json;
    10.  
    11. public class ConnectNode : MonoBehaviour {
    12.     internal Boolean socketReady = false;
    13.  
    14.     TcpClient mySocket;
    15.     NetworkStream theStream;
    16.     StreamWriter theWriter;
    17.     StreamReader theReader;
    18.     String Host = "192.168.0.100";
    19.     Int32 Port = 843;
    20.    
    21.     void Awake () {
    22.         Application.runInBackground = true;
    23.         print("---------Port: "+Port.ToString());
    24.         bool isOk = Security.PrefetchSocketPolicy(Host, 843, 500);
    25.        
    26.         print("---------prefetch?: "+isOk.ToString());
    27.        
    28.         //setupSocket();
    29.        
    30.     }
    31.    
    32.     void Start () {
    33.     }
    34.     void Update () {
    35.         //print("1");
    36.         readSocket();
    37.     }
    38. // **********************************************
    39.     public void setupSocket() {
    40.         try {
    41.             mySocket = new TcpClient(Host, Port);
    42.             theStream = mySocket.GetStream();
    43.             theWriter = new StreamWriter(theStream);
    44.             theReader = new StreamReader(theStream);
    45.             socketReady = true;
    46.             print ("Socket Setup");
    47.                    
    48.            
    49.         }
    50.         catch (Exception e) {
    51.             Debug.Log("Socket error: " + e);
    52.         }
    53.     }
    54.     public void writeSocket(string theLine) {
    55.         if (!socketReady)
    56.             return;
    57.         String foo = theLine + "\r\n";
    58.         theWriter.Write(foo);
    59.         theWriter.Flush();
    60.         print ("sending=-=-"+foo);
    61.     }
    62.     public String readSocket() {
    63.         if (!socketReady)
    64.             //print ("not ready");
    65.             return "";
    66.         if (theStream.DataAvailable)
    67.             print ("reading....");
    68.             return theReader.ReadLine();
    69.         return "";
    70.     }
    71.     public void closeSocket() {
    72.         if (!socketReady)
    73.             return;
    74.         theWriter.Close();
    75.         theReader.Close();
    76.         mySocket.Close();
    77.         socketReady = false;
    78.     }
    79.    
    80.     public void OnGUI () {
    81.         if (GUI.Button (new Rect (200,100,100,30), "Send")) {
    82.             //string json = JsonWriter.Serialize("message:hello there");
    83.             print (mySocket);
    84.             print (mySocket.GetStream());
    85.             print (theStream.DataAvailable);
    86.             writeSocket("unity");
    87.             //server.send ( 'pm', { from: 'Tom', to: 'Dave', msg: 'this is for you matey!' } );
    88.             print ("sent");
    89.         }
    90.     }
    91.    
    92.    
    93.    
    94. } // end class s_TCP
    95.  
    96.  
    97.  
    98.  
    99.  
     
  21. Tomo-Games

    Tomo-Games

    Joined:
    Sep 20, 2010
    Posts:
    223
    Works for me... ---------prefetch?: True
    Tomo$ cat SockPol.js
    Code (csharp):
    1.  
    2. var net = require("net"),
    3. domains = ["*:50000-50500"];
    4.  
    5. net.createServer(
    6.     function(socket)
    7.     {
    8.         console.log("<?xml version=\"1.0\"?>");
    9.         socket.write("<?xml version=\"1.0\"?>\n");
    10.  
    11.         console.log("<cross-domain-policy>");
    12.         socket.write("<cross-domain-policy>\n");
    13.  
    14.         domains.forEach(
    15.             function(domain)
    16.             {
    17.                 var parts = domain.split(':');
    18.             console.log("<allow-access-from domain=\""+parts[0]+"\"to-ports =\""+parts[1]+"\"/>");
    19.                 socket.write("<allow-access-from domain=\""+parts[0]+"\"to-ports =\""+parts[1]+"\"/>\n");
    20.             }
    21.         );
    22.         console.log("</cross-domain-policy>");
    23.         socket.write("</cross-domain-policy>\n");
    24.         socket.end();  
    25.     }
    26. ).listen(8843);
    27.  
    Output of SockPol.js
    You'll have to modify your code post for "if blocks" as they need the curly brackets for the return statements...
    I commented out the import JsonFx too.

    I haven't actually tried connecting a simple test game server port 50200 to the client as there isn't any server.js code about ?
     
  22. idealc

    idealc

    Joined:
    Mar 13, 2012
    Posts:
    19
    thanks got further! Web player now shows prefetch is true.
    unity now appears to write to the socket ok, but node never receives it.
    Unity also shuts down the socket after 3 attempts, and node.js never acknowledges a connection.
    ;-(
     
  23. idealc

    idealc

    Joined:
    Mar 13, 2012
    Posts:
    19
    am using this in node.js


    Code (csharp):
    1.  
    2. var io = require('socket.io').listen(50200);
    3.  
    4. io.sockets.on('connection', function (socket) {
    5.     console.log('connection [', socket.id, '] ');
    6.    
    7.     socket.on('unity', function (unity) {
    8.         socket.emit('unity');
    9.         console.log('unity ', socket.id, ' = ', unity.message );
    10.     });
    11.  
    12. });
    13.  
    14.  
     
  24. Tomo-Games

    Tomo-Games

    Joined:
    Sep 20, 2010
    Posts:
    223
    Your client example will not work with socket.io as you need to write all of the web socket handshaking to go with it. This looks quick and dirty. I have not tested...

    Best to use a current C# implementation of WebSockets. Which is a bit of a moving target on the client side...

    WebSocket4Net / SuperWebSocket

    Websocket-Sharp

    Anaida

    Alternatives to Node.js for C#

    Fleck

    Manos
     
  25. idealc

    idealc

    Joined:
    Mar 13, 2012
    Posts:
    19
    thanks! - I'll check these out.
     
  26. Brad-Keys

    Brad-Keys

    Joined:
    May 1, 2006
    Posts:
    161
    Is this true for registered domains too? What if you're running a cloud hosted service with a load balancer? I can't really know the IP address beforehand, I only know the domain.
     
  27. tcarr9

    tcarr9

    Joined:
    Oct 11, 2010
    Posts:
    63
    I haven't tried with the most recent version of Unity (PreFetch might work with domain names now), but what does work if you have a domain name is using this to convert the domain name to an IP address:
    Code (csharp):
    1.  
    2.     private string getIP(string host)
    3.     {
    4.             return Dns.GetHostAddresses(host)[0].ToString();
    5.     }
    6.  
     
  28. Brad-Keys

    Brad-Keys

    Joined:
    May 1, 2006
    Posts:
    161
    Awesome that works great, thanks :)
     
  29. kungfooman

    kungfooman

    Joined:
    Jun 3, 2014
    Posts:
    7
    I still have the same problem. Networking with security privacy works perfect in native Build, but in Unity itself or Web Player it doesn't work.
     
  30. Raynoko

    Raynoko

    Joined:
    May 9, 2014
    Posts:
    7


    Hi can i ask u? what require is? Because when i put this code in my *.js, console write me error : "
    Assets/SockPol.js(2,15): BCE0005: Unknown identifier: 'require'."
    Canu help me pls?
    Thanks