dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
34.82k stars 9.84k forks source link

[SignalR] Precision on specifications for MessagePack #43455

Open LioRei opened 1 year ago

LioRei commented 1 year ago

Is there an existing issue for this?

Describe the bug

Hi, I try to create a lib to communicate with SignalR from an Arduino (ESP32S2 Saola to be precise) and I'm using HubProtocol.md as reference for my dev.

As Arduino is a very limited device, I want to use MessagePack as serialization and websocket as transport but I've 2 "issues".

1) The HandshakeResponse is sended in binary and not in text

It's not really an issue, I can manage a response in binary but in TransportProtocols.md it is specified this "When using a text-based protocol like JSON, it is preferable for the WebSockets transport to use Text frames.". As Handshake is always in json, I've waited for a response in text. Maybe, it's a good idea to specify in the document that when using MessagePack, the reponse will be in binary.

2) In regular frame after Handshake, I have 1 unspecified byte more in frame

I've verified with Wireshark the problem : image

At the end of the payload, 0x82 0x03 is a correct websocket header that specify a binary frame with 3 bytes of payload and 0x91 0x06 is a valid Ping message but what is 0x02 ? I have checked the whole documentation and nowhere it's specified a header or something else between the websocket header and the message. For reference, I quote the Ping message specification :

image

Expected Behavior

Suppression of the "unwanted" byte or a modification of the specification to tell what is this byte to be able to write a conform client

Steps To Reproduce

My test program (on C# side) is very simple, 1 aspnet core project with 1 SignalR hub:

Program.cs:

namespace Arduino.SignalR.Client.DemoServer
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var builder = WebApplication.CreateBuilder(args);

            builder.Services.AddSignalR().AddMessagePackProtocol();

            var app = builder.Build();

            app.MapHub<TestHub>("/TestHub");

            app.Run();
        }
    }
}

TestHub.cs:

using Microsoft.AspNetCore.SignalR;

namespace Arduino.SignalR.Client.DemoServer
{
    public class TestHub : Hub
    {
        public async Task EchoMessage(string message)
        {
            await Clients.All.SendAsync("ReceivedMessage", message);
        }
    }
}

The Arduino side is a little more complexe and could be find here Arduino.SignalR.Client. It's a WIP :)

Exceptions (if any)

No response

.NET Version

6.0.400

Anything else?

ASP.NET Core version: 6.0 IDE: Visual studio for C# and Cpp

dotnet --info
.NET SDK (reflecting any global.json):
 Version:   6.0.400
 Commit:    7771abd614

Environnement d'exécution :
 OS Name:     Windows
 OS Version:  10.0.19044
 OS Platform: Windows
 RID:         win10-x64
 Base Path:   C:\Program Files\dotnet\sdk\6.0.400\

global.json file:
  Not found

Host:
  Version:      6.0.8
  Architecture: x64
  Commit:       55fb7ef977

.NET SDKs installed:
  2.2.207 [C:\Program Files\dotnet\sdk]
  3.1.422 [C:\Program Files\dotnet\sdk]
  5.0.303 [C:\Program Files\dotnet\sdk]
  5.0.408 [C:\Program Files\dotnet\sdk]
  6.0.202 [C:\Program Files\dotnet\sdk]
  6.0.203 [C:\Program Files\dotnet\sdk]
  6.0.303 [C:\Program Files\dotnet\sdk]
  6.0.400 [C:\Program Files\dotnet\sdk]

.NET runtimes installed:
  Microsoft.AspNetCore.All 2.2.8 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.App 2.2.8 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.1.28 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 5.0.9 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 5.0.10 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 5.0.17 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 6.0.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 6.0.8 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 2.2.8 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.1.28 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 5.0.9 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 5.0.10 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 5.0.17 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 6.0.4 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 6.0.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 6.0.8 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.WindowsDesktop.App 3.1.28 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 5.0.9 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 5.0.10 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 5.0.17 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 6.0.4 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 6.0.5 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 6.0.8 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

Download .NET:
  https://aka.ms/dotnet-download

Learn about .NET Runtimes and SDKs:
  https://aka.ms/dotnet/runtimes-sdk-info
davidfowl commented 1 year ago

It's not really an issue, I can manage a response in binary but in TransportProtocols.md it is specified this "When using a text-based protocol like JSON, it is preferable for the WebSockets transport to use Text frames.". As Handshake is always in json, I've waited for a response in text. Maybe, it's a good idea to specify in the document that when using MessagePack, the reponse will be in binary.

That's a good point. Since SignalR assumes a "stream based transport" there's no way to mark individual messages so the entire transport is either considered binary or text. We should update this in the spec.

PS: We have a C++ client here that maybe you can take inspiration from (or directly use) https://github.com/aspnet/SignalR-Client-Cpp/tree/main/src/signalrclient

LioRei commented 1 year ago

I've seen this repo only today :) but I can't use it directly (too much dependencies that require a "real" Cpp compilator). But yes, it would be a good example of what to do and how

BrennanConroy commented 1 year ago

0x91 0x06 is a valid Ping message but what is 0x02 ?

The MessagePack hub protocol is well defined at https://github.com/dotnet/aspnetcore/blob/main/src/SignalR/docs/specs/HubProtocol.md#messagepack-msgpack-encoding, the 0x02 is specifically the length prefix described at https://github.com/dotnet/aspnetcore/blob/main/src/SignalR/docs/specs/HubProtocol.md#binary-encoding

LioRei commented 1 year ago

My bad, I've not read this section as I have a lib who do the serialization for me 😅 Maybe this section worth a better visibility ? Like being between "MessagePack (MsgPack) encoding" and "Invocation Message Encoding"?

Thx for the response, I can continue my work to connect small object to big datacenter in real time

LioRei commented 1 year ago

You can close this issue if you want 😉

BrennanConroy commented 1 year ago

As Handshake is always in json, I've waited for a response in text. Maybe, it's a good idea to specify in the document that when using MessagePack, the reponse will be in binary.

This is definitely worth calling out, let's keep the issue open for doc improvements.

wadepickett commented 1 year ago

@BrennanConroy, Are we good with how we point out the messages are binary in this section here?: [Use MessagePack Hub Protocol in SignalR for ASP.NET Core - What is MessagePack?] https://docs.microsoft.com/en-us/aspnet/core/signalr/messagepackhubprotocol?view=aspnetcore-6.0#what-is-messagepack]. Is something more needed? If that is good, then I will verify we have something similar in other SignalR docs that mention MessagePack.

BrennanConroy commented 1 year ago

This is tracking updating https://github.com/dotnet/aspnetcore/blob/main/src/SignalR/docs/specs/HubProtocol.md, sorry we used the same label you're now looking at for the docs repo.