Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Confused about DispatchMessageQueue() and different order of OnClose/OnMessage in the latest version #67

Open
xucian opened this issue Jun 19, 2022 · 3 comments
Labels
bug Something isn't working

Comments

@xucian
Copy link

xucian commented Jun 19, 2022

Hi, I recently updated to the latest version and I realized OnMessage is not being called anymore.
I've spent several hours debugging and, by mistake, discovered this DispatchMessageQueue() method, which is not called by anyone.
Did I just have a very old version where this method was automatically called? I don't find the text "DispatchMessageQueue" anywhere throughout any of the involved projects, so it means in my last version it was called automatically, internally.
I really looked among your release notes before upgrading and such a breaking change wasn't mentioned anywhere..
Was my version just an ancient one (like before 1.0.0)? Just trying to understand what happened.
Very useful library, BTW. Thanks!

@xucian
Copy link
Author

xucian commented Jun 19, 2022

Also, I'm getting some messages in a different order. Specifically, it seems that previously I was able to disconnect and reconnect a player and sync any lost messages (which I cache locally on both the server and the client), and now I receive a disconnect event a bit sooner than expected (and I suppose there might be other subtle differences).
This is a hefty process that I didn't want to ever dive into again, as it took ages to design properly.

I suppose several other things changed, not only when OnMessage() is called, as I also tried to call OnMessage manually, to closely match the old way, but issues still happen.
This is the older code of Receive():

		public async Task Receive()
		{
			ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[8192]);

			while (m_Socket.State == System.Net.WebSockets.WebSocketState.Open)
			{
				WebSocketReceiveResult result = null;

				using (var ms = new MemoryStream())
				{
					do
					{
						result = await m_Socket.ReceiveAsync(buffer, CancellationToken.None);
						ms.Write(buffer.Array, buffer.Offset, result.Count);
					}
					while (!result.EndOfMessage);

					ms.Seek(0, SeekOrigin.Begin);

					if (result.MessageType == WebSocketMessageType.Text)
					{
						OnMessage?.Invoke(ms.ToArray());
						//using (var reader = new StreamReader(ms, Encoding.UTF8))
						//{
						//	string message = reader.ReadToEnd();
						//	OnMessage?.Invoke(this, new MessageEventArgs(message));
						//}
					}
					else if (result.MessageType == WebSocketMessageType.Binary)
					{
						OnMessage?.Invoke(ms.ToArray());
					}
					else if (result.MessageType == WebSocketMessageType.Close)
					{
						await Close();
						OnClose?.Invoke(WebSocketHelpers.ParseCloseCodeEnum((int)result.CloseStatus));
						break;
					}
				}
			}

		}

and this is the current one in this repo:

        public async Task Receive()
        {
            WebSocketCloseCode closeCode = WebSocketCloseCode.Abnormal;
            await new WaitForBackgroundThread();

            ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[8192]);
            try
            {
                while (m_Socket.State == System.Net.WebSockets.WebSocketState.Open)
                {
                    WebSocketReceiveResult result = null;

                    using (var ms = new MemoryStream())
                    {
                        do
                        {
                            result = await m_Socket.ReceiveAsync(buffer, m_CancellationToken);
                            ms.Write(buffer.Array, buffer.Offset, result.Count);
                        }
                        while (!result.EndOfMessage);

                        ms.Seek(0, SeekOrigin.Begin);

                        if (result.MessageType == WebSocketMessageType.Text)
                        {
                            lock (IncomingMessageLock)
                            {
                              m_MessageList.Add(ms.ToArray());
                            }

                            //using (var reader = new StreamReader(ms, Encoding.UTF8))
                            //{
                            //	string message = reader.ReadToEnd();
                            //	OnMessage?.Invoke(this, new MessageEventArgs(message));
                            //}
                        }
                        else if (result.MessageType == WebSocketMessageType.Binary)
                        {
                            lock (IncomingMessageLock)
                            {
                              m_MessageList.Add(ms.ToArray());
                            }
                        }
                        else if (result.MessageType == WebSocketMessageType.Close)
                        {
                            await Close();
                            closeCode = WebSocketHelpers.ParseCloseCodeEnum((int)result.CloseStatus);
                            break;
                        }
                    }
                }
            }
            catch (Exception)
            {
                m_TokenSource.Cancel();
            }
            finally
            {
                await new WaitForUpdate();
                OnClose?.Invoke(closeCode);
            }
        }

Is there any obvious change that could lead to my issue?
I'd be really grateful for any direction, as I have very different usages of this plugin in my project and they all relied on the older behavior. Specifically, the gameplay module has around 100 game events that depend on the "correct" order of OnMessage/OnClose etc.
I imagine a solution would invove either me changing the code in my logic, or changing something in the plugin itself. Anything that could help me track the issue is highly appreciated!

@xucian xucian changed the title Confused about DispatchMessageQueue() Confused about DispatchMessageQueue() and different order of OnClose/OnMessage in the latest version Jun 19, 2022
@endel endel added the bug Something isn't working label Jun 20, 2022
@endel
Copy link
Owner

endel commented Jun 20, 2022

Hi @tfgstudios, this change on the library has been introduced since this PR #11, IIRC this new threading mechanism was due to extra unnecessary delays happening on the previous implementation when receiving messages.

I think you are right regarding the order of "close" and message events that differ after this release. The await Close(); is triggered immediately when parsing incoming message, whereas binary and text messages are enqueued for the next "queue dispatch". So if a "close" happens to be received along with other messages, it will fire first.

I've flagged this issue as a bug, please let me know if you have any luck fixing this!

@xucian
Copy link
Author

xucian commented Jun 28, 2022

Hey, I was only able to fix it on the user side. There were other issues (Unity's own ones) in the play, so I'm not sure which fixed which.
Based on your comment, this still remains a bug, albeit it doesn't affect my specific case anymore.
What I can say is this plugin is very useful and thanks for it! I hope it'll remain actual in the next years

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants