diff --git a/.gitignore b/.gitignore
index 25e7ded..ece189d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -44,3 +44,5 @@ UpgradeLog.htm
*.svclog
mono_crash.*.json
mono_crash.*.blob
+
+autobahn/reports/*
\ No newline at end of file
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 60f38ba..f89a17b 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -2,7 +2,7 @@
true
-
@@ -13,9 +13,8 @@
-
+
-
@@ -28,4 +27,4 @@
-
+
\ No newline at end of file
diff --git a/SimpleR.sln b/SimpleR.sln
index 6ee7df7..518a23b 100644
--- a/SimpleR.sln
+++ b/SimpleR.sln
@@ -64,6 +64,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ext", "ext", "{813A63E0-FB3
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleR.Ocpp", "ext\SimpleR.Ocpp\SimpleR.Ocpp.csproj", "{531643BE-44A4-404B-A3BB-6C44BC7C49D9}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "autobahn", "autobahn", "{D4D520AA-4FE3-4F44-857B-B4AC0AF37E5A}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleR.Authobahn.Server", "autobahn\server\SimpleR.Authobahn.Server.csproj", "{2D7F07BA-59E0-4B6D-8AB2-5AF9962AAD13}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -144,6 +148,12 @@ Global
{531643BE-44A4-404B-A3BB-6C44BC7C49D9}.Release|Any CPU.Build.0 = Release|Any CPU
{531643BE-44A4-404B-A3BB-6C44BC7C49D9}.Publish|Any CPU.ActiveCfg = Debug|Any CPU
{531643BE-44A4-404B-A3BB-6C44BC7C49D9}.Publish|Any CPU.Build.0 = Debug|Any CPU
+ {2D7F07BA-59E0-4B6D-8AB2-5AF9962AAD13}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2D7F07BA-59E0-4B6D-8AB2-5AF9962AAD13}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2D7F07BA-59E0-4B6D-8AB2-5AF9962AAD13}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {2D7F07BA-59E0-4B6D-8AB2-5AF9962AAD13}.Release|Any CPU.Build.0 = Release|Any CPU
+ {2D7F07BA-59E0-4B6D-8AB2-5AF9962AAD13}.Publish|Any CPU.ActiveCfg = Debug|Any CPU
+ {2D7F07BA-59E0-4B6D-8AB2-5AF9962AAD13}.Publish|Any CPU.Build.0 = Debug|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -164,5 +174,6 @@ Global
{8CA715D9-6491-42C2-878D-6FBDA9D9B87C} = {D1E4601A-E2A0-43AC-8D33-B05D0001C88F}
{1EFE8056-F4BD-4ED0-B7AB-5B61BFE35C29} = {4BEDDC2A-CC7B-4650-BC97-AF81DE36D351}
{531643BE-44A4-404B-A3BB-6C44BC7C49D9} = {813A63E0-FB31-48A3-AC0D-D4F3C469706A}
+ {2D7F07BA-59E0-4B6D-8AB2-5AF9962AAD13} = {D4D520AA-4FE3-4F44-857B-B4AC0AF37E5A}
EndGlobalSection
EndGlobal
diff --git a/autobahn/config/fuzzingclient.json b/autobahn/config/fuzzingclient.json
new file mode 100644
index 0000000..48d6cac
--- /dev/null
+++ b/autobahn/config/fuzzingclient.json
@@ -0,0 +1,13 @@
+{
+ "options": {"failByDrop": false},
+ "outdir": "./reports/servers",
+
+ "servers": [{"agent": "SimpleR", "url": "ws://host.docker.internal:9002"}],
+ "cases": ["*"],
+ "exclude-cases": [
+ "9.*",
+ "12.*",
+ "13.*"
+ ],
+ "exclude-agent-cases": {}
+ }
\ No newline at end of file
diff --git a/autobahn/fuzzingclient.sh b/autobahn/fuzzingclient.sh
new file mode 100755
index 0000000..54d8061
--- /dev/null
+++ b/autobahn/fuzzingclient.sh
@@ -0,0 +1,3 @@
+#! /bin/sh
+
+docker run -it --rm -v "${PWD}/config:/config" -v "${PWD}/reports:/reports" -p 9002:9002 --name fuzzingclient crossbario/autobahn-testsuite wstest -m fuzzingclient -s /config/fuzzingclient.json
\ No newline at end of file
diff --git a/autobahn/server/EchoDispatcher.cs b/autobahn/server/EchoDispatcher.cs
new file mode 100644
index 0000000..ed561f0
--- /dev/null
+++ b/autobahn/server/EchoDispatcher.cs
@@ -0,0 +1,19 @@
+namespace SimpleR.Authobahn.Server;
+
+public class EchoDispatcher : IWebSocketMessageDispatcher
+{
+ public Task OnConnectedAsync(IWebsocketConnectionContext connection)
+ {
+ return Task.CompletedTask;
+ }
+
+ public Task OnDisconnectedAsync(IWebsocketConnectionContext connection, Exception? exception)
+ {
+ return Task.CompletedTask;
+ }
+
+ public async Task DispatchMessageAsync(IWebsocketConnectionContext connection, byte[] message)
+ {
+ await connection.WriteAsync(message);
+ }
+}
\ No newline at end of file
diff --git a/autobahn/server/EchoProtocol.cs b/autobahn/server/EchoProtocol.cs
new file mode 100644
index 0000000..3d15f59
--- /dev/null
+++ b/autobahn/server/EchoProtocol.cs
@@ -0,0 +1,17 @@
+using System.Buffers;
+using SimpleR.Protocol;
+
+namespace SimpleR.Authobahn.Server;
+
+public class EchoProtocol : IDelimitedMessageProtocol
+{
+ public void WriteMessage(byte[] message, IBufferWriter output)
+ {
+ output.Write(message);
+ }
+
+ public byte[] ParseMessage(ref ReadOnlySequence input)
+ {
+ return input.ToArray();
+ }
+}
\ No newline at end of file
diff --git a/autobahn/server/Program.cs b/autobahn/server/Program.cs
new file mode 100644
index 0000000..feec011
--- /dev/null
+++ b/autobahn/server/Program.cs
@@ -0,0 +1,20 @@
+using SimpleR.Authobahn.Server;
+using SimpleR.Protocol;
+
+var builder = WebApplication.CreateBuilder(args);
+
+// Add services to the container.
+builder.Services.AddSimpleR();
+
+var app = builder.Build();
+
+app.UseRouting();
+
+app.UseAuthorization();
+
+app.MapSimpleR("/", b =>
+{
+ b.UseEndOfMessageDelimitedProtocol(new EchoProtocol()).UseDispatcher();
+});
+
+app.Run();
diff --git a/autobahn/server/Properties/launchSettings.json b/autobahn/server/Properties/launchSettings.json
new file mode 100644
index 0000000..1ebded2
--- /dev/null
+++ b/autobahn/server/Properties/launchSettings.json
@@ -0,0 +1,38 @@
+{
+ "$schema": "http://json.schemastore.org/launchsettings.json",
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:62410",
+ "sslPort": 44332
+ }
+ },
+ "profiles": {
+ "http": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": true,
+ "applicationUrl": "http://localhost:9002",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "https": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": true,
+ "applicationUrl": "https://localhost:9003;http://localhost:9002",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/autobahn/server/SimpleR.Authobahn.Server.csproj b/autobahn/server/SimpleR.Authobahn.Server.csproj
new file mode 100644
index 0000000..88bb118
--- /dev/null
+++ b/autobahn/server/SimpleR.Authobahn.Server.csproj
@@ -0,0 +1,13 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+
+
+
+
+
+
diff --git a/autobahn/server/appsettings.Development.json b/autobahn/server/appsettings.Development.json
new file mode 100644
index 0000000..33e2405
--- /dev/null
+++ b/autobahn/server/appsettings.Development.json
@@ -0,0 +1,8 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Trace",
+ "Microsoft.AspNetCore": "Trace"
+ }
+ }
+}
diff --git a/autobahn/server/appsettings.json b/autobahn/server/appsettings.json
new file mode 100644
index 0000000..10f68b8
--- /dev/null
+++ b/autobahn/server/appsettings.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ },
+ "AllowedHosts": "*"
+}
diff --git a/test/PingPong.Server.Tests/Binary/PingPongCustomBinaryProtocolTests.cs b/test/PingPong.Server.Tests/Binary/PingPongCustomBinaryProtocolTests.cs
index 7f94afb..bc62303 100644
--- a/test/PingPong.Server.Tests/Binary/PingPongCustomBinaryProtocolTests.cs
+++ b/test/PingPong.Server.Tests/Binary/PingPongCustomBinaryProtocolTests.cs
@@ -45,27 +45,4 @@ await socket.SendAsync(new ArraySegment(new byte[] { 5, 0 }), WebSocketMes
client.Dispose();
}
}
-
- [Fact]
- public async Task SendSinglePartMessage_GetReversed()
- {
- // Arrange
- var receivedQueue = new List();
- var (client, socket) = await _factory.Server.ConnectWebsocketAsync(_route);
- try
- {
- using var sub = client.MessageReceived.Subscribe(message => { receivedQueue.Add(message.Binary); });
-
- await socket.SendAsync(new ArraySegment(new byte[] { 1, 2, 3, 4, 5, 0 }), WebSocketMessageType.Binary,
- false, CancellationToken.None);
- await WaitHelpers.WaitFor(() => receivedQueue.Any());
-
- receivedQueue.Should().HaveCount(1);
- receivedQueue[0].Should().Equal(5, 4, 3, 2, 1);
- }
- finally
- {
- client.Dispose();
- }
- }
}
\ No newline at end of file
diff --git a/test/PingPong.Server.Tests/Binary/PingPongDelimitedBinaryProtocolTests.cs b/test/PingPong.Server.Tests/Binary/PingPongDelimitedBinaryProtocolTests.cs
index 846bb6a..905d431 100644
--- a/test/PingPong.Server.Tests/Binary/PingPongDelimitedBinaryProtocolTests.cs
+++ b/test/PingPong.Server.Tests/Binary/PingPongDelimitedBinaryProtocolTests.cs
@@ -66,4 +66,30 @@ await socket.SendAsync(new ArraySegment(new byte[] { 1, 2, 3, 4, 5 }), Web
client.Dispose();
}
}
+
+ [Fact]
+ public async Task SendEmptyMessage_GetReversed()
+ {
+ // Arrange
+ var receivedQueue = new List();
+ var (client, socket) = await _factory.Server.ConnectWebsocketAsync(_route);
+ try
+ {
+ using var sub = client.MessageReceived.Subscribe((message) => { receivedQueue.Add(message.Binary); });
+
+ await socket.SendAsync(new ArraySegment([], 0, 0), WebSocketMessageType.Binary,
+ true, CancellationToken.None);
+ await socket.SendAsync(new ArraySegment([], 0, 0), WebSocketMessageType.Binary,
+ true, CancellationToken.None);
+ await WaitHelpers.WaitFor(() => receivedQueue.Count == 2);
+
+ receivedQueue.Should().HaveCount(2);
+ receivedQueue[0].Should().Equal([]);
+ receivedQueue[1].Should().Equal([]);
+ }
+ finally
+ {
+ client.Dispose();
+ }
+ }
}
\ No newline at end of file
diff --git a/test/PingPong.Server.Tests/Text/PingPongCustomTextProtocolTests.cs b/test/PingPong.Server.Tests/Text/PingPongCustomTextProtocolTests.cs
index 8421738..7ce3596 100644
--- a/test/PingPong.Server.Tests/Text/PingPongCustomTextProtocolTests.cs
+++ b/test/PingPong.Server.Tests/Text/PingPongCustomTextProtocolTests.cs
@@ -72,5 +72,4 @@ await socket.SendAsync(new ArraySegment(bytes), WebSocketMessageType.Text,
client.Dispose();
}
}
-
}
\ No newline at end of file
diff --git a/test/PingPong.Server.Tests/Text/PingPongDelimitedTextProtocolTests.cs b/test/PingPong.Server.Tests/Text/PingPongDelimitedTextProtocolTests.cs
index 08952ec..f7435b2 100644
--- a/test/PingPong.Server.Tests/Text/PingPongDelimitedTextProtocolTests.cs
+++ b/test/PingPong.Server.Tests/Text/PingPongDelimitedTextProtocolTests.cs
@@ -81,4 +81,30 @@ await socket.SendAsync(new ArraySegment(bytes), WebSocketMessageType.Text,
client.Dispose();
}
}
+
+ [Fact]
+ public async Task SendEmptyMessage_GetBack()
+ {
+ // Arrange
+ var receivedQueue = new List();
+ var (client, socket) = await _factory.Server.ConnectWebsocketAsync(_route);
+ try
+ {
+ using var sub = client.MessageReceived.Subscribe((message) => { receivedQueue.Add(message.Text); });
+ await socket.SendAsync(new ArraySegment([], 0, 0), WebSocketMessageType.Text, true,
+ CancellationToken.None);
+ await socket.SendAsync(new ArraySegment([], 0, 0), WebSocketMessageType.Text, true,
+ CancellationToken.None);
+
+ await WaitHelpers.WaitFor(() => receivedQueue.Count == 2);
+
+ receivedQueue.Should().HaveCount(2);
+ receivedQueue[0].Should().Be("");
+ receivedQueue[1].Should().Be("");
+ }
+ finally
+ {
+ client.Dispose();
+ }
+ }
}
\ No newline at end of file
diff --git a/test/SimpleR.Protocol.Tests/FrameBufferWriterTests.cs b/test/SimpleR.Protocol.Tests/FrameBufferWriterTests.cs
index ab10838..d3f8ae9 100644
--- a/test/SimpleR.Protocol.Tests/FrameBufferWriterTests.cs
+++ b/test/SimpleR.Protocol.Tests/FrameBufferWriterTests.cs
@@ -17,6 +17,23 @@ public FrameBufferWriterTests()
_frameWriter = new FrameBufferWriter(_bufferWriter);
}
+ [Fact]
+ public void EmptyAdvance_ShouldBeCorrect()
+ {
+ // Advance the writer by the number of bytes written
+ _frameWriter.Advance(0);
+
+ // Finish writing the last frame
+ _frameWriter.FinishLastFrame(true);
+
+ // Get the written bytes as an array
+ var result = _bufferWriter.WrittenMemory.ToArray();
+
+ // Assert that the result is as expected
+ result.Should()
+ .BeEquivalentTo(new byte[] { 0, 0, 0, 0, 1 });
+ }
+
[Fact]
public void WriteTwoFrames_UsingMemory_ShouldBeCorrect()
{