Skip to content

Commit

Permalink
Updated Quic channel for the new async channel API.
Browse files Browse the repository at this point in the history
  • Loading branch information
yallie committed Dec 12, 2024
1 parent 3d03f11 commit 00a4fd3
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 87 deletions.
36 changes: 16 additions & 20 deletions CoreRemoting.Channels.Quic/CoreRemoting.Channels.Quic.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,24 @@

<PropertyGroup>
<TargetFramework>net9.0.0</TargetFramework>
<RootNamespace>CoreRemoting.Channels.Quic</RootNamespace>
<AssemblyName>CoreRemoting.Channels.Quic</AssemblyName>
<PackageVersion>1.2.1</PackageVersion>
<Authors>Alexey Yakovlev</Authors>
<Description>Quic channels for CoreRemoting</Description>
<Copyright>2024 Alexey Yakovlev</Copyright>
<PackageProjectUrl>https://github.com/theRainbird/CoreRemoting</PackageProjectUrl>
<PackageLicenseUrl></PackageLicenseUrl>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Title>CoreRemoting.Channels.Quic</Title>
<RepositoryUrl>https://github.com/theRainbird/CoreRemoting.git</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<AssemblyVersion>1.2.1</AssemblyVersion>
<LangVersion>10</LangVersion>
<RootNamespace>CoreRemoting.Channels.Quic</RootNamespace>
<AssemblyName>CoreRemoting.Channels.Quic</AssemblyName>
<PackageVersion>1.2.1</PackageVersion>
<Authors>Alexey Yakovlev</Authors>
<Description>Quic channels for CoreRemoting</Description>
<Copyright>2024 Alexey Yakovlev</Copyright>
<PackageProjectUrl>https://github.com/theRainbird/CoreRemoting</PackageProjectUrl>
<PackageLicenseUrl></PackageLicenseUrl>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Title>CoreRemoting.Channels.Quic</Title>
<RepositoryUrl>https://github.com/theRainbird/CoreRemoting.git</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<AssemblyVersion>1.2.1</AssemblyVersion>
<LangVersion>12</LangVersion>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<NoWarn>1701;1702;CA1416</NoWarn>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<NoWarn>1701;1702;1416</NoWarn>
<PropertyGroup>
<NoWarn>$(NoWarn),1701;1702;CA1416;NU1701,NU1903</NoWarn>
</PropertyGroup>

<ItemGroup>
Expand Down
81 changes: 30 additions & 51 deletions CoreRemoting.Channels.Quic/QuicClientChannel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Net.Security;
using System.Text;
using System.Threading.Tasks;
using CoreRemoting.Toolbox;

namespace CoreRemoting.Channels.Quic;

Expand Down Expand Up @@ -95,51 +96,39 @@ public void Init(IRemotingClient client)
}

/// <inheritdoc />
public void Connect()
public async Task ConnectAsync()
{
ConnectTask = ConnectTask ?? Task.Factory.StartNew(async () =>
// connect and open duplex stream
Connection = await QuicConnection.ConnectAsync(Options);
ClientStream = await Connection.OpenOutboundStreamAsync(QuicStreamType.Bidirectional);
ClientReader = new BinaryReader(ClientStream, Encoding.UTF8, leaveOpen: true);
ClientWriter = new BinaryWriter(ClientStream, Encoding.UTF8, leaveOpen: true);

// prepare handshake message
var handshakeMessage = Array.Empty<byte>();
if (Client.MessageEncryption)
{
// connect and open duplex stream
Connection = await QuicConnection.ConnectAsync(Options);
ClientStream = await Connection.OpenOutboundStreamAsync(QuicStreamType.Bidirectional);
ClientReader = new BinaryReader(ClientStream, Encoding.UTF8, leaveOpen: true);
ClientWriter = new BinaryWriter(ClientStream, Encoding.UTF8, leaveOpen: true);

// prepare handshake message
var handshakeMessage = Array.Empty<byte>();
if (Client.MessageEncryption)
{
handshakeMessage = Client.PublicKey;
}

// send handshake message
SendMessage(handshakeMessage);
IsConnected = true;
Connected?.Invoke();
handshakeMessage = Client.PublicKey;
}

// start listening for incoming messages
_ = Task.Factory.StartNew(() => StartListening());
});
// send handshake message
await SendMessageAsync(handshakeMessage);
IsConnected = true;
Connected?.Invoke();

