SoftwareGuy / Ignorance

Ignorance utilizes the power of ENet to provide a reliable UDP networking transport for Mirror Networking.
Other
248 stars 31 forks source link

Doesn't Work in PlayFab Docker Containers #53

Closed TCROC closed 4 years ago

TCROC commented 4 years ago

Here is the same thing reported as the conversation in Discord:

I am struggling to connect IgnoranceThreaded or IgnoranceClassic while running in the PlayFab MockVM Agent locally on my Windows 10. It works just fine with Telepathy Transport.

Here is my MultiplayerSettings.json file when trying to connect with Ignorance

{
    "RunContainer": true,
    "OutputFolder": "D:\\PlayFabMultiPlayerLocalAgent\\0.7.1\\Output",
    "NumHeartBeatsForActivateResponse": 10,
    "NumHeartBeatsForTerminateResponse": 6000,
    "TitleId": "",
    "BuildId": "00000000-0000-0000-0000-000000000000",
    "Region": "WestUs",
    "AgentListeningPort": 56001,
    "ServerStartParameters": {
        "ImageDetails": {
            "Registry": "mcr.microsoft.com",
            "ImageName": "playfab/multiplayer",
            "ImageTag": "wsc-10.0.17134.950",
            "Username": "",
            "Password": ""
        },
        "AssetDetails": [
            {
                "MountPath": "C:\\Assets",
                "SasTokens": null,
                "LocalFilePath": "D:\\PlayFabMultiPlayerLocalAgent\\GameServers\\BlockyBall-Mechanics\\BlockyBall-GameServer-0.0.6.zip"
            }
        ],
        "StartGameCommand": "C:\\Assets\\GameServer.exe",
        "PortMappingsList": [
            [
                {
                    "NodePort": 56100,
                    "GamePort": {
                        "Name": "game_port",
                        "Number": 3600,
                        "Protocol": "UDP"
                    }
                }
            ]
        ]
    },
    "SessionConfig": {
        "SessionId": "ba67d671-512a-4e7d-a38c-2329ce181946",
        "SessionCookie": null,
        "InitialPlayers": [ "Player1", "Player2" ]
    }
}

And here is the setup in Unity:

image

And this is how I assign the port:

public virtual ushort Port
{
    get
    {
        ushort invalidValue = 0;

        switch (transport)
        {
            case IgnoranceClassic ignoranceClassic:
                return (ushort) ignoranceClassic.CommunicationPort;
            case IgnoranceThreaded ignoranceThreaded:
                return (ushort) ignoranceThreaded.CommunicationPort;
            case TelepathyTransport telepathyTransport:
                return telepathyTransport.port;
        }

        Debug.LogError($"There is not a supported transport attached to this {GetType().Name}", this);
        return invalidValue;
    }
    protected set
    {
        switch (transport)
        {
            case IgnoranceClassic ignoranceClassic:
                ignoranceClassic.CommunicationPort = value;
                return;
            case IgnoranceThreaded ignoranceThreaded:
                ignoranceThreaded.CommunicationPort = value;
                return;
            case TelepathyTransport telepathyTransport:
                telepathyTransport.port = value;
                return;
        }

        Debug.LogError($"There is not a supported transport attached to this {GetType().Name}", this);
    }
}

I'm at a loss here as to why I can't connect locally in the Docker Container with the Mock VM Agent. Telepathy works just fine over TCP but Ignorance does not. I've opened up the ports and communication on my firewall for both TCP and UDP but still no luck. Even with those ports not opened on my firewall, communication still works just fine locally over TCP so that is not the issue. Any help would be extremely appreciated.

Here is the docs for the PlayFab Docker Container: https://docs.microsoft.com/en-us/gaming/playfab/features/multiplayer/servers/locally-debugging-game-servers-and-integration-with-playfab

SoftwareGuy commented 4 years ago

Looking into this two-fold:

1) Running it from a docker container itself 2) Running it from inside a PlayFab docker container

Working on the first one first.

TCROC commented 4 years ago

Awesome! Can't wait to get to use Ignorance in PlayFab! :)

SoftwareGuy commented 4 years ago

Okay, so apparently starting a server inside a docker container will work fine, but if a client attempts to connect to the docker container's instance it will go boom and emit a huge stack trace. I guess this is what's happening for you but your PlayFab setup isn't logging it.

I'm gonna have to dig deeper. I don't understand why this is happening.

SoftwareGuy commented 4 years ago

Okay, looking deeper, I see Windows Server and Windows Client (non-docker, testing it via one instance as server and another as client) builds are working. I wonder if my build bot is making bad builds of the Linux binary blobs.

TCROC commented 4 years ago

That is an interesting find. I will try creating a build and see if I get similar logs as well.

TCROC commented 4 years ago

I checked the logs after running in the Windows10 PlayFab Docker container and everything seems fine:

Log: 
Ignorance Server worker thread is ready for connections! I'm listening on UDP port 8080.
Capacity: 4095 peers with 3 channels. My buffer size is 65536 bytes
Stack Trace: 
UnityEngine.Debug:Log(Object)
Mirror.IgnoranceThreaded:ServerWorkerThread(ThreadBootstrapStruct) (at D:/Travis/User Folders/Documents/Unity/Projects/BlockyBallv2/Assets/External/Mirror/Runtime/Transport/Ignorance/IgnoranceThreaded.cs:498)
Mirror.<>c__DisplayClass44_0:<IgnoranceServerThread>b__0() (at D:/Travis/User Folders/Documents/Unity/Projects/BlockyBallv2/Assets/External/Mirror/Runtime/Transport/Ignorance/IgnoranceThreaded.cs:465)
System.Threading.ThreadHelper:ThreadStart()

I am unable to connect to it though and no errors were thrown in the file.

