Dalanchoo
Dalanchoo

Reputation: 177

Cross Domain Policy troubles non port 80 in Unity

I'm having trouble accessing my web service from Unity if it is not running on port 80. This is the C# code that I'm using in Unity

private void RunSimulation()
{
    string url = @"http://192.168.1.116:9000/simulate";
    WWW goServer = new WWW(url);
}

On 192.168.1.116, I have a program written in go that is listening on port 9000. I can easily reach this URL from a web browser and I will get my expected result.

When I try this in Unity, if I examine the contents of my goServer variable, I will see the message

System.Security.Exception: No valid crossdomain policy available to allow access

There is a crossdomain policy file. It is located at /var/www/html/crossdomain.xml Is has the following contents:

<allow-access-from domain="*" to-ports="*" secure="false"/>
<site-control permitted-cross-domain-policies="all"/>

This file existed before and there were .php programs that were able to successfully be called. I added the to-ports"*" to try to get it to work, but no luck.

I have tried having my go server listen on port 80. When I do this, I am able to connect from Unity. Any idea?


(The input sanitizer is defeating me and I can't figure out how to post without the input form telling me that my links are not allowed, so I'm going to omit 192.168.1.116:9000)

I was not getting anything at serverurl.com:9000/crossdomain.xml So I put some code into my go server to respond to this request and return a response with headers Access-Control-Allow-Origin, Access-Control-Allow-Headers, and Access-Control-Allow-Credentials.

I set the ENABLE_CROSSDOMAIN_LOGGING environment variable. I see this in the log file plus a bunch more

Determining crossdomain.xml location for request: /simulate?asdfa=sadfsa

About to parse url: /simulate?asdfa=sadfsa

Determining crossdomain.xml location for request:/simulate?asdfa=sadfsa

About to parse url: /crossdomain.xml

About to parse url: /simulate?asdfa=sadfsa

Determining crossdomain.xml location for request: /simulate?asdfa=sadfsa

Download had OK statuscode

Received the following crossdomain.xml

----------



----------

received policy

BuildFlashPolicy caught an exception while parsing
/crossdomain.xml: Policy can't be constructed from empty stream.

ArgumentException: Policy can't be constructed from empty stream. at MonoForks.System.Windows.Browser.Net.FlashCrossDomainPolicy.FromStream (System.IO.Stream originalStream) [0x00000] in :0 at MonoForks.System.Windows.Browser.Net.CrossDomainPolicyManager.BuildFlashPolicy (Boolean statuscodeOK, MonoForks.System.Uri uri, System.IO.Stream responsestream, System.Collections.Generic.Dictionary`2 responseheaders) [0x00000] in :0 UnityEngine.WWW:get_assetBundle() PlayEditorMain:RunSimulation() (at Assets\Scripts\Play Editor Scripts\Menu Scripts\PlayEditorMain.cs:526) PlayEditorMain:ButtonPressed(GameObject) (at Assets\Scripts\Play Editor Scripts\Menu Scripts\PlayEditorMain.cs:261) MainMenuButton:OnClick() (at Assets\Scripts\Play Editor Scripts\Menu Buttons\MainMenuButton.cs:23) UnityEngine.GameObject:SendMessage(String, Object, SendMessageOptions) UICamera:Notify(GameObject, String, Object) (at Assets\3rd Party\NGUI\Scripts\UI\UICamera.cs:765) UICamera:ProcessTouch(Boolean, Boolean) (at Assets\3rd Party\NGUI\Scripts\UI\UICamera.cs:1435) UICamera:ProcessMouse() (at Assets\3rd Party\NGUI\Scripts\UI\UICamera.cs:1063) UICamera:Update() (at Assets\3rd Party\NGUI\Scripts\UI\UICamera.cs:909)

(Filename: Assets/Scripts/Play Editor Scripts/Menu Scripts/PlayEditorMain.cs Line: 526)