ConnectTask.ConfigureAwait(false)
.GetAwaiter()
.GetResult();
// start listening for incoming messages
_ = Task.Run(() => ReadIncomingMessages());
}

private Task ConnectTask { get; set; }

private void StartListening()
private void ReadIncomingMessages()
{
try
{
while (IsConnected)
{
var messageSize = ClientReader.Read7BitEncodedInt();
var message = ClientReader.ReadBytes(Math.Min(messageSize, MaxMessageSize));
if (message.Length > 0)
{
ReceiveMessage(message);
}
ReceiveMessage(message);
}
}
catch (Exception ex)
Expand All @@ -152,12 +141,12 @@ private void StartListening()
}
finally
{
Disconnect();
DisconnectAsync().JustWait();
}
}

/// <inheritdoc />
public bool SendMessage(byte[] rawMessage)
public async Task<bool> SendMessageAsync(byte[] rawMessage)
{
try
{
Expand All @@ -167,7 +156,7 @@ public bool SendMessage(byte[] rawMessage)

// message length + message body
ClientWriter.Write7BitEncodedInt(rawMessage.Length);
ClientWriter.Write(rawMessage, 0, rawMessage.Length);
await ClientStream.WriteAsync(rawMessage, 0, rawMessage.Length);
return true;
}
catch (Exception ex)
Expand All @@ -180,17 +169,12 @@ public bool SendMessage(byte[] rawMessage)
}
}

private Task DisconnectTask { get; set; }

/// <inheritdoc />
public void Disconnect()
public async Task DisconnectAsync()
{
DisconnectTask = DisconnectTask ?? Task.Factory.StartNew(async () =>
{
await Connection.CloseAsync(0x0C);
IsConnected = false;
Disconnected?.Invoke();
});
await Connection.CloseAsync(0x0C);
IsConnected = false;
Disconnected?.Invoke();
}

/// <inheritdoc />
Expand All @@ -200,13 +184,8 @@ public void Dispose()
return;

if (IsConnected)
Disconnect();

var task = DisconnectTask;
if (task != null)
task.ConfigureAwait(false)
.GetAwaiter()
.GetResult();
DisconnectAsync()
.JustWait();

Connection.DisposeAsync()
.ConfigureAwait(false)
Expand Down
8 changes: 3 additions & 5 deletions CoreRemoting.Channels.Quic/QuicServerChannel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Net.Quic;
using System.Net.Security;
using System.Threading.Tasks;
using CoreRemoting.Toolbox;

namespace CoreRemoting.Channels.Quic;

