Route C# mesh clients through RUDP endpoints
This commit is contained in:
parent
114fb86b0f
commit
9621d310f0
3 changed files with 147 additions and 8 deletions
|
|
@ -339,7 +339,8 @@ namespace GameCult.Mesh
|
|||
public Action<Client>? ConfigureClient { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the schema-v0 client factory. Defaults to the C# LiteNetLib adapter.
|
||||
/// Gets or sets the schema-v0 client factory.
|
||||
/// Defaults to endpoint selection: rudp:// uses RUDP and cultnet:// uses LiteNetLib.
|
||||
/// </summary>
|
||||
public Func<ICultNetSchemaClient>? CreateClient { get; set; }
|
||||
}
|
||||
|
|
@ -375,7 +376,7 @@ namespace GameCult.Mesh
|
|||
var completion = new TaskCompletionSource<CultMeshPeerExchangeResponseMessage>(
|
||||
TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
|
||||
using var client = CreateClient();
|
||||
using var client = CreateClient(endpoint);
|
||||
client.OnCultNet<CultMeshPeerExchangeResponseMessage>(response =>
|
||||
{
|
||||
if (string.Equals(response.MessageId, messageId, StringComparison.Ordinal))
|
||||
|
|
@ -431,10 +432,10 @@ namespace GameCult.Mesh
|
|||
return count;
|
||||
}
|
||||
|
||||
private ICultNetSchemaClient CreateClient()
|
||||
private ICultNetSchemaClient CreateClient(string endpoint)
|
||||
{
|
||||
return _options.CreateClient?.Invoke()
|
||||
?? CultNetSchemaClients.CreateLiteNetLib(_options.Security, _options.ConfigureClient);
|
||||
?? CultNetSchemaClients.CreateForEndpoint(endpoint, _options.Security, _options.ConfigureClient);
|
||||
}
|
||||
|
||||
private async Task WaitForConnectionAsync(ICultNetSchemaClient client, string endpoint)
|
||||
|
|
|
|||
|
|
@ -157,7 +157,8 @@ namespace GameCult.Mesh
|
|||
public Action<Client>? ConfigureClient { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the schema-v0 client factory. Defaults to the C# LiteNetLib adapter.
|
||||
/// Gets or sets the schema-v0 client factory.
|
||||
/// Defaults to endpoint selection: rudp:// uses RUDP and cultnet:// uses LiteNetLib.
|
||||
/// </summary>
|
||||
public Func<ICultNetSchemaClient>? CreateClient { get; set; }
|
||||
}
|
||||
|
|
@ -190,7 +191,7 @@ namespace GameCult.Mesh
|
|||
var completion = new TaskCompletionSource<CultMeshVerseCatalogResponseMessage>(
|
||||
TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
|
||||
using var client = CreateClient();
|
||||
using var client = CreateClient(endpoint);
|
||||
client.OnCultNet<CultMeshVerseCatalogResponseMessage>(response =>
|
||||
{
|
||||
if (string.Equals(response.MessageId, messageId, StringComparison.Ordinal))
|
||||
|
|
@ -238,10 +239,10 @@ namespace GameCult.Mesh
|
|||
return count;
|
||||
}
|
||||
|
||||
private ICultNetSchemaClient CreateClient()
|
||||
private ICultNetSchemaClient CreateClient(string endpoint)
|
||||
{
|
||||
return _options.CreateClient?.Invoke()
|
||||
?? CultNetSchemaClients.CreateLiteNetLib(_options.Security, _options.ConfigureClient);
|
||||
?? CultNetSchemaClients.CreateForEndpoint(endpoint, _options.Security, _options.ConfigureClient);
|
||||
}
|
||||
|
||||
private async Task WaitForConnectionAsync(ICultNetSchemaClient client, string endpoint)
|
||||
|
|
|
|||
|
|
@ -1836,6 +1836,143 @@ namespace GameCult.Networking.Tests
|
|||
Assert.That(response.Schemas.Single().SchemaId, Is.EqualTo("rudp.schema.test"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task CultMeshVerseDiscoveryClient_Fetches_Over_RudpEndpoint()
|
||||
{
|
||||
using var serverSocket = BindUdpSocket();
|
||||
using var server = new CultNetRudpSocketTransportConnection(new CultNetRudpSocketTransportOptions
|
||||
{
|
||||
RuntimeId = "csharp-rudp-verse-discovery-server",
|
||||
Mode = CultNetRudpSocketMode.Server,
|
||||
Socket = serverSocket,
|
||||
ConnectionId = 0x43554c54,
|
||||
InitialSequence = 100,
|
||||
TransportId = "schema-rudp",
|
||||
ResendDelayMs = 25,
|
||||
MaxFragmentBytes = 1024
|
||||
});
|
||||
var serverDone = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
var serverThread = new Thread(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
while (!serverDone.Task.IsCompleted)
|
||||
{
|
||||
var request = server.ReceiveSchemaMessageOnce<CultMeshVerseCatalogRequestMessage>();
|
||||
server.PollResends();
|
||||
if (request == null)
|
||||
{
|
||||
Thread.Sleep(5);
|
||||
continue;
|
||||
}
|
||||
|
||||
server.SendSchemaMessage(new CultMeshVerseCatalogResponseMessage
|
||||
{
|
||||
MessageId = request.MessageId,
|
||||
Verses =
|
||||
[
|
||||
new CultMeshVerseDescriptor(
|
||||
"rudp-verse",
|
||||
"RUDP Verse",
|
||||
CultMeshVerseAuthorityModel.OperatorCluster,
|
||||
new CultMeshVerseCompatibility("cultmesh.v0", "rules"),
|
||||
discoveryEndpoints: ["rudp://127.0.0.1"]).ToMessage()
|
||||
]
|
||||
});
|
||||
serverDone.TrySetResult();
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (Exception error)
|
||||
{
|
||||
serverDone.TrySetException(error);
|
||||
}
|
||||
})
|
||||
{
|
||||
IsBackground = true
|
||||
};
|
||||
serverThread.Start();
|
||||
|
||||
var client = new CultMeshVerseDiscoveryClient(new CultMeshVerseDiscoveryClientOptions
|
||||
{
|
||||
ConnectTimeout = TimeSpan.FromSeconds(2),
|
||||
ResponseTimeout = TimeSpan.FromSeconds(2)
|
||||
});
|
||||
var response = await client.FetchAsync($"rudp://127.0.0.1:{((IPEndPoint)serverSocket.LocalEndPoint!).Port}");
|
||||
await AwaitWithTimeout(serverDone.Task, TimeSpan.FromSeconds(2));
|
||||
|
||||
Assert.That(response.Verses.Single().VerseId, Is.EqualTo("rudp-verse"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task CultMeshPeerExchangeClient_Fetches_Over_RudpEndpoint()
|
||||
{
|
||||
using var serverSocket = BindUdpSocket();
|
||||
using var server = new CultNetRudpSocketTransportConnection(new CultNetRudpSocketTransportOptions
|
||||
{
|
||||
RuntimeId = "csharp-rudp-peer-exchange-server",
|
||||
Mode = CultNetRudpSocketMode.Server,
|
||||
Socket = serverSocket,
|
||||
ConnectionId = 0x43554c54,
|
||||
InitialSequence = 100,
|
||||
TransportId = "schema-rudp",
|
||||
ResendDelayMs = 25,
|
||||
MaxFragmentBytes = 1024
|
||||
});
|
||||
var serverDone = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
var serverThread = new Thread(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
while (!serverDone.Task.IsCompleted)
|
||||
{
|
||||
var request = server.ReceiveSchemaMessageOnce<CultMeshPeerExchangeRequestMessage>();
|
||||
server.PollResends();
|
||||
if (request == null)
|
||||
{
|
||||
Thread.Sleep(5);
|
||||
continue;
|
||||
}
|
||||
|
||||
server.SendSchemaMessage(new CultMeshPeerExchangeResponseMessage
|
||||
{
|
||||
MessageId = request.MessageId,
|
||||
Peers =
|
||||
[
|
||||
new CultMeshPeerCard(
|
||||
"rudp-peer",
|
||||
request.VerseId,
|
||||
["rudp://127.0.0.1"],
|
||||
roles: ["mesh-peer"]).ToMessage()
|
||||
]
|
||||
});
|
||||
serverDone.TrySetResult();
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (Exception error)
|
||||
{
|
||||
serverDone.TrySetException(error);
|
||||
}
|
||||
})
|
||||
{
|
||||
IsBackground = true
|
||||
};
|
||||
serverThread.Start();
|
||||
|
||||
var client = new CultMeshPeerExchangeClient(new CultMeshPeerExchangeClientOptions
|
||||
{
|
||||
ConnectTimeout = TimeSpan.FromSeconds(2),
|
||||
ResponseTimeout = TimeSpan.FromSeconds(2)
|
||||
});
|
||||
var response = await client.FetchAsync(
|
||||
$"rudp://127.0.0.1:{((IPEndPoint)serverSocket.LocalEndPoint!).Port}",
|
||||
new CultMeshPeerExchangeRequestMessage { VerseId = "local" });
|
||||
await AwaitWithTimeout(serverDone.Task, TimeSpan.FromSeconds(2));
|
||||
|
||||
Assert.That(response.Peers.Single().PeerId, Is.EqualTo("rudp-peer"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CultMesh_CreateClient_Returns_CultNetClient()
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in a new issue