BarRaider / obs-websocket-dotnet

C# .NET library to communicate with an obs-websocket server
MIT License
224 stars 104 forks source link

[BUG] Connect does not ensure that identify sequence has completed #112

Closed justinas55 closed 2 years ago

justinas55 commented 2 years ago

Issue Type

Describe the bug If I want websocket to connect and send command right away - sometimes it fails. For example this code (Code 1):

for(int i = 0; i < 100; i++)
{
    var obsApi = new ObsApiClient("ws://localhost:4444", "");
    obsApi.Connect();
    var result = obsApi.GetStreamStatus(); // this line would hang indefinitely at random occurrences
}

After some investigation and checking OBS logs I found that Connect() does not wait opcode sequence (0 Hello > 1 Identify > 2 Identified) before request is sent and so sometimes 'identified' is not fast enough and it fails. (https://github.com/BarRaider/obs-websocket-dotnet/blob/403f673b7d82b222ffbb36af91d54b02909101d7/obs-websocket-dotnet/OBSWebsocket.cs#L98 , https://github.com/BarRaider/obs-websocket-dotnet/blob/403f673b7d82b222ffbb36af91d54b02909101d7/obs-websocket-dotnet/OBSWebsocket.cs#L160)

As a workaround I'm using this helper method:

    public static class ObsClientExtensions
    {
        public static bool EnsureConnected(this OBSWebsocket client, string url, string password = "")
        {
            if (client.IsConnected)
            {
                return true;
            }

            using (var manualReset = new ManualResetEventSlim())
            {
                EventHandler connected = (s, e) => manualReset.Set();
                try
                {
                    client.Connected += connected;
                    client.Connect(url, password);

                    if (!manualReset.Wait(2000))
                    {
                        client.Disconnect();
                        return false;
                    }

                    return true;
                }
                finally
                {
                    client.Connected -= connected;
                }
            }
        }
    }

then this code works reliably:

            var obsApi = new OBSWebsocket();
            obsApi.EnsureConnected("ws://localhost:4444", "");
            var result = obsApi.GetStreamStatus();

To Reproduce Steps to reproduce the behavior:

  1. Run test with 'Code 1'
  2. Test hangs

Expected behavior Test succeeds in maximum few seconds.

Screenshots N/A

Versions OBS Version: 28.0.1 OBS WebSocket Version: 5.0.1 OBS WebSocket Dotnet (this library) Version: 5.0.0 (not beta) OS: Windows 10

BarRaider commented 2 years ago

I am not sure I would consider it a bug. You should be listening to the Connected (and Disconnected) events and run commands only after they've been triggered.