Unable to determine the audio type from the URL (/simulate?asdfa=sadfsa) . Please specify the type. UnityEngine.WWW:GetAudioClip(Boolean, Boolean, AudioType) UnityEngine.WWW:GetAudioClip(Boolean, Boolean) (at C:\BuildAgent\work\d63dfc6385190b60\artifacts\EditorGenerated\Utils.cs:308) UnityEngine.WWW:GetAudioClip(Boolean) (at C:\BuildAgent\work\d63dfc6385190b60\artifacts\EditorGenerated\Utils.cs:301) UnityEngine.WWW:get_audioClip() (at C:\BuildAgent\work\d63dfc6385190b60\artifacts\EditorGenerated\Utils.cs:293) PlayEditorMain:RunSimulation() (at Assets\Scripts\Play Editor Scripts\Menu Scripts\PlayEditorMain.cs:526) PlayEditorMain:ButtonPressed(GameObject) (at Assets\Scripts\Play Editor Scripts\Menu Scripts\PlayEditorMain.cs:261) MainMenuButton:OnClick() (at Assets\Scripts\Play Editor Scripts\Menu Buttons\MainMenuButton.cs:23) UnityEngine.GameObject:SendMessage(String, Object, SendMessageOptions) UICamera:Notify(GameObject, String, Object) (at Assets\3rd Party\NGUI\Scripts\UI\UICamera.cs:765) UICamera:ProcessTouch(Boolean, Boolean) (at Assets\3rd Party\NGUI\Scripts\UI\UICamera.cs:1435) UICamera:ProcessMouse() (at Assets\3rd Party\NGUI\Scripts\UI\UICamera.cs:1063) UICamera:Update() (at Assets\3rd Party\NGUI\Scripts\UI\UICamera.cs:909)

[C:/BuildAgent/work/d63dfc6385190b60/Runtime/Audio/AudioClip.cpp line 118] (Filename: Assets/Scripts/Play Editor Scripts/Menu Scripts/PlayEditorMain.cs Line: 526)

So I think I am now returning the correct headers, but I'm thinking that I also need to return the contents in the body. I'm thinking that I'll just return the same contents that the crossdomain.xml file I get when I query it on port 80.

I know that the crossdomain.xml endpoint on my server is being hit. If I understand what the logfile that unity is outputting, the problem might just be that the body is empty and I have an empty stream.

Upvotes: 1

Views: 612

Answers (2)

Dalanchoo
Dalanchoo

Reputation: 177

What I had to do was implement my own version of the crossdomain.xml endpoint. It currently looks like this.

func crossdomain(res http.ResponseWriter, req *http.Request) { log.Println("At the top of crossdomain")

if origin := req.Header.Get("Origin"); origin != "" {
    res.Header().Set("Access-Control-Allow-Origin", origin)
}
res.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
res.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token")
res.Header().Set("Access-Control-Allow-Credentials", "true")

body := "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + 
            "<!DOCTYPE cross-domain-policy SYSTEM \"http://www.adobe.com/xml/dtds/cross-domain-policy.dtd\">" +
                "<cross-domain-policy>" +
                    "<site-control permitted-cross-domain-policies=\"all\"/>" +
                    "<allow-access-from domain=\"*\" to-ports=\"*\" secure=\"false\"/>" +
                    "<allow-access-from domain=\"*\" to-ports=\"*\"/>" +
                    "<allow-access-from domain=\"*\"/>" +
                    "<allow-http-request-headers-from domain=\"*\"  to-ports=\"*\"/>" +
                    "<allow-http-request-headers-from domain=\"*\"/>" +
                    "<site-control permitted-cross-domain-policies=\"all\"/>" +
                "</cross-domain-policy>"

io.WriteString(res,body)

}

func main() {

http.HandleFunc("/simulate", simulate)
http.HandleFunc("/crossdomain.xml", crossdomain)

listenErr := http.ListenAndServe(":9000", nil)

}

Upvotes: 0

Krzysztof Bociurko
Krzysztof Bociurko

Reputation: 4661

No proxy needed, unity has logging crossdomain stuff built in: take a look at the the debuging section of the unity3d manual on the security sandbox and turn on crossdomain debugging with ENABLE_CROSSDOMAIN_LOGGING. Then look for the results in the logs.

Just to be sure, a crossdomain file is reachable at http://192.168.1.116:9000/crossdomain.xml?

Upvotes: 1

Related Questions