This is how the GameServer and client are configured in Unity:

image

And this is the json file configured for the MockVMAgent:

{
    "RunContainer": true,
    "OutputFolder": "D:\\PlayFab\\Agent\\0.7.1\\Output",
    "NumHeartBeatsForActivateResponse": 10,
    "NumHeartBeatsForTerminateResponse": 6000,
    "TitleId": "",
    "BuildId": "00000000-0000-0000-0000-000000000000",
    "Region": "WestUs",
    "AgentListeningPort": 56001,
    "ServerStartParameters": {
        "ImageDetails": {
            "Registry": "mcr.microsoft.com",
            "ImageName": "playfab/multiplayer",
            "ImageTag": "wsc-10.0.17134.950",
            "Username": "",
            "Password": ""
        },
        "AssetDetails": [
            {
                "MountPath": "C:\\Assets",
                "SasTokens": null,
                "LocalFilePath": "D:\\PlayFab\\GameServers\\BlockyBall\\BlockyBall-GameServer-0.0.27-Test.zip"
            }
        ],
        "StartGameCommand": "C:\\Assets\\BlockyBallv2.exe",
        "PortMappingsList": [
            [
                {
                    "NodePort": 56100,
                    "GamePort": {
                        "Name": "game_port",
                        "Number": 8080,
                        "Protocol": "UDP"
                    }
                }
            ]
        ]
    },
    "SessionConfig": {
        "SessionId": "ba67d671-512a-4e7d-a38c-2329ce181946",
        "SessionCookie": null,
        "InitialPlayers": [ "Player1", "Player2" ]
    }
}

Here is the beginning of the PlayFabMockVM log:

PS D:\PlayFab\Agent\0.7.1\Agent> ./MockVMAgent.exe                                                                      Warning: SessionCookie is not specified.
TitleId: 1E9926F9
BuildId: 9f816a84-3fdc-4606-9e4b-e6de8bea64a0
VmId: xcloudwusu4uyz5daouzl:WestUs:40f36fa7-98d9-4732-8682-18527fc3e9b5:tvmps_484d1824b16647a9ba9eb844b40e8879bb146bc817da4cccbd7688fbd1e9fbf3_d
info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
      User profile is available. Using 'C:\Users\travi\AppData\Local\ASP.NET\DataProtection-Keys' as key repository and Windows DPAPI to encrypt keys at rest.
Mock Agent is listening on port 56001
Player1, Player2
info: MockPlayFabVmAgent[0]
      game_port (UDP): Local port 56100 mapped to container port 8080
info: MockPlayFabVmAgent[0]
      Starting image pull for: mcr.microsoft.com/playfab/multiplayer:wsc-10.0.17134.950.
info: MockPlayFabVmAgent[0]
      [null]
info: MockPlayFabVmAgent[0]
      [null]
info: MockPlayFabVmAgent[0]
      [null]
info: MockPlayFabVmAgent[0]
      Event: PullImage. Properties: NULL, Metrics: {"downloadDuration":0.0,"extractDuration":0.0,"size":0.0}
info: MockPlayFabVmAgent[0]
      Event: ContainerStats. Properties: NULL, Metrics: {"containerCreationTimeMs":52.0}
info: MockPlayFabVmAgent[0]
      Created a container with session host id: ae1db2146e91489cb3238cbe236358838bf53883a44cbfc92eb5c4131f8d45fc
info: MockPlayFabVmAgent[0]
      Creating the configuration file at D:\PlayFab\Agent\0.7.1\Output\PlayFabVmAgentOutput\2019-11-20T20-44-25\Config\SH0\gsdkConfig.json
info: MockPlayFabVmAgent[0]
      Event: ContainerStats. Properties: NULL, Metrics: {"containerStartTimeMs":2384.0}
info: MockPlayFabVmAgent[0]
      Container ae1db2146e91489cb3238cbe236358838bf53883a44cbfc92eb5c4131f8d45fc start completed.
info: MockPlayFabVmAgent[0]
      Started container ae1db2146e91489cb3238cbe236358838bf53883a44cbfc92eb5c4131f8d45fc, with assignmentId ffffffff-ffff-ffff-f926-991e00000000:9f816a84-3fdc-4606-9e4b-e6de8bea64a0:WestUs, instance number 0, and logFolderId acc26c18-327f-4448-9af8-c5fceb6f3616
info: MockPlayFabVmAgent[0]
      Waiting for heartbeats from the game server.....

The localhost port on my machine 56100 is mapped to the docker container port 8080. The log says: game_port (UDP): Local port 56100 mapped to container port 8080. This works fine with Telepathy, but not Ignorance (In this case Ignorance Threaded).

It works fine when setting RunContainer: false in the JSON file so it does not appear to be an issue with the agent. The behavior seems to suggest that it is to do with the Docker container.

To clarify the entire process, I set the port for IgnoranceThreaded to 8080 after reading it from the json settings file. The Docker Container listens on 56100 and forwards that to port 8080 in the container (which IgnoranceThreaded is listening on).

TCROC commented 4 years ago

For anyone else that has this issue, IgnoranceThreaded does work in PlayFab Thunderhead in a Linux container. It does not work with PlayFab's MockVMAgent. It appears to be an issue with PlayFab's MockVM Agent.

Solution: Upload a build to PlayFab Thunderhead in a Linux Container

Windows Container in Thunderhead have not been tested yet.

SoftwareGuy commented 4 years ago

Shit, why did GitHub try to auto-close this? I'll make note of this in the readme.md file in the next commit.

Thanks again for helping debug this - your assistance was greatly appreciated.

TCROC commented 4 years ago

Of course! Thanks for working with me as well! Its so nice to find a great tool with a great creator who continuously supports it :)