Expand Down Expand Up @@ -61,7 +62,7 @@ public void Init(IRemotingServer server)
/// <inheritdoc/>
public void StartListening()
{
_ = Task.Factory.StartNew(async () =>
_ = Task.Run(async () =>
{
// start the listener
Listener = await QuicListener.ListenAsync(new QuicListenerOptions()
Expand Down Expand Up @@ -100,10 +101,7 @@ public void StopListening()
if (Listener != null && IsListening)
{
IsListening = false;
Listener.DisposeAsync()
.ConfigureAwait(false)
.GetAwaiter()
.GetResult();
Listener.DisposeAsync().JustWait();
}
}

Expand Down
15 changes: 6 additions & 9 deletions CoreRemoting.Channels.Quic/QuicServerConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Net.Quic;
using System.Text;
using System.Threading.Tasks;
using CoreRemoting.Toolbox;

namespace CoreRemoting.Channels.Quic;

Expand Down Expand Up @@ -52,7 +53,7 @@ public QuicServerConnection(QuicConnection connection, QuicStream stream, IRemot
public event Action Disconnected;

/// <inheritdoc/>
public bool SendMessage(byte[] rawMessage)
public async Task<bool> SendMessageAsync(byte[] rawMessage)
{
try
{
Expand All @@ -62,7 +63,7 @@ public bool SendMessage(byte[] rawMessage)

// message length + message body
ClientWriter.Write7BitEncodedInt(rawMessage.Length);
ClientWriter.Write(rawMessage, 0, rawMessage.Length);
await ClientStream.WriteAsync(rawMessage, 0, rawMessage.Length);
return true;
}
catch (Exception ex)
Expand All @@ -81,7 +82,7 @@ public bool SendMessage(byte[] rawMessage)
public Guid StartListening()
{
var sessionId = CreateRemotingSession();
_ = Task.Factory.StartNew(() => ReadIncomingMessages());
_ = Task.Run(() => ReadIncomingMessages());
return sessionId;
}

Expand Down Expand Up @@ -117,11 +118,7 @@ private void ReadIncomingMessages()
while (true)
{
var message = ReadIncomingMessage();
if (message != null && message.Length > 0)
{
// flush received QUIC message
ReceiveMessage(message);
}
ReceiveMessage(message ?? []);
}
}
catch (Exception ex)
Expand All @@ -134,7 +131,7 @@ private void ReadIncomingMessages()
}
finally
{
Connection?.DisposeAsync().ConfigureAwait(false).GetAwaiter().GetResult();
Connection?.DisposeAsync().JustWait();
Connection = null;
}
}
Expand Down
9 changes: 7 additions & 2 deletions CoreRemoting.Tests/CoreRemoting.Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net9.0</TargetFramework>
<EnableUnsafeBinaryFormatterSerialization>true</EnableUnsafeBinaryFormatterSerialization>
<IsPackable>false</IsPackable>
<NoWarn>$(NoWarn),NU1701,NU1903</NoWarn>
</PropertyGroup>

<!-- Exclude the unnecessary tests to save Github Actions time -->
<!-- WatsonTcp is the default channel, WebSocketSharp is optional -->
<!-- WatsonTcp is the default channel, WebSocketSharp is optional, Quic is .net9 only -->
<ItemGroup>
<Compile Remove="DisposableTests.Async.cs" />
<!--Compile Remove="RpcTests_Quic.cs" /-->
<Compile Remove="RpcTests_WatsonTcp.cs" />
<Compile Remove="RpcTests_WebsocketSharp.cs" />
<Compile Remove="RpcTests_WsClientWsharpServer.cs" />
Expand All @@ -33,6 +34,10 @@
</PackageReference>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\CoreRemoting.Channels.Quic\CoreRemoting.Channels.Quic.csproj" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\CoreRemoting.Channels.WebsocketSharp\CoreRemoting.Channels.WebsocketSharp.csproj" />
<ProjectReference Include="..\CoreRemoting.Tests.ExternalTypes\CoreRemoting.Tests.ExternalTypes.csproj" />
Expand Down
17 changes: 17 additions & 0 deletions CoreRemoting.Tests/RpcTests_Quic.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using CoreRemoting.Channels;
using CoreRemoting.Channels.Quic;
using Xunit.Abstractions;

namespace CoreRemoting.Tests
{
public class RpcTests_Quic : RpcTests
{
protected override IServerChannel ServerChannel => new QuicServerChannel();

protected override IClientChannel ClientChannel => new QuicClientChannel();

public RpcTests_Quic(ServerFixture fixture, ITestOutputHelper helper) : base(fixture, helper)
{
}
}
}
6 changes: 6 additions & 0 deletions CoreRemoting.sln
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CoreRemoting.Tests.External
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CoreRemoting.Channels.WebsocketSharp", "CoreRemoting.Channels.WebsocketSharp\CoreRemoting.Channels.WebsocketSharp.csproj", "{A2440A47-F1F2-4556-958B-5CA19BF17A59}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CoreRemoting.Channels.Quic", "CoreRemoting.Channels.Quic\CoreRemoting.Channels.Quic.csproj", "{6CC666E2-A400-4409-A9CA-3583BE832A2C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -78,6 +80,10 @@ Global
{A2440A47-F1F2-4556-958B-5CA19BF17A59}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A2440A47-F1F2-4556-958B-5CA19BF17A59}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A2440A47-F1F2-4556-958B-5CA19BF17A59}.Release|Any CPU.Build.0 = Release|Any CPU
{6CC666E2-A400-4409-A9CA-3583BE832A2C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6CC666E2-A400-4409-A9CA-3583BE832A2C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6CC666E2-A400-4409-A9CA-3583BE832A2C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6CC666E2-A400-4409-A9CA-3583BE832A2C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down

0 comments on commit 00a4fd3

Please sign in to comment.