mirror of
https://github.com/FabInfra/capnproto-dotnetcore_Runtime.git
synced 2025-03-12 23:01:44 +01:00
Re-integrated branch into master
This commit is contained in:
commit
b952ae47e2
2
.gitignore
vendored
2
.gitignore
vendored
@ -84,6 +84,8 @@ StyleCopReport.xml
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
*.dll
|
||||
*.exe
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
|
113
Capnp.Net.Runtime.Core21/Capnp.Net.Runtime.Core21.csproj
Normal file
113
Capnp.Net.Runtime.Core21/Capnp.Net.Runtime.Core21.csproj
Normal file
@ -0,0 +1,113 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<PackageId>Capnp.Net.Runtime</PackageId>
|
||||
<Authors>Christian Köllner and contributors</Authors>
|
||||
<Company />
|
||||
<Product>capnproto-dotnetcore</Product>
|
||||
<Description>A Cap'n Proto implementation for .NET Core, runtime assembly for .NET Core 2.1</Description>
|
||||
<Copyright>Christian Köllner and contributors</Copyright>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
<PackageLicenseFile></PackageLicenseFile>
|
||||
<PackageProjectUrl>https://github.com/c80k/capnproto-dotnetcore</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/c80k/capnproto-dotnetcore</RepositoryUrl>
|
||||
<AssemblyName>Capnp.Net.Runtime</AssemblyName>
|
||||
<RootNamespace>Capnp</RootNamespace>
|
||||
<RepositoryType>Git</RepositoryType>
|
||||
<PackageTags>capnp "Cap'n Proto" RPC serialization cerealization</PackageTags>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\Capnp.Net.Runtime\AnyPointer.cs" Link="AnyPointer.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\CapnpSerializable.cs" Link="CapnpSerializable.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\DeserializationException.cs" Link="DeserializationException.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\DeserializerState.cs" Link="DeserializerState.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\DynamicSerializerState.cs" Link="DynamicSerializerState.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\EmptyList.cs" Link="EmptyList.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\EmptyListDeserializer.cs" Link="EmptyListDeserializer.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\FramePump.cs" Link="FramePump.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\Framing.cs" Link="Framing.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\ICapnpSerializable.cs" Link="ICapnpSerializable.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\ISegmentAllocator.cs" Link="ISegmentAllocator.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\IStructDeserializer.cs" Link="IStructDeserializer.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\IStructSerializer.cs" Link="IStructSerializer.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\ListDeserializer.cs" Link="ListDeserializer.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\ListKind.cs" Link="ListKind.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\ListOfBitsDeserializer.cs" Link="ListOfBitsDeserializer.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\ListOfBitsSerializer.cs" Link="ListOfBitsSerializer.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\ListOfCapsDeserializer.cs" Link="ListOfCapsDeserializer.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\ListOfCapsSerializer.cs" Link="ListOfCapsSerializer.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\ListOfEmptyDeserializer.cs" Link="ListOfEmptyDeserializer.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\ListOfEmptySerializer.cs" Link="ListOfEmptySerializer.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\ListOfPointersDeserializer.cs" Link="ListOfPointersDeserializer.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\ListOfPointersSerializer.cs" Link="ListOfPointersSerializer.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\ListOfPrimitivesDeserializer.cs" Link="ListOfPrimitivesDeserializer.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\ListOfPrimitivesSerializer.cs" Link="ListOfPrimitivesSerializer.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\ListOfStructsDeserializer.cs" Link="ListOfStructsDeserializer.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\ListOfStructsSerializer.cs" Link="ListOfStructsSerializer.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\ListOfTextSerializer.cs" Link="ListOfTextSerializer.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\Logging.cs" Link="Logging.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\MessageBuilder.cs" Link="MessageBuilder.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\ObjectKind.cs" Link="ObjectKind.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\PrimitiveCoder.cs" Link="PrimitiveCoder.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\ReadOnlyListExtensions.cs" Link="ReadOnlyListExtensions.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\Reserializing.cs" Link="Reserializing.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\Rpc\AnswerOrCounterquestion.cs" Link="Rpc\AnswerOrCounterquestion.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\Rpc\BareProxy.cs" Link="Rpc\BareProxy.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\Rpc\CapabilityReflection.cs" Link="Rpc\CapabilityReflection.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\Rpc\ConsumedCapability.cs" Link="Rpc\ConsumedCapability.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\Rpc\IEndpoint.cs" Link="Rpc\IEndpoint.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\Rpc\IMonoSkeleton.cs" Link="Rpc\IMonoSkeleton.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\Rpc\Impatient.cs" Link="Rpc\Impatient.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\Rpc\ImportedCapability.cs" Link="Rpc\ImportedCapability.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\Rpc\InvalidCapabilityInterfaceException.cs" Link="Rpc\InvalidCapabilityInterfaceException.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\Rpc\IPromisedAnswer.cs" Link="Rpc\IPromisedAnswer.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\Rpc\IProvidedCapability.cs" Link="Rpc\IProvidedCapability.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\Rpc\IResolvingCapability.cs" Link="Rpc\IResolvingCapability.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\Rpc\IRpcEndpoint.cs" Link="Rpc\IRpcEndpoint.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\Rpc\LazyCapability.cs" Link="Rpc\LazyCapability.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\Rpc\LocalAnswer.cs" Link="Rpc\LocalAnswer.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\Rpc\LocalAnswerCapability.cs" Link="Rpc\LocalAnswerCapability.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\Rpc\LocalCapability.cs" Link="Rpc\LocalCapability.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\Rpc\MemberAccessPath.cs" Link="Rpc\MemberAccessPath.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\Rpc\PendingAnswer.cs" Link="Rpc\PendingAnswer.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\Rpc\PendingQuestion.cs" Link="Rpc\PendingQuestion.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\Rpc\PolySkeleton.cs" Link="Rpc\PolySkeleton.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\Rpc\PromisedCapability.cs" Link="Rpc\PromisedCapability.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\Rpc\Proxy.cs" Link="Rpc\Proxy.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\Rpc\ProxyAttribute.cs" Link="Rpc\ProxyAttribute.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\Rpc\RefCountingCapability.cs" Link="Rpc\RefCountingCapability.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\Rpc\RemoteAnswerCapability.cs" Link="Rpc\RemoteAnswerCapability.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\Rpc\RemoteCapability.cs" Link="Rpc\RemoteCapability.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\Rpc\RemoteResolvingCapability.cs" Link="Rpc\RemoteResolvingCapability.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\Rpc\ResolvingCapabilityExtensions.cs" Link="Rpc\ResolvingCapabilityExtensions.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\Rpc\rpc.cs" Link="Rpc\rpc.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\Rpc\RpcEngine.cs" Link="Rpc\RpcEngine.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\Rpc\RpcException.cs" Link="Rpc\RpcException.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\Rpc\RpcUnimplementedException.cs" Link="Rpc\RpcUnimplementedException.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\Rpc\Skeleton.cs" Link="Rpc\Skeleton.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\Rpc\SkeletonAttribute.cs" Link="Rpc\SkeletonAttribute.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\Rpc\TcpRpcClient.cs" Link="Rpc\TcpRpcClient.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\Rpc\TcpRpcServer.cs" Link="Rpc\TcpRpcServer.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\Rpc\Vine.cs" Link="Rpc\Vine.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\SecurityOptions.cs" Link="SecurityOptions.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\SegmentAllocator.cs" Link="SegmentAllocator.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\SegmentSlice.cs" Link="SegmentSlice.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\SerializerExtensions.cs" Link="SerializerExtensions.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\SerializerState.cs" Link="SerializerState.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\UtilityExtensions.cs" Link="UtilityExtensions.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\WireFrame.cs" Link="WireFrame.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime\WirePointer.cs" Link="WirePointer.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Rpc\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
@ -0,0 +1,44 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\Capnp.Net.Runtime.Tests\CallContext.cs" Link="CallContext.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime.Tests\DeserializationTests.cs" Link="DeserializationTests.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime.Tests\DynamicSerializerStateTests.cs" Link="DynamicSerializerStateTests.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime.Tests\FramePumpTests.cs" Link="FramePumpTests.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime.Tests\General.cs" Link="General.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime.Tests\JobUtil.cs" Link="JobUtil.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime.Tests\MessageBuilderTests.cs" Link="MessageBuilderTests.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime.Tests\ProvidedCapabilityMock.cs" Link="ProvidedCapabilityMock.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime.Tests\ProvidedCapabilityMultiCallMock.cs" Link="ProvidedCapabilityMultiCallMock.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime.Tests\RpcSchemaTests.cs" Link="RpcSchemaTests.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime.Tests\SegmentAllocatorTests.cs" Link="SegmentAllocatorTests.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime.Tests\TcpRpc.cs" Link="TcpRpc.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime.Tests\TcpRpcAdvancedStuff.cs" Link="TcpRpcAdvancedStuff.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime.Tests\TcpRpcInterop.cs" Link="TcpRpcInterop.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime.Tests\TcpRpcPorted.cs" Link="TcpRpcPorted.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime.Tests\TcpRpcStress.cs" Link="TcpRpcStress.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime.Tests\test.cs" Link="test.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime.Tests\TestBase.cs" Link="TestBase.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime.Tests\TestCapImplementations.cs" Link="TestCapImplementations.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime.Tests\TestInterfaces.cs" Link="TestInterfaces.cs" />
|
||||
<Compile Include="..\Capnp.Net.Runtime.Tests\WirePointerTests.cs" Link="WirePointerTests.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.0.1" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="1.4.0" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="1.4.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Capnp.Net.Runtime\Capnp.Net.Runtime.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
@ -1,11 +1,13 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
|
||||
<LangVersion>7.1</LangVersion>
|
||||
|
||||
<OutputType>Library</OutputType>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
@ -111,7 +111,9 @@ namespace Capnp.Net.Runtime.Tests
|
||||
Assert.AreEqual(expectedCount - i, length);
|
||||
for (int j = 0; j < length; j++)
|
||||
{
|
||||
Assert.AreEqual((ulong)(length - j), frame.Segments[i].Span[j]);
|
||||
var expected = (ulong) (length - j);
|
||||
var actual = frame.Segments[i].Span[j];
|
||||
Assert.AreEqual(expected, actual);
|
||||
}
|
||||
}
|
||||
|
||||
@ -165,7 +167,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
txPump.Send(PackFrame(4));
|
||||
txPump.Send(PackFrame(5));
|
||||
|
||||
Assert.IsTrue(SpinWait.SpinUntil(() => bc.Count == 8, 500));
|
||||
Assert.IsTrue(SpinWait.SpinUntil(() => bc.Count == 8, 50000));
|
||||
|
||||
UnpackAndVerifyFrame(bc.Take(), 1);
|
||||
UnpackAndVerifyFrame(bc.Take(), 8);
|
||||
|
@ -1,8 +1,8 @@
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading.Tasks.Dataflow;
|
||||
using Capnp.Rpc;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System.Threading.Tasks.Dataflow;
|
||||
|
||||
namespace Capnp.Net.Runtime.Tests
|
||||
{
|
||||
|
@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
@ -29,6 +30,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
{
|
||||
ExpectingLogOutput = true;
|
||||
|
||||
Logging.LoggerFactory?.Dispose();
|
||||
Logging.LoggerFactory = new LoggerFactory().AddConsole((msg, level) =>
|
||||
{
|
||||
if (!ExpectingLogOutput && level != LogLevel.Debug)
|
||||
@ -41,7 +43,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
|
||||
int MediumTimeout => Debugger.IsAttached ? Timeout.Infinite : 2000;
|
||||
|
||||
[TestMethod]
|
||||
[TestMethod, Timeout(10000)]
|
||||
public void CreateAndDispose()
|
||||
{
|
||||
(var server, var client) = SetupClientServerPair();
|
||||
@ -52,7 +54,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestMethod, Timeout(10000)]
|
||||
public void ConnectAndDispose()
|
||||
{
|
||||
(var server, var client) = SetupClientServerPair();
|
||||
@ -60,13 +62,21 @@ namespace Capnp.Net.Runtime.Tests
|
||||
using (server)
|
||||
using (client)
|
||||
{
|
||||
Assert.IsTrue(client.WhenConnected.Wait(MediumTimeout));
|
||||
try
|
||||
{
|
||||
client.WhenConnected.Wait();
|
||||
SpinWait.SpinUntil(() => server.ConnectionCount > 0, MediumTimeout);
|
||||
Assert.AreEqual(1, server.ConnectionCount);
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestMethod, Timeout(10000)]
|
||||
public void ConnectNoServer()
|
||||
{
|
||||
using (var client = new TcpRpcClient("localhost", TcpPort))
|
||||
@ -75,7 +85,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestMethod, Timeout(10000)]
|
||||
public void ConnectAndBootstrap()
|
||||
{
|
||||
(var server, var client) = SetupClientServerPair();
|
||||
@ -83,7 +93,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
using (server)
|
||||
using (client)
|
||||
{
|
||||
Assert.IsTrue(client.WhenConnected.Wait(MediumTimeout));
|
||||
client.WhenConnected.Wait();
|
||||
SpinWait.SpinUntil(() => server.ConnectionCount > 0, MediumTimeout);
|
||||
Assert.AreEqual(1, server.ConnectionCount);
|
||||
|
||||
@ -94,7 +104,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestMethod, Timeout(10000)]
|
||||
public void ConnectNoBootstrap()
|
||||
{
|
||||
(var server, var client) = SetupClientServerPair();
|
||||
@ -102,7 +112,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
using (server)
|
||||
using (client)
|
||||
{
|
||||
Assert.IsTrue(client.WhenConnected.Wait(MediumTimeout));
|
||||
client.WhenConnected.Wait();
|
||||
SpinWait.SpinUntil(() => server.ConnectionCount > 0, MediumTimeout);
|
||||
Assert.AreEqual(1, server.ConnectionCount);
|
||||
|
||||
@ -112,7 +122,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestMethod, Timeout(10000)]
|
||||
public void CallReturn()
|
||||
{
|
||||
(var server, var client) = SetupClientServerPair();
|
||||
@ -120,7 +130,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
using (server)
|
||||
using (client)
|
||||
{
|
||||
Assert.IsTrue(client.WhenConnected.Wait(MediumTimeout));
|
||||
client.WhenConnected.Wait();
|
||||
SpinWait.SpinUntil(() => server.ConnectionCount > 0, MediumTimeout);
|
||||
Assert.AreEqual(1, server.ConnectionCount);
|
||||
|
||||
@ -153,7 +163,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestMethod, Timeout(10000)]
|
||||
public void CallCancelOnServer()
|
||||
{
|
||||
(var server, var client) = SetupClientServerPair();
|
||||
@ -161,7 +171,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
using (server)
|
||||
using (client)
|
||||
{
|
||||
Assert.IsTrue(client.WhenConnected.Wait(MediumTimeout));
|
||||
client.WhenConnected.Wait();
|
||||
SpinWait.SpinUntil(() => server.ConnectionCount > 0, MediumTimeout);
|
||||
Assert.AreEqual(1, server.ConnectionCount);
|
||||
|
||||
@ -188,7 +198,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestMethod, Timeout(10000)]
|
||||
public void CallCancelOnClient()
|
||||
{
|
||||
ExpectingLogOutput = false;
|
||||
@ -200,7 +210,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
{
|
||||
try
|
||||
{
|
||||
Assert.IsTrue(client.WhenConnected.Wait(MediumTimeout));
|
||||
client.WhenConnected.Wait();
|
||||
SpinWait.SpinUntil(() => server.ConnectionCount > 0, MediumTimeout);
|
||||
Assert.AreEqual(1, server.ConnectionCount);
|
||||
|
||||
@ -233,7 +243,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestMethod, Timeout(10000)]
|
||||
public void CallReturnAfterClientSideCancel()
|
||||
{
|
||||
ExpectingLogOutput = false;
|
||||
@ -244,7 +254,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
{
|
||||
try
|
||||
{
|
||||
Assert.IsTrue(client.WhenConnected.Wait(MediumTimeout));
|
||||
client.WhenConnected.Wait();
|
||||
SpinWait.SpinUntil(() => server.ConnectionCount > 0, MediumTimeout);
|
||||
Assert.AreEqual(1, server.ConnectionCount);
|
||||
|
||||
@ -295,7 +305,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestMethod, Timeout(10000)]
|
||||
public void CallServerSideException()
|
||||
{
|
||||
(var server, var client) = SetupClientServerPair();
|
||||
@ -303,7 +313,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
using (server)
|
||||
using (client)
|
||||
{
|
||||
Assert.IsTrue(client.WhenConnected.Wait(MediumTimeout));
|
||||
client.WhenConnected.Wait();
|
||||
SpinWait.SpinUntil(() => server.ConnectionCount > 0, MediumTimeout);
|
||||
Assert.AreEqual(1, server.ConnectionCount);
|
||||
|
||||
@ -332,7 +342,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestMethod, Timeout(10000)]
|
||||
public void PipelineBeforeReturn()
|
||||
{
|
||||
(var server, var client) = SetupClientServerPair();
|
||||
@ -340,7 +350,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
using (server)
|
||||
using (client)
|
||||
{
|
||||
Assert.IsTrue(client.WhenConnected.Wait(MediumTimeout));
|
||||
client.WhenConnected.Wait();
|
||||
SpinWait.SpinUntil(() => server.ConnectionCount > 0, MediumTimeout);
|
||||
Assert.AreEqual(1, server.ConnectionCount);
|
||||
|
||||
@ -405,7 +415,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestMethod, Timeout(10000)]
|
||||
public void PipelineAfterReturn()
|
||||
{
|
||||
(var server, var client) = SetupClientServerPair();
|
||||
@ -413,7 +423,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
using (server)
|
||||
using (client)
|
||||
{
|
||||
Assert.IsTrue(client.WhenConnected.Wait(MediumTimeout));
|
||||
client.WhenConnected.Wait();
|
||||
SpinWait.SpinUntil(() => server.ConnectionCount > 0, MediumTimeout);
|
||||
Assert.AreEqual(1, server.ConnectionCount);
|
||||
|
||||
@ -481,7 +491,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestMethod, Timeout(10000)]
|
||||
public void PipelineMultiple()
|
||||
{
|
||||
(var server, var client) = SetupClientServerPair();
|
||||
@ -489,7 +499,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
using (server)
|
||||
using (client)
|
||||
{
|
||||
Assert.IsTrue(client.WhenConnected.Wait(MediumTimeout));
|
||||
client.WhenConnected.Wait();
|
||||
SpinWait.SpinUntil(() => server.ConnectionCount > 0, MediumTimeout);
|
||||
Assert.AreEqual(1, server.ConnectionCount);
|
||||
|
||||
@ -598,7 +608,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestMethod, Timeout(10000)]
|
||||
public void PipelineCallAfterDisposal()
|
||||
{
|
||||
(var server, var client) = SetupClientServerPair();
|
||||
@ -606,7 +616,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
using (server)
|
||||
using (client)
|
||||
{
|
||||
Assert.IsTrue(client.WhenConnected.Wait(MediumTimeout));
|
||||
client.WhenConnected.Wait();
|
||||
SpinWait.SpinUntil(() => server.ConnectionCount > 0, MediumTimeout);
|
||||
Assert.AreEqual(1, server.ConnectionCount);
|
||||
|
||||
@ -631,11 +641,21 @@ namespace Capnp.Net.Runtime.Tests
|
||||
args2.SetStruct(1, 0);
|
||||
args2.WriteData(0, 654321);
|
||||
|
||||
Assert.ThrowsException<System.ObjectDisposedException>(() => pipelined.Call(0x8765432187654321, 0x4444, args2, false));
|
||||
try
|
||||
{
|
||||
pipelined.Call(0x8765432187654321, 0x4444, args2, false);
|
||||
Assert.Fail("Expected an exception here");
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
}
|
||||
catch (TaskCanceledException)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestMethod, Timeout(10000)]
|
||||
public void PipelineCallDuringDisposal()
|
||||
{
|
||||
(var server, var client) = SetupClientServerPair();
|
||||
@ -643,7 +663,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
using (server)
|
||||
using (client)
|
||||
{
|
||||
Assert.IsTrue(client.WhenConnected.Wait(MediumTimeout));
|
||||
client.WhenConnected.Wait();
|
||||
SpinWait.SpinUntil(() => server.ConnectionCount > 0, MediumTimeout);
|
||||
Assert.AreEqual(1, server.ConnectionCount);
|
||||
|
||||
|
@ -12,7 +12,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
[TestClass]
|
||||
public class TcpRpcAdvancedStuff : TestBase
|
||||
{
|
||||
[TestMethod]
|
||||
[TestMethod, Timeout(10000)]
|
||||
public void MultiConnect()
|
||||
{
|
||||
using (var server = SetupServer())
|
||||
@ -25,7 +25,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
{
|
||||
using (var client = SetupClient())
|
||||
{
|
||||
Assert.IsTrue(client.WhenConnected.Wait(MediumNonDbgTimeout));
|
||||
client.WhenConnected.Wait();
|
||||
|
||||
using (var main = client.GetMain<ITestInterface>())
|
||||
{
|
||||
@ -50,7 +50,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestMethod, Timeout(10000)]
|
||||
public void TwoClients()
|
||||
{
|
||||
using (var server = SetupServer())
|
||||
@ -88,5 +88,37 @@ namespace Capnp.Net.Runtime.Tests
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod, Timeout(10000)]
|
||||
public void ClosingServerWhileRequestingBootstrap()
|
||||
{
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
var server = SetupServer();
|
||||
var counters = new Counters();
|
||||
var tcs = new TaskCompletionSource<int>();
|
||||
server.Main = new TestInterfaceImpl(counters, tcs);
|
||||
|
||||
using (var client = SetupClient())
|
||||
{
|
||||
client.WhenConnected.Wait();
|
||||
|
||||
using (var main = client.GetMain<ITestInterface>())
|
||||
{
|
||||
server.Dispose();
|
||||
|
||||
// Resolution must either succeed or be cancelled. A hanging resolution would be inacceptable.
|
||||
|
||||
try
|
||||
{
|
||||
Assert.IsTrue(((IResolvingCapability)main).WhenResolved.Wait(MediumNonDbgTimeout));
|
||||
}
|
||||
catch (AggregateException)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -95,14 +95,14 @@ namespace Capnp.Net.Runtime.Tests
|
||||
Assert.AreEqual(expected, line.Result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestMethod, Timeout(10000)]
|
||||
public void BasicClient()
|
||||
{
|
||||
LaunchCompatTestProcess("server:Interface", stdout =>
|
||||
{
|
||||
using (var client = new TcpRpcClient("localhost", TcpPort))
|
||||
{
|
||||
Assert.IsTrue(client.WhenConnected.Wait(MediumNonDbgTimeout));
|
||||
client.WhenConnected.Wait();
|
||||
|
||||
using (var main = client.GetMain<ITestInterface>())
|
||||
{
|
||||
@ -126,7 +126,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
});
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestMethod, Timeout(10000)]
|
||||
public void BasicServer()
|
||||
{
|
||||
using (var server = SetupServer())
|
||||
@ -143,7 +143,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestMethod, Timeout(10000)]
|
||||
public void PipelineClient()
|
||||
{
|
||||
LaunchCompatTestProcess("server:Pipeline", stdout =>
|
||||
@ -152,7 +152,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
|
||||
using (var client = new TcpRpcClient("localhost", TcpPort))
|
||||
{
|
||||
Assert.IsTrue(client.WhenConnected.Wait(MediumNonDbgTimeout));
|
||||
client.WhenConnected.Wait();
|
||||
|
||||
using (var main = client.GetMain<ITestPipeline>())
|
||||
{
|
||||
@ -180,7 +180,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
});
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestMethod, Timeout(10000)]
|
||||
public void PipelineServer()
|
||||
{
|
||||
using (var server = SetupServer())
|
||||
@ -198,14 +198,14 @@ namespace Capnp.Net.Runtime.Tests
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestMethod, Timeout(10000)]
|
||||
public void ReleaseClient()
|
||||
{
|
||||
LaunchCompatTestProcess("server:MoreStuff", stdout =>
|
||||
{
|
||||
using (var client = new TcpRpcClient("localhost", TcpPort))
|
||||
{
|
||||
Assert.IsTrue(client.WhenConnected.Wait(MediumNonDbgTimeout));
|
||||
client.WhenConnected.Wait();
|
||||
|
||||
using (var main = client.GetMain<ITestMoreStuff>())
|
||||
{
|
||||
@ -231,7 +231,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
});
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestMethod, Timeout(10000)]
|
||||
public void ReleaseServer()
|
||||
{
|
||||
using (var server = SetupServer())
|
||||
@ -259,7 +259,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestMethod, Timeout(10000)]
|
||||
public void ReleaseOnCancelClient()
|
||||
{
|
||||
// Since we have a threaded model, there is no way to deterministically provoke the situation
|
||||
@ -271,7 +271,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
{
|
||||
using (var client = new TcpRpcClient("localhost", TcpPort))
|
||||
{
|
||||
Assert.IsTrue(client.WhenConnected.Wait(MediumNonDbgTimeout));
|
||||
client.WhenConnected.Wait();
|
||||
|
||||
using (var main = client.GetMain<ITestMoreStuff>())
|
||||
{
|
||||
@ -337,7 +337,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
});
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestMethod, Timeout(10000)]
|
||||
public void ReleaseOnCancelServer()
|
||||
{
|
||||
using (var server = SetupServer())
|
||||
@ -354,14 +354,14 @@ namespace Capnp.Net.Runtime.Tests
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestMethod, Timeout(10000)]
|
||||
public void TestTailCallClient()
|
||||
{
|
||||
LaunchCompatTestProcess("server:TailCaller", stdout =>
|
||||
{
|
||||
using (var client = new TcpRpcClient("localhost", TcpPort))
|
||||
{
|
||||
Assert.IsTrue(client.WhenConnected.Wait(MediumNonDbgTimeout));
|
||||
client.WhenConnected.Wait();
|
||||
|
||||
using (var main = client.GetMain<ITestTailCaller>())
|
||||
{
|
||||
@ -389,7 +389,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
});
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestMethod, Timeout(10000), Ignore]
|
||||
public void TestTailCallServer()
|
||||
{
|
||||
using (var server = SetupServer())
|
||||
@ -408,7 +408,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestMethod, Timeout(10000)]
|
||||
public void CancelationServer()
|
||||
{
|
||||
LaunchCompatTestProcess("server:MoreStuff", stdout =>
|
||||
@ -417,7 +417,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
|
||||
using (var client = new TcpRpcClient("localhost", TcpPort))
|
||||
{
|
||||
Assert.IsTrue(client.WhenConnected.Wait(MediumNonDbgTimeout));
|
||||
client.WhenConnected.Wait();
|
||||
|
||||
using (var main = client.GetMain<ITestMoreStuff>())
|
||||
{
|
||||
@ -432,13 +432,13 @@ namespace Capnp.Net.Runtime.Tests
|
||||
cts.Cancel();
|
||||
|
||||
Assert.IsTrue(destroyed.Task.Wait(MediumNonDbgTimeout));
|
||||
Assert.IsFalse(cancelTask.IsCompletedSuccessfully);
|
||||
Assert.IsFalse(cancelTask.IsCompleted && !cancelTask.IsCanceled);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestMethod, Timeout(10000)]
|
||||
public void CancelationClient()
|
||||
{
|
||||
using (var server = SetupServer())
|
||||
@ -455,14 +455,14 @@ namespace Capnp.Net.Runtime.Tests
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestMethod, Timeout(10000)]
|
||||
public void PromiseResolveServer()
|
||||
{
|
||||
LaunchCompatTestProcess("server:MoreStuff", stdout =>
|
||||
{
|
||||
using (var client = new TcpRpcClient("localhost", TcpPort))
|
||||
{
|
||||
Assert.IsTrue(client.WhenConnected.Wait(MediumNonDbgTimeout));
|
||||
client.WhenConnected.Wait();
|
||||
|
||||
using (var main = client.GetMain<ITestMoreStuff>())
|
||||
{
|
||||
@ -497,7 +497,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
});
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestMethod, Timeout(10000)]
|
||||
public void PromiseResolveClient()
|
||||
{
|
||||
using (var server = SetupServer())
|
||||
@ -516,7 +516,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestMethod, Timeout(10000)]
|
||||
public void RetainAndReleaseServer()
|
||||
{
|
||||
var destructionPromise = new TaskCompletionSource<int>();
|
||||
@ -528,7 +528,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
|
||||
using (var client = new TcpRpcClient("localhost", TcpPort))
|
||||
{
|
||||
Assert.IsTrue(client.WhenConnected.Wait(MediumNonDbgTimeout));
|
||||
client.WhenConnected.Wait();
|
||||
|
||||
using (var main = client.GetMain<ITestMoreStuff>())
|
||||
{
|
||||
@ -594,7 +594,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
});
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestMethod, Timeout(10000)]
|
||||
public void RetainAndReleaseClient()
|
||||
{
|
||||
using (var server = SetupServer())
|
||||
@ -614,14 +614,14 @@ namespace Capnp.Net.Runtime.Tests
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestMethod, Timeout(10000)]
|
||||
public void CancelServer()
|
||||
{
|
||||
LaunchCompatTestProcess("server:MoreStuff", stdout =>
|
||||
{
|
||||
using (var client = new TcpRpcClient("localhost", TcpPort))
|
||||
{
|
||||
Assert.IsTrue(client.WhenConnected.Wait(MediumNonDbgTimeout));
|
||||
client.WhenConnected.Wait();
|
||||
|
||||
var destructionPromise = new TaskCompletionSource<int>();
|
||||
var destructionTask = destructionPromise.Task;
|
||||
@ -655,7 +655,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
});
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestMethod, Timeout(10000)]
|
||||
public void CancelClient()
|
||||
{
|
||||
using (var server = SetupServer())
|
||||
@ -672,14 +672,14 @@ namespace Capnp.Net.Runtime.Tests
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestMethod, Timeout(10000)]
|
||||
public void SendTwiceServer()
|
||||
{
|
||||
LaunchCompatTestProcess("server:MoreStuff", stdout =>
|
||||
{
|
||||
using (var client = new TcpRpcClient("localhost", TcpPort))
|
||||
{
|
||||
Assert.IsTrue(client.WhenConnected.Wait(MediumNonDbgTimeout));
|
||||
client.WhenConnected.Wait();
|
||||
|
||||
using (var main = client.GetMain<ITestMoreStuff>())
|
||||
{
|
||||
@ -716,7 +716,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
});
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestMethod, Timeout(10000)]
|
||||
public void SendTwiceClient()
|
||||
{
|
||||
using (var server = SetupServer())
|
||||
@ -736,7 +736,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestMethod, Timeout(10000)]
|
||||
public void EmbargoServer()
|
||||
{
|
||||
LaunchCompatTestProcess("server:MoreStuff", stdout =>
|
||||
@ -751,7 +751,19 @@ namespace Capnp.Net.Runtime.Tests
|
||||
using (var main = client.GetMain<ITestMoreStuff>())
|
||||
{
|
||||
var resolving = main as IResolvingCapability;
|
||||
if (!resolving.WhenResolved.Wait(MediumNonDbgTimeout))
|
||||
|
||||
bool success;
|
||||
|
||||
try
|
||||
{
|
||||
success = resolving.WhenResolved.Wait(MediumNonDbgTimeout);
|
||||
}
|
||||
catch
|
||||
{
|
||||
success = false;
|
||||
}
|
||||
|
||||
if (!success)
|
||||
{
|
||||
if (++retry == 5)
|
||||
{
|
||||
@ -803,7 +815,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
});
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestMethod, Timeout(10000)]
|
||||
public void EmbargoClient()
|
||||
{
|
||||
using (var server = SetupServer())
|
||||
@ -824,7 +836,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
using (var client = new TcpRpcClient("localhost", TcpPort))
|
||||
{
|
||||
|
||||
Assert.IsTrue(client.WhenConnected.Wait(MediumNonDbgTimeout));
|
||||
client.WhenConnected.Wait();
|
||||
|
||||
using (var main = client.GetMain<ITestMoreStuff>())
|
||||
{
|
||||
@ -873,13 +885,13 @@ namespace Capnp.Net.Runtime.Tests
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestMethod, Timeout(10000)]
|
||||
public void EmbargoErrorServer()
|
||||
{
|
||||
LaunchCompatTestProcess("server:MoreStuff", EmbargoErrorImpl);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestMethod, Timeout(10000)]
|
||||
public void RepeatedEmbargoError()
|
||||
{
|
||||
LaunchCompatTestProcess("server:MoreStuff", stdout =>
|
||||
@ -891,7 +903,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
});
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestMethod, Timeout(10000)]
|
||||
public void EmbargoErrorClient()
|
||||
{
|
||||
using (var server = SetupServer())
|
||||
@ -907,7 +919,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestMethod, Timeout(10000)]
|
||||
public void EmbargoNullServer()
|
||||
{
|
||||
LaunchCompatTestProcess("server:MoreStuff", stdout =>
|
||||
@ -917,13 +929,24 @@ namespace Capnp.Net.Runtime.Tests
|
||||
label:
|
||||
using (var client = new TcpRpcClient("localhost", TcpPort))
|
||||
{
|
||||
|
||||
Assert.IsTrue(client.WhenConnected.Wait(MediumNonDbgTimeout));
|
||||
client.WhenConnected.Wait();
|
||||
|
||||
using (var main = client.GetMain<ITestMoreStuff>())
|
||||
{
|
||||
var resolving = main as IResolvingCapability;
|
||||
if (!resolving.WhenResolved.Wait(MediumNonDbgTimeout))
|
||||
|
||||
bool success;
|
||||
|
||||
try
|
||||
{
|
||||
success = resolving.WhenResolved.Wait(MediumNonDbgTimeout);
|
||||
}
|
||||
catch
|
||||
{
|
||||
success = false;
|
||||
}
|
||||
|
||||
if (!success)
|
||||
{
|
||||
if (++retry == 5)
|
||||
{
|
||||
@ -956,7 +979,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
});
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestMethod, Timeout(10000)]
|
||||
public void EmbargoNullClient()
|
||||
{
|
||||
using (var server = SetupServer())
|
||||
@ -972,14 +995,14 @@ namespace Capnp.Net.Runtime.Tests
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestMethod, Timeout(10000)]
|
||||
public void CallBrokenPromiseServer()
|
||||
{
|
||||
LaunchCompatTestProcess("server:MoreStuff", stdout =>
|
||||
{
|
||||
using (var client = new TcpRpcClient("localhost", TcpPort))
|
||||
{
|
||||
Assert.IsTrue(client.WhenConnected.Wait(MediumNonDbgTimeout));
|
||||
client.WhenConnected.Wait();
|
||||
|
||||
using (var main = client.GetMain<ITestMoreStuff>())
|
||||
{
|
||||
@ -1009,7 +1032,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
});
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestMethod, Timeout(10000)]
|
||||
public void CallBrokenPromiseClient()
|
||||
{
|
||||
using (var server = SetupServer())
|
||||
|
@ -22,7 +22,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
using (server)
|
||||
using (client)
|
||||
{
|
||||
Assert.IsTrue(client.WhenConnected.Wait(MediumNonDbgTimeout));
|
||||
client.WhenConnected.Wait();
|
||||
|
||||
var counters = new Counters();
|
||||
server.Main = new TestInterfaceImpl(counters);
|
||||
@ -52,7 +52,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
using (server)
|
||||
using (client)
|
||||
{
|
||||
Assert.IsTrue(client.WhenConnected.Wait(MediumNonDbgTimeout));
|
||||
client.WhenConnected.Wait();
|
||||
|
||||
var counters = new Counters();
|
||||
server.Main = new TestPipelineImpl(counters);
|
||||
@ -87,7 +87,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
using (server)
|
||||
using (client)
|
||||
{
|
||||
Assert.IsTrue(client.WhenConnected.Wait(MediumNonDbgTimeout));
|
||||
client.WhenConnected.Wait();
|
||||
|
||||
var counters = new Counters();
|
||||
server.Main = new TestMoreStuffImpl(counters);
|
||||
@ -120,7 +120,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
using (server)
|
||||
using (client)
|
||||
{
|
||||
Assert.IsTrue(client.WhenConnected.Wait(MediumNonDbgTimeout));
|
||||
client.WhenConnected.Wait();
|
||||
|
||||
var counters = new Counters();
|
||||
server.Main = new TestMoreStuffImpl(counters);
|
||||
@ -159,7 +159,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
using (server)
|
||||
using (client)
|
||||
{
|
||||
Assert.IsTrue(client.WhenConnected.Wait(MediumNonDbgTimeout));
|
||||
client.WhenConnected.Wait();
|
||||
|
||||
var counters = new Counters();
|
||||
server.Main = new TestTailCallerImpl(counters);
|
||||
@ -196,7 +196,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
using (server)
|
||||
using (client)
|
||||
{
|
||||
Assert.IsTrue(client.WhenConnected.Wait(MediumNonDbgTimeout));
|
||||
client.WhenConnected.Wait();
|
||||
|
||||
var counters = new Counters();
|
||||
server.Main = new TestMoreStuffImpl(counters);
|
||||
@ -212,7 +212,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
cts.Cancel();
|
||||
|
||||
Assert.IsTrue(destroyed.Task.Wait(MediumNonDbgTimeout));
|
||||
Assert.IsFalse(cancelTask.IsCompletedSuccessfully);
|
||||
Assert.IsFalse(cancelTask.IsCompleted && !cancelTask.IsCanceled);
|
||||
}
|
||||
|
||||
}
|
||||
@ -226,7 +226,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
using (server)
|
||||
using (client)
|
||||
{
|
||||
Assert.IsTrue(client.WhenConnected.Wait(MediumNonDbgTimeout));
|
||||
client.WhenConnected.Wait();
|
||||
|
||||
var counters = new Counters();
|
||||
var impl = new TestMoreStuffImpl(counters);
|
||||
@ -268,7 +268,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
using (server)
|
||||
using (client)
|
||||
{
|
||||
Assert.IsTrue(client.WhenConnected.Wait(MediumNonDbgTimeout));
|
||||
client.WhenConnected.Wait();
|
||||
|
||||
var destructionPromise = new TaskCompletionSource<int>();
|
||||
var destructionTask = destructionPromise.Task;
|
||||
@ -345,7 +345,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
using (server)
|
||||
using (client)
|
||||
{
|
||||
Assert.IsTrue(client.WhenConnected.Wait(MediumNonDbgTimeout));
|
||||
client.WhenConnected.Wait();
|
||||
|
||||
var destructionPromise = new TaskCompletionSource<int>();
|
||||
var destructionTask = destructionPromise.Task;
|
||||
@ -388,7 +388,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
using (server)
|
||||
using (client)
|
||||
{
|
||||
Assert.IsTrue(client.WhenConnected.Wait(MediumNonDbgTimeout));
|
||||
client.WhenConnected.Wait();
|
||||
|
||||
var destructionPromise = new TaskCompletionSource<int>();
|
||||
var destructionTask = destructionPromise.Task;
|
||||
@ -435,7 +435,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
using (server)
|
||||
using (client)
|
||||
{
|
||||
Assert.IsTrue(client.WhenConnected.Wait(MediumNonDbgTimeout));
|
||||
client.WhenConnected.Wait();
|
||||
|
||||
var counters = new Counters();
|
||||
var impl = new TestMoreStuffImpl(counters);
|
||||
@ -496,7 +496,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
using (server)
|
||||
using (client)
|
||||
{
|
||||
Assert.IsTrue(client.WhenConnected.Wait(MediumNonDbgTimeout));
|
||||
client.WhenConnected.Wait();
|
||||
|
||||
var counters = new Counters();
|
||||
var impl = new TestMoreStuffImpl(counters);
|
||||
@ -553,7 +553,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
using (server)
|
||||
using (client)
|
||||
{
|
||||
Assert.IsTrue(client.WhenConnected.Wait(MediumNonDbgTimeout));
|
||||
client.WhenConnected.Wait();
|
||||
|
||||
var counters = new Counters();
|
||||
var impl = new TestMoreStuffImpl(counters);
|
||||
@ -590,7 +590,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
using (server)
|
||||
using (client)
|
||||
{
|
||||
Assert.IsTrue(client.WhenConnected.Wait(MediumNonDbgTimeout));
|
||||
client.WhenConnected.Wait();
|
||||
|
||||
var counters = new Counters();
|
||||
var impl = new TestMoreStuffImpl(counters);
|
||||
|
@ -13,8 +13,6 @@ namespace Capnp.Net.Runtime.Tests
|
||||
[TestClass]
|
||||
public class TcpRpcStress: TestBase
|
||||
{
|
||||
ILogger Logger { get; set; }
|
||||
|
||||
void Repeat(int count, Action action)
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
@ -24,15 +22,6 @@ namespace Capnp.Net.Runtime.Tests
|
||||
}
|
||||
}
|
||||
|
||||
[TestInitialize]
|
||||
public void InitConsoleLogging()
|
||||
{
|
||||
Logging.LoggerFactory = new LoggerFactory().AddConsole((msg, level) => true);
|
||||
Logger = Logging.CreateLogger<TcpRpcStress>();
|
||||
if (Thread.CurrentThread.Name == null)
|
||||
Thread.CurrentThread.Name = $"Test Thread {Thread.CurrentThread.ManagedThreadId}";
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ResolveMain()
|
||||
{
|
||||
@ -43,7 +32,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
using (server)
|
||||
using (client)
|
||||
{
|
||||
Assert.IsTrue(client.WhenConnected.Wait(MediumNonDbgTimeout));
|
||||
client.WhenConnected.Wait();
|
||||
|
||||
var counters = new Counters();
|
||||
var impl = new TestMoreStuffImpl(counters);
|
||||
|
@ -33,6 +33,7 @@ namespace Capnp.Net.Runtime.Tests
|
||||
[TestInitialize]
|
||||
public void InitConsoleLogging()
|
||||
{
|
||||
Logging.LoggerFactory?.Dispose();
|
||||
Logging.LoggerFactory = new LoggerFactory().AddConsole((msg, level) => true);
|
||||
Logger = Logging.CreateLogger<TcpRpcStress>();
|
||||
if (Thread.CurrentThread.Name == null)
|
||||
|
3608
Capnp.Net.Runtime/Capnp.Net.Runtime.Std20.xml
Normal file
3608
Capnp.Net.Runtime/Capnp.Net.Runtime.Std20.xml
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,15 +1,33 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
<TargetFrameworks>netstandard2.0;netcoreapp2.1</TargetFrameworks>
|
||||
<RootNamespace>Capnp</RootNamespace>
|
||||
<LangVersion>7.2</LangVersion>
|
||||
<AssemblyName>Capnp.Net.Runtime</AssemblyName>
|
||||
<PackageId>Capnp.Net.Runtime</PackageId>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<Authors>Christian Köllner and contributors</Authors>
|
||||
<Description>A Cap'n Proto implementation for .NET Standard & Core</Description>
|
||||
<Product>capnproto-dotnetcore</Product>
|
||||
<Copyright>Christian Köllner and contributors</Copyright>
|
||||
<PackageLicenseFile></PackageLicenseFile>
|
||||
<PackageProjectUrl>https://github.com/c80k/capnproto-dotnetcore</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/c80k/capnproto-dotnetcore</RepositoryUrl>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
<RepositoryType>Git</RepositoryType>
|
||||
<PackageTags>capnp "Cap'n Proto" RPC serialization cerealization</PackageTags>
|
||||
<Version>1.0.0</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Release'">
|
||||
<DocumentationFile>F:\Repos\capnproto-dotnetcore\Capnp.Net.Runtime\Capnp.Net.Runtime.Std20.xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.2.0" />
|
||||
</ItemGroup>
|
||||
|
@ -7,10 +7,16 @@ namespace Capnp
|
||||
/// </summary>
|
||||
public class DeserializationException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructs an instance
|
||||
/// </summary>
|
||||
public DeserializationException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs an instance with message and inner exception
|
||||
/// </summary>
|
||||
public DeserializationException(string message, Exception innerException):
|
||||
base(message, innerException)
|
||||
{
|
||||
|
@ -637,6 +637,9 @@ namespace Capnp
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Capability interface</typeparam>
|
||||
/// <param name="index">index within this struct's pointer table</param>
|
||||
/// <param name="memberName">debugging aid</param>
|
||||
/// <param name="sourceFilePath">debugging aid</param>
|
||||
/// <param name="sourceLineNumber">debugging aid</param>
|
||||
/// <returns>capability instance or null if pointer was null</returns>
|
||||
/// <exception cref="IndexOutOfRangeException">negative index</exception>
|
||||
/// <exception cref="DeserializationException">state does not represent a struct, invalid pointer,
|
||||
|
@ -61,8 +61,8 @@ namespace Capnp
|
||||
/// <exception cref="ArgumentNullException"><paramref name="target"/> is null</exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException"><paramref name="slot"/> out of range</exception>
|
||||
/// <exception cref="InvalidOperationException"><list type="bullet">
|
||||
/// <item><description>This state does neither describe a struct, nor a list of pointers</description></item></list>
|
||||
/// <item><description>Another state is already linked to the specified position (sorry, no overwrite allowed)</description></item></list>
|
||||
/// <item><description>This state does neither describe a struct, nor a list of pointers</description></item>
|
||||
/// <item><description>Another state is already linked to the specified position (sorry, no overwrite allowed)</description></item>
|
||||
/// <item><description>This state and <paramref name="target"/> belong to different message builder, and<paramref name="allowCopy"/> is false</description></item></list>
|
||||
/// </exception>
|
||||
public new void Link(int slot, SerializerState target, bool allowCopy = true) => base.Link(slot, target, allowCopy);
|
||||
@ -74,7 +74,7 @@ namespace Capnp
|
||||
/// If this state describes a list of pointers: List element index.</param>
|
||||
/// <param name="capabilityIndex">capability index inside the capability table</param>
|
||||
/// <exception cref="InvalidOperationException"><list type="bullet">
|
||||
/// <item><description>This state does neither describe a struct, nor a list of pointers</description></item></list>
|
||||
/// <item><description>This state does neither describe a struct, nor a list of pointers</description></item>
|
||||
/// <item><description>Another state is already linked to the specified position (sorry, no overwrite allowed)</description></item></list>
|
||||
/// </exception>
|
||||
public new void LinkToCapability(int slot, uint capabilityIndex) => base.LinkToCapability(slot, capabilityIndex);
|
||||
@ -123,24 +123,25 @@ namespace Capnp
|
||||
/// <item><description>An instance implementing <see cref="ICapnpSerializable"/></description></item>
|
||||
/// <item><description>null</description></item>
|
||||
/// <item><description>A <see cref="String"/></description></item>
|
||||
/// <item><description>A <see cref="IReadOnlyList{Byte}"/></description></item>
|
||||
/// <item><description>A <see cref="IReadOnlyList{SByte}"/></description></item>
|
||||
/// <item><description>A <see cref="IReadOnlyList{UInt16}"/></description></item>
|
||||
/// <item><description>A <see cref="IReadOnlyList{Int16}"/></description></item>
|
||||
/// <item><description>A <see cref="IReadOnlyList{UInt32}"/></description></item>
|
||||
/// <item><description>A <see cref="IReadOnlyList{Int64}"/></description></item>
|
||||
/// <item><description>A <see cref="IReadOnlyList{UInt64}"/></description></item>
|
||||
/// <item><description>A <see cref="IReadOnlyList{Single}"/></description></item>
|
||||
/// <item><description>A <see cref="IReadOnlyList{Double}"/></description></item>
|
||||
/// <item><description>A <see cref="IReadOnlyList{Boolean}/></description></item>
|
||||
/// <item><description>A <see cref="IReadOnlyList{String}"/></description></item>
|
||||
/// <item><description>A <code><![CDATA[IReadOnlyList<byte>]]></code></description></item>
|
||||
/// <item><description>A <code><![CDATA[IReadOnlyList<sbyte>]]></code></description></item>
|
||||
/// <item><description>A <code><![CDATA[IReadOnlyList<ushort>]]></code></description></item>
|
||||
/// <item><description>A <code><![CDATA[IReadOnlyList<short>]]></code></description></item>
|
||||
/// <item><description>A <code><![CDATA[IReadOnlyList<int>]]></code></description></item>
|
||||
/// <item><description>A <code><![CDATA[IReadOnlyList<uint>]]></code></description></item>
|
||||
/// <item><description>A <code><![CDATA[IReadOnlyList<long>]]></code></description></item>
|
||||
/// <item><description>A <code><![CDATA[IReadOnlyList<ulong>]]></code></description></item>
|
||||
/// <item><description>A <code><![CDATA[IReadOnlyList<float>]]></code></description></item>
|
||||
/// <item><description>A <code><![CDATA[IReadOnlyList<double>]]></code></description></item>
|
||||
/// <item><description>A <code><![CDATA[IReadOnlyList<bool>]]></code></description></item>
|
||||
/// <item><description>A <code><![CDATA[IReadOnlyList<string>]]></code></description></item>
|
||||
/// <item><description>Another <see cref="DeserializerState"/></description></item>
|
||||
/// <item><description>Another <see cref="SerializerState"/></description></item>
|
||||
/// <item><description>Low-level capability object (<see cref="Rpc.ConsumedCapability"/>)</description></item>
|
||||
/// <item><description>Proxy object (<see cref="Rpc.Proxy"/>)</description></item>
|
||||
/// <item><description>Skeleton object (<see cref="Rpc.Skeleton"/>)</description></item>
|
||||
/// <item><description>Capability interface implementation</description></item>
|
||||
/// <item><description>A <see cref="IReadOnlyList{Object}"/> whereby each list item is one of the things listed here.</description></item>
|
||||
/// <item><description>A <code><![CDATA[IReadOnlyList<object>]]></code> whereby each list item is one of the things listed here.</description></item>
|
||||
/// </list>
|
||||
/// </param>
|
||||
public void SetObject(object obj)
|
||||
|
@ -21,47 +21,47 @@ namespace Capnp
|
||||
public override IReadOnlyList<T> Cast<T>(Func<DeserializerState, T> cons) => new EmptyList<T>();
|
||||
|
||||
/// <summary>
|
||||
/// Returns an empty <see cref="IReadOnlyList{Boolean}"/>.
|
||||
/// Returns an empty <code><![CDATA[IReadOnlyList<bool>]]></code>/>.
|
||||
/// </summary>
|
||||
public override IReadOnlyList<bool> CastBool() => new EmptyList<bool>();
|
||||
|
||||
/// <summary>
|
||||
/// Returns an empty <see cref="IReadOnlyList{Byte}"/>.
|
||||
/// Returns an empty <code><![CDATA[IReadOnlyList<byte>]]></code>/>.
|
||||
/// </summary>
|
||||
public override IReadOnlyList<byte> CastByte() => new EmptyList<byte>();
|
||||
|
||||
/// <summary>
|
||||
/// Returns an empty <see cref="IReadOnlyList{Double}"/>.
|
||||
/// Returns an empty <code><![CDATA[IReadOnlyList<double>]]></code>/>.
|
||||
/// </summary>
|
||||
public override IReadOnlyList<double> CastDouble() => new EmptyList<double>();
|
||||
|
||||
/// <summary>
|
||||
/// Returns an empty <see cref="IReadOnlyList{Single}"./>
|
||||
/// Returns an empty <code><![CDATA[IReadOnlyList<float>]]></code>.
|
||||
/// </summary>
|
||||
public override IReadOnlyList<float> CastFloat() => new EmptyList<float>();
|
||||
|
||||
/// <summary>
|
||||
/// Returns an empty <see cref="IReadOnlyList{Int32}"/>.
|
||||
/// Returns an empty <code><![CDATA[IReadOnlyList<int>]]></code>.
|
||||
/// </summary>
|
||||
public override IReadOnlyList<int> CastInt() => new EmptyList<int>();
|
||||
|
||||
/// <summary>
|
||||
/// Returns an empty <see cref="IReadOnlyList{ListDeserializer}"/>.
|
||||
/// Returns an empty <code><![CDATA[IReadOnlyList<ListDeserializer>]]></code>.
|
||||
/// </summary>
|
||||
public override IReadOnlyList<ListDeserializer> CastList() => new EmptyList<ListDeserializer>();
|
||||
|
||||
/// <summary>
|
||||
/// Returns an empty <see cref="IReadOnlyList{Int64}"/>.
|
||||
/// Returns an empty <code><![CDATA[IReadOnlyList<long>]]></code>/>.
|
||||
/// </summary>
|
||||
public override IReadOnlyList<long> CastLong() => new EmptyList<long>();
|
||||
|
||||
/// <summary>
|
||||
/// Returns an empty <see cref="IReadOnlyList{SByte}"/>.
|
||||
/// Returns an empty <code><![CDATA[IReadOnlyList<sbyte>]]></code>.
|
||||
/// </summary>
|
||||
public override IReadOnlyList<sbyte> CastSByte() => new EmptyList<sbyte>();
|
||||
|
||||
/// <summary>
|
||||
/// Returns an empty <see cref="IReadOnlyList{Int16}"/>.
|
||||
/// Returns an empty <code><![CDATA[IReadOnlyList<short>]]></code>.
|
||||
/// </summary>
|
||||
public override IReadOnlyList<short> CastShort() => new EmptyList<short>();
|
||||
|
||||
@ -71,17 +71,17 @@ namespace Capnp
|
||||
public override string CastText() => string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Returns an empty <see cref="IReadOnlyList{UInt32}"/>.
|
||||
/// Returns an empty <code><![CDATA[IReadOnlyList<uint>]]></code>.
|
||||
/// </summary>
|
||||
public override IReadOnlyList<uint> CastUInt() => new EmptyList<uint>();
|
||||
|
||||
/// <summary>
|
||||
/// Returns an empty <see cref="IReadOnlyList{UInt64}"/>.
|
||||
/// Returns an empty <code><![CDATA[IReadOnlyList<ulong>]]></code>.
|
||||
/// </summary>
|
||||
public override IReadOnlyList<ulong> CastULong() => new EmptyList<ulong>();
|
||||
|
||||
/// <summary>
|
||||
/// Returns an empty <see cref="IReadOnlyList{UInt16}"/>.
|
||||
/// Returns an empty <code><![CDATA[IReadOnlyList<ushort>]]></code>.
|
||||
/// </summary>
|
||||
public override IReadOnlyList<ushort> CastUShort() => new EmptyList<ushort>();
|
||||
}
|
||||
|
@ -99,8 +99,11 @@ namespace Capnp
|
||||
|
||||
foreach (var segment in frame.Segments)
|
||||
{
|
||||
#if NETSTANDARD2_0
|
||||
var bytes = MemoryMarshal.Cast<ulong, byte>(segment.Span).ToArray();
|
||||
#else
|
||||
var bytes = MemoryMarshal.Cast<ulong, byte>(segment.Span);
|
||||
|
||||
#endif
|
||||
_writer.Write(bytes);
|
||||
}
|
||||
}
|
||||
@ -123,7 +126,7 @@ namespace Capnp
|
||||
/// to be part of normal operation. It does pass exceptions which arise due to I/O errors or invalid data.
|
||||
/// </summary>
|
||||
/// <exception cref="ArgumentException">The underlying stream does not support reading or is already closed.</exception>
|
||||
/// <exception cref="OverflowException">Received invalid data.</exception>
|
||||
/// <exception cref="InvalidDataException">Encountered Invalid Framing Data</exception>
|
||||
/// <exception cref="OutOfMemoryException">Received a message with too many or too big segments, probably dues to invalid data.</exception>
|
||||
/// <exception cref="IOException">An I/O error occurs.</exception>
|
||||
public void Run()
|
||||
@ -135,55 +138,19 @@ namespace Capnp
|
||||
while (true)
|
||||
{
|
||||
IsWaitingForData = true;
|
||||
|
||||
uint scountm = reader.ReadUInt32();
|
||||
int scount = checked((int)(scountm + 1));
|
||||
var buffers = new Memory<ulong>[scount];
|
||||
|
||||
for (uint i = 0; i < scount; i++)
|
||||
{
|
||||
int size = checked((int)reader.ReadUInt32());
|
||||
|
||||
// This implementation will never send empty segments.
|
||||
// Other implementations should not. An empty segment may also
|
||||
// indicate and end-of-stream (stream closed) condition.
|
||||
if (size == 0)
|
||||
{
|
||||
Logger.LogInformation("Received zero-sized segment, stopping interaction");
|
||||
return;
|
||||
}
|
||||
|
||||
buffers[i] = new Memory<ulong>(new ulong[size]);
|
||||
}
|
||||
|
||||
if ((scount & 1) == 0)
|
||||
{
|
||||
// Padding
|
||||
reader.ReadUInt32();
|
||||
}
|
||||
|
||||
for (uint i = 0; i < scount; i++)
|
||||
{
|
||||
var buffer = MemoryMarshal.Cast<ulong, byte>(buffers[i].Span);
|
||||
|
||||
int got = reader.Read(buffer);
|
||||
|
||||
if (got != buffer.Length)
|
||||
{
|
||||
Logger.LogWarning("Received incomplete frame");
|
||||
|
||||
throw new EndOfStreamException("Expected more bytes according to framing header");
|
||||
}
|
||||
}
|
||||
|
||||
var frame = reader.ReadWireFrame();
|
||||
IsWaitingForData = false;
|
||||
|
||||
FrameReceived?.Invoke(new WireFrame(new ArraySegment<Memory<ulong>>(buffers, 0, scount)));
|
||||
FrameReceived?.Invoke(frame);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (EndOfStreamException)
|
||||
{
|
||||
Logger.LogWarning("Encountered End of Stream");
|
||||
}
|
||||
catch (InvalidDataException e)
|
||||
{
|
||||
Logger.LogWarning(e.Message);
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
|
@ -21,19 +21,51 @@ namespace Capnp
|
||||
/// <exception cref="EndOfStreamException">The end of the stream is reached.</exception>
|
||||
/// <exception cref="ObjectDisposedException">The stream is closed.</exception>
|
||||
/// <exception cref="IOException">An I/O error occurs.</exception>
|
||||
/// <exception cref="OverflowException">Encountered invalid framing data.</exception>
|
||||
/// <exception cref="InvalidDataException">Encountered invalid framing data, too many or too large segments</exception>
|
||||
/// <exception cref="OutOfMemoryException">Too many or too large segments, probably due to invalid framing data.</exception>
|
||||
public static WireFrame ReadSegments(Stream stream)
|
||||
{
|
||||
using (var reader = new BinaryReader(stream, Encoding.Default, true))
|
||||
{
|
||||
uint scountm = reader.ReadUInt32();
|
||||
uint scount = checked(scountm + 1);
|
||||
return reader.ReadWireFrame();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deserializes the next Cap'n Proto message from given stream.
|
||||
/// </summary>
|
||||
/// <param name="reader">The stream to read from</param>
|
||||
/// <returns>The message</returns>
|
||||
public static WireFrame ReadWireFrame(this BinaryReader reader)
|
||||
{
|
||||
uint scount = reader.ReadUInt32();
|
||||
if (scount++ == uint.MaxValue)
|
||||
{
|
||||
throw new InvalidDataException("Encountered invalid framing data");
|
||||
}
|
||||
|
||||
// Cannot have more segments than the traversal limit
|
||||
if (scount >= SecurityOptions.TraversalLimit)
|
||||
{
|
||||
throw new InvalidDataException("Too many segments. Probably invalid data. Try increasing the traversal limit.");
|
||||
}
|
||||
|
||||
var buffers = new Memory<ulong>[scount];
|
||||
|
||||
for (uint i = 0; i < scount; i++)
|
||||
{
|
||||
uint size = reader.ReadUInt32();
|
||||
|
||||
if (size == 0)
|
||||
{
|
||||
throw new EndOfStreamException("Stream closed");
|
||||
}
|
||||
|
||||
if (size >= SecurityOptions.TraversalLimit)
|
||||
{
|
||||
throw new InvalidDataException("Too large segment. Probably invalid data. Try increasing the traversal limit.");
|
||||
}
|
||||
|
||||
buffers[i] = new Memory<ulong>(new ulong[size]);
|
||||
}
|
||||
|
||||
@ -43,18 +75,35 @@ namespace Capnp
|
||||
reader.ReadUInt32();
|
||||
}
|
||||
|
||||
for (uint i = 0; i < scount; i++)
|
||||
{
|
||||
var buffer = MemoryMarshal.Cast<ulong, byte>(buffers[i].Span);
|
||||
|
||||
if (reader.Read(buffer) != buffer.Length)
|
||||
{
|
||||
throw new EndOfStreamException("Expected more bytes according to framing header");
|
||||
}
|
||||
}
|
||||
FillBuffersFromFrames(buffers, scount, reader);
|
||||
|
||||
return new WireFrame(buffers);
|
||||
}
|
||||
|
||||
static void FillBuffersFromFrames(Memory<ulong>[] buffers, uint segmentCount, BinaryReader reader)
|
||||
{
|
||||
for (uint i = 0; i < segmentCount; i++)
|
||||
{
|
||||
#if NETSTANDARD2_0
|
||||
var buffer = MemoryMarshal.Cast<ulong, byte>(buffers[i].Span.ToArray());
|
||||
var tmpBuffer = reader.ReadBytes(buffer.Length);
|
||||
|
||||
if (tmpBuffer.Length != buffer.Length)
|
||||
{
|
||||
throw new InvalidDataException("Expected more bytes according to framing header");
|
||||
}
|
||||
|
||||
// Fastest way to do this without /unsafe
|
||||
for (int j = 0; j < buffers[i].Length; j++)
|
||||
{
|
||||
var value = BitConverter.ToUInt64(tmpBuffer, j*8);
|
||||
buffers[i].Span[j] = value;
|
||||
}
|
||||
#else
|
||||
var buffer = MemoryMarshal.Cast<ulong, byte>(buffers[i].Span);
|
||||
reader.Read(buffer);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -360,12 +360,12 @@ namespace Capnp
|
||||
return Cast(sd => sd.ReadDataUInt(0));
|
||||
}
|
||||
|
||||
public virtual IReadOnlyList<long> CastLong()
|
||||
/// <summary>
|
||||
/// Represents this list as List(Int64).
|
||||
/// </summary>
|
||||
/// <returns>The desired representation</returns>
|
||||
/// <exception cref="NotSupportedException">If this list cannot be represented in the desired manner.</exception>
|
||||
public virtual IReadOnlyList<long> CastLong()
|
||||
{
|
||||
return Cast(sd => sd.ReadDataLong(0));
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ namespace Capnp
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implements <see cref="IEnumerable{bool}"/>
|
||||
/// Implements <see cref="IEnumerable{T}"/>
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public IEnumerator<bool> GetEnumerator()
|
||||
|
@ -56,7 +56,7 @@ namespace Capnp
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implements <see cref="IEnumerable{T}"./>
|
||||
/// Implements <see cref="IEnumerable{T}"/>.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
|
@ -95,7 +95,7 @@ namespace Capnp
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implements <see cref="IEnumerable{T}"./>
|
||||
/// Implements <see cref="IEnumerable{T}"/>.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
|
@ -208,7 +208,7 @@ namespace Capnp
|
||||
var utf8Bytes = PrimitiveCast<byte>().Data;
|
||||
if (utf8Bytes.Length == 0) return string.Empty;
|
||||
var utf8GytesNoZterm = utf8Bytes.Slice(0, utf8Bytes.Length - 1);
|
||||
return Encoding.UTF8.GetString(utf8GytesNoZterm);
|
||||
return Encoding.UTF8.GetString(utf8GytesNoZterm.ToArray());
|
||||
}
|
||||
|
||||
IEnumerable<T> Enumerate()
|
||||
|
@ -66,7 +66,7 @@ namespace Capnp
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implements <see cref="IEnumerable{DeserializerState}"./>
|
||||
/// Implements <see cref="IEnumerable{DeserializerState}"/>.
|
||||
/// </summary>
|
||||
public IEnumerator<DeserializerState> GetEnumerator()
|
||||
{
|
||||
|
@ -24,10 +24,10 @@ namespace Capnp
|
||||
Coder<ulong>.Fn = (x, y) => x ^ y;
|
||||
Coder<float>.Fn = (x, y) =>
|
||||
{
|
||||
int xi = BitConverter.SingleToInt32Bits(x);
|
||||
int yi = BitConverter.SingleToInt32Bits(y);
|
||||
int xi = x.ReplacementSingleToInt32Bits();
|
||||
int yi = y.ReplacementSingleToInt32Bits();
|
||||
int zi = xi ^ yi;
|
||||
return BitConverter.Int32BitsToSingle(zi);
|
||||
return BitConverter.ToSingle(BitConverter.GetBytes(zi), 0);
|
||||
};
|
||||
Coder<double>.Fn = (x, y) =>
|
||||
{
|
||||
|
@ -38,7 +38,7 @@ namespace Capnp
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// LINQ-like "Select" operator for <see cref="IReadOnlyList{T}", with the addition that the resulting elements are accessible by index.
|
||||
/// LINQ-like "Select" operator for <see cref="IReadOnlyList{T}"/>, with the addition that the resulting elements are accessible by index.
|
||||
/// The operator implements lazy semantics, which means that the selector function results are not cached./>
|
||||
/// </summary>
|
||||
/// <typeparam name="From">Source element type</typeparam>
|
||||
|
@ -12,17 +12,32 @@
|
||||
_obj = obj;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wraps a SerializerState
|
||||
/// </summary>
|
||||
/// <param name="answer">object to wrap</param>
|
||||
public static implicit operator AnswerOrCounterquestion (SerializerState answer)
|
||||
{
|
||||
return new AnswerOrCounterquestion(answer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wraps a PendingQuestion
|
||||
/// </summary>
|
||||
/// <param name="counterquestion">object to wrap</param>
|
||||
public static implicit operator AnswerOrCounterquestion (PendingQuestion counterquestion)
|
||||
{
|
||||
return new AnswerOrCounterquestion(counterquestion);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// SerializerState, if applicable
|
||||
/// </summary>
|
||||
public SerializerState Answer => _obj as SerializerState;
|
||||
|
||||
/// <summary>
|
||||
/// PendingQuestion, if applicable
|
||||
/// </summary>
|
||||
public PendingQuestion Counterquestion => _obj as PendingQuestion;
|
||||
}
|
||||
}
|
||||
|
@ -10,13 +10,13 @@
|
||||
/// </summary>
|
||||
/// <param name="impl">Capability implementation</param>
|
||||
/// <returns>Proxy</returns>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="impl"/> is null.</exception>
|
||||
/// <exception cref="System.ArgumentNullException"><paramref name="impl"/> is null.</exception>
|
||||
/// <exception cref="InvalidCapabilityInterfaceException">No <see cref="SkeletonAttribute"/> found on implemented interface(s).</exception>
|
||||
/// <exception cref="InvalidOperationException">Mismatch between generic type arguments (if capability interface is generic).</exception>
|
||||
/// <exception cref="ArgumentException">Mismatch between generic type arguments (if capability interface is generic).</exception>
|
||||
/// <exception cref="System.InvalidOperationException">Mismatch between generic type arguments (if capability interface is generic).</exception>
|
||||
/// <exception cref="System.ArgumentException">Mismatch between generic type arguments (if capability interface is generic).</exception>
|
||||
/// <exception cref="System.Reflection.TargetInvocationException">Problem with instatiating the Skeleton (constructor threw exception).</exception>
|
||||
/// <exception cref="MemberAccessException">Caller does not have permission to invoke the Skeleton constructor.</exception>
|
||||
/// <exception cref="TypeLoadException">Problem with building the Skeleton type, or problem with loading some dependent class.</exception>
|
||||
/// <exception cref="System.MemberAccessException">Caller does not have permission to invoke the Skeleton constructor.</exception>
|
||||
/// <exception cref="System.TypeLoadException">Problem with building the Skeleton type, or problem with loading some dependent class.</exception>
|
||||
public static BareProxy FromImpl(object impl)
|
||||
{
|
||||
return new BareProxy(LocalCapability.Create(CapabilityReflection.CreateSkeleton(impl)));
|
||||
|
@ -252,6 +252,9 @@ namespace Capnp.Rpc
|
||||
/// </summary>
|
||||
/// <typeparam name="TInterface">Capability interface. Must be annotated with <see cref="ProxyAttribute"/>.</typeparam>
|
||||
/// <param name="cap">low-level capability</param>
|
||||
/// <param name="memberName">debugging aid</param>
|
||||
/// <param name="sourceFilePath">debugging aid</param>
|
||||
/// <param name="sourceLineNumber">debugging aid</param>
|
||||
/// <returns>The Proxy instance which implements <typeparamref name="TInterface"/>.</returns>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="cap"/> is null.</exception>
|
||||
/// <exception cref="InvalidCapabilityInterfaceException"><typeparamref name="TInterface"/> did not qualify as capability interface.</exception>
|
||||
|
@ -81,6 +81,9 @@ namespace Capnp.Rpc
|
||||
/// </summary>
|
||||
/// <typeparam name="TInterface">Capability interface type</typeparam>
|
||||
/// <param name="task">The task</param>
|
||||
/// <param name="memberName">debugging aid</param>
|
||||
/// <param name="sourceFilePath">debugging aid</param>
|
||||
/// <param name="sourceLineNumber">debugging aid</param>
|
||||
/// <returns>A proxy for the given task.</returns>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="task"/> is null.</exception>
|
||||
/// <exception cref="InvalidCapabilityInterfaceException"><typeparamref name="TInterface"/> did not
|
||||
@ -101,6 +104,13 @@ namespace Capnp.Rpc
|
||||
set { _askingEndpoint.Value = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether a given task belongs to a pending RPC and requests a tail call if applicable.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Task result type</typeparam>
|
||||
/// <param name="task">Task to request</param>
|
||||
/// <param name="func">Converts the task's result to a SerializerState</param>
|
||||
/// <returns>Tail-call aware task</returns>
|
||||
public static async Task<AnswerOrCounterquestion> MaybeTailCall<T>(Task<T> task, Func<T, SerializerState> func)
|
||||
{
|
||||
if (TryGetAnswer(task) is PendingQuestion pendingQuestion &&
|
||||
@ -115,31 +125,49 @@ namespace Capnp.Rpc
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overload for tuple-typed tasks
|
||||
/// </summary>
|
||||
public static Task<AnswerOrCounterquestion> MaybeTailCall<T1, T2>(Task<(T1, T2)> task, Func<T1, T2, SerializerState> func)
|
||||
{
|
||||
return MaybeTailCall(task, (ValueTuple<T1, T2> t) => func(t.Item1, t.Item2));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overload for tuple-typed tasks
|
||||
/// </summary>
|
||||
public static Task<AnswerOrCounterquestion> MaybeTailCall<T1, T2, T3>(Task<(T1, T2, T3)> task, Func<T1, T2, T3, SerializerState> func)
|
||||
{
|
||||
return MaybeTailCall(task, (ValueTuple<T1, T2, T3> t) => func(t.Item1, t.Item2, t.Item3));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overload for tuple-typed tasks
|
||||
/// </summary>
|
||||
public static Task<AnswerOrCounterquestion> MaybeTailCall<T1, T2, T3, T4>(Task<(T1, T2, T3, T4)> task, Func<T1, T2, T3, T4, SerializerState> func)
|
||||
{
|
||||
return MaybeTailCall(task, (ValueTuple<T1, T2, T3, T4> t) => func(t.Item1, t.Item2, t.Item3, t.Item4));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overload for tuple-typed tasks
|
||||
/// </summary>
|
||||
public static Task<AnswerOrCounterquestion> MaybeTailCall<T1, T2, T3, T4, T5>(Task<(T1, T2, T3, T4, T5)> task, Func<T1, T2, T3, T4, T5, SerializerState> func)
|
||||
{
|
||||
return MaybeTailCall(task, (ValueTuple<T1, T2, T3, T4, T5> t) => func(t.Item1, t.Item2, t.Item3, t.Item4, t.Item5));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overload for tuple-typed tasks
|
||||
/// </summary>
|
||||
public static Task<AnswerOrCounterquestion> MaybeTailCall<T1, T2, T3, T4, T5, T6>(Task<(T1, T2, T3, T4, T5, T6)> task, Func<T1, T2, T3, T4, T5, T6, SerializerState> func)
|
||||
{
|
||||
return MaybeTailCall(task, (ValueTuple<T1, T2, T3, T4, T5, T6> t) => func(t.Item1, t.Item2, t.Item3, t.Item4, t.Item5, t.Item6));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overload for tuple-typed tasks
|
||||
/// </summary>
|
||||
public static Task<AnswerOrCounterquestion> MaybeTailCall<T1, T2, T3, T4, T5, T6, T7>(Task<(T1, T2, T3, T4, T5, T6, T7)> task, Func<T1, T2, T3, T4, T5, T6, T7, SerializerState> func)
|
||||
{
|
||||
return MaybeTailCall(task, (ValueTuple<T1, T2, T3, T4, T5, T6, T7> t) => func(t.Item1, t.Item2, t.Item3, t.Item4, t.Item5, t.Item6, t.Item7));
|
||||
|
@ -7,10 +7,16 @@
|
||||
/// </summary>
|
||||
public class InvalidCapabilityInterfaceException : System.Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructs an instance.
|
||||
/// </summary>
|
||||
public InvalidCapabilityInterfaceException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs an instance with message an inner exception.
|
||||
/// </summary>
|
||||
public InvalidCapabilityInterfaceException(string message, System.Exception innerException) : base(message, innerException)
|
||||
{
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ namespace Capnp.Rpc
|
||||
|
||||
internal override void Export(IRpcEndpoint endpoint, CapDescriptor.WRITER writer)
|
||||
{
|
||||
if (WhenResolved.IsCompletedSuccessfully)
|
||||
if (WhenResolved.ReplacementTaskIsCompletedSuccessfully())
|
||||
{
|
||||
WhenResolved.Result.Export(endpoint, writer);
|
||||
}
|
||||
|
@ -9,8 +9,16 @@ namespace Capnp.Rpc
|
||||
/// </summary>
|
||||
public class MemberAccessPath
|
||||
{
|
||||
/// <summary>
|
||||
/// Path to the bootstrap capability (which is an empty path)
|
||||
/// </summary>
|
||||
public static readonly MemberAccessPath BootstrapAccess = new MemberAccessPath(new List<MemberAccess>());
|
||||
|
||||
/// <summary>
|
||||
/// Deserializes a MemberAccessPath from Cap'n Proto representation.
|
||||
/// </summary>
|
||||
/// <param name="promisedAnswer">Cap'n Proto representation</param>
|
||||
/// <returns>The MemberAccessPath</returns>
|
||||
public static MemberAccessPath Deserialize(PromisedAnswer.READER promisedAnswer)
|
||||
{
|
||||
var ops = new MemberAccess[promisedAnswer.Transform.Count];
|
||||
@ -55,6 +63,11 @@ namespace Capnp.Rpc
|
||||
/// </remarks>
|
||||
public abstract class MemberAccess
|
||||
{
|
||||
/// <summary>
|
||||
/// Deserializes a MemberAccess instance from Cap'n Proto representation.
|
||||
/// </summary>
|
||||
/// <param name="op">Cap'n Proto representation</param>
|
||||
/// <returns>Deserialized instance</returns>
|
||||
public static MemberAccess Deserialize(PromisedAnswer.Op.READER op)
|
||||
{
|
||||
switch (op.which)
|
||||
|
@ -15,15 +15,47 @@ namespace Capnp.Rpc
|
||||
/// </remarks>
|
||||
public sealed class PendingQuestion: IPromisedAnswer
|
||||
{
|
||||
/// <summary>
|
||||
/// Question lifetime management state
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum State
|
||||
{
|
||||
/// <summary>
|
||||
/// The question has not yet been sent.
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Tail call flag
|
||||
/// </summary>
|
||||
TailCall = 1,
|
||||
|
||||
/// <summary>
|
||||
/// The question has been sent.
|
||||
/// </summary>
|
||||
Sent = 2,
|
||||
|
||||
/// <summary>
|
||||
/// The question has been answered.
|
||||
/// </summary>
|
||||
Returned = 4,
|
||||
|
||||
/// <summary>
|
||||
/// A 'finish' request was sent to the peer, indicating that no further requests will refer
|
||||
/// to this question.
|
||||
/// </summary>
|
||||
FinishRequested = 8,
|
||||
|
||||
/// <summary>
|
||||
/// Question object was disposed.
|
||||
/// </summary>
|
||||
Disposed = 16,
|
||||
|
||||
/// <summary>
|
||||
/// Question object was finalized by GC.
|
||||
/// This flag should only be observable when debugging the finalizer itself.
|
||||
/// </summary>
|
||||
Finalized = 32
|
||||
}
|
||||
|
||||
@ -59,7 +91,12 @@ namespace Capnp.Rpc
|
||||
internal object ReentrancyBlocker { get; } = new object();
|
||||
internal uint QuestionId => _questionId;
|
||||
internal State StateFlags { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Eventually returns the server answer
|
||||
/// </summary>
|
||||
public Task<DeserializerState> WhenReturned => _tcs.Task;
|
||||
|
||||
internal bool IsTailCall
|
||||
{
|
||||
get => StateFlags.HasFlag(State.TailCall);
|
||||
@ -189,6 +226,13 @@ namespace Capnp.Rpc
|
||||
DeleteMyQuestion();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Refer to a (possibly nested) member of this question's (possibly future) result and return
|
||||
/// it as a capability.
|
||||
/// </summary>
|
||||
/// <param name="access">Access path</param>
|
||||
/// <returns>Low-level capability</returns>
|
||||
/// <exception cref="DeserializationException">The referenced member does not exist or does not resolve to a capability pointer.</exception>
|
||||
public ConsumedCapability Access(MemberAccessPath access)
|
||||
{
|
||||
lock (ReentrancyBlocker)
|
||||
@ -296,11 +340,17 @@ namespace Capnp.Rpc
|
||||
ReleaseCaps(target, inParams);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finalizer
|
||||
/// </summary>
|
||||
~PendingQuestion()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implements <see cref="IDisposable"/>.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
|
@ -77,7 +77,8 @@ namespace Capnp.Rpc
|
||||
{
|
||||
lock (_reentrancyBlocker)
|
||||
{
|
||||
if (_resolvedCap.Task.IsCompletedSuccessfully)
|
||||
|
||||
if (_resolvedCap.Task.ReplacementTaskIsCompletedSuccessfully())
|
||||
{
|
||||
_resolvedCap.Task.Result.Export(endpoint, writer);
|
||||
}
|
||||
|
@ -35,6 +35,9 @@ namespace Capnp.Rpc
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Underlying low-level capability
|
||||
/// </summary>
|
||||
protected internal ConsumedCapability ConsumedCap { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
@ -68,7 +71,7 @@ namespace Capnp.Rpc
|
||||
/// <returns>An answer promise</returns>
|
||||
/// <exception cref="ObjectDisposedException">This instance was disposed, or transport-layer stream was disposed.</exception>
|
||||
/// <exception cref="InvalidOperationException">Capability is broken.</exception>
|
||||
/// <exception cref="IOException">An I/O error occurs.</exception>
|
||||
/// <exception cref="System.IO.IOException">An I/O error occurs.</exception>
|
||||
protected internal IPromisedAnswer Call(ulong interfaceId, ushort methodId, DynamicSerializerState args, bool tailCall, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (_disposedValue)
|
||||
@ -87,6 +90,9 @@ namespace Capnp.Rpc
|
||||
return answer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a null instance.
|
||||
/// </summary>
|
||||
public Proxy()
|
||||
{
|
||||
}
|
||||
@ -135,6 +141,9 @@ namespace Capnp.Rpc
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finalizer
|
||||
/// </summary>
|
||||
~Proxy()
|
||||
{
|
||||
#if DebugFinalizers
|
||||
|
@ -3,6 +3,7 @@ using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
@ -97,7 +98,14 @@ namespace Capnp.Rpc
|
||||
{
|
||||
_exportTable.Clear();
|
||||
_revExportTable.Clear();
|
||||
_questionTable.Clear();
|
||||
|
||||
foreach (var question in _questionTable.Values.ToList())
|
||||
{
|
||||
question.OnException(new RpcException("RPC connection is broken. Task would never return."));
|
||||
}
|
||||
|
||||
Debug.Assert(_questionTable.Count == 0);
|
||||
|
||||
_answerTable.Clear();
|
||||
_pendingDisembargos.Clear();
|
||||
}
|
||||
@ -179,13 +187,7 @@ namespace Capnp.Rpc
|
||||
|
||||
uint RandId()
|
||||
{
|
||||
uint id = 0;
|
||||
var idSpan = MemoryMarshal.CreateSpan(ref id, 1);
|
||||
var idBytes = MemoryMarshal.Cast<uint, byte>(idSpan);
|
||||
|
||||
_random.NextBytes(idBytes);
|
||||
|
||||
return id;
|
||||
return unchecked((uint)_random.Next(int.MinValue, int.MaxValue));
|
||||
}
|
||||
|
||||
uint AllocateExport(Skeleton providedCapability, out bool first)
|
||||
@ -237,7 +239,7 @@ namespace Capnp.Rpc
|
||||
|
||||
lock (_reentrancyBlocker)
|
||||
{
|
||||
while (!_questionTable.TryAdd(questionId, question))
|
||||
while (!_questionTable.ReplacementTryAdd(questionId, question))
|
||||
{
|
||||
questionId = RandId();
|
||||
var oldQuestion = question;
|
||||
@ -277,7 +279,7 @@ namespace Capnp.Rpc
|
||||
{
|
||||
uint id = RandId();
|
||||
|
||||
while (!_pendingDisembargos.TryAdd(id, tcs))
|
||||
while (!_pendingDisembargos.ReplacementTryAdd(id, tcs))
|
||||
{
|
||||
id = RandId();
|
||||
}
|
||||
@ -323,7 +325,7 @@ namespace Capnp.Rpc
|
||||
bool added;
|
||||
lock (_reentrancyBlocker)
|
||||
{
|
||||
added = _answerTable.TryAdd(req.QuestionId, pendingAnswer);
|
||||
added = _answerTable.ReplacementTryAdd(req.QuestionId, pendingAnswer);
|
||||
}
|
||||
|
||||
if (!added)
|
||||
@ -382,7 +384,7 @@ namespace Capnp.Rpc
|
||||
bool added;
|
||||
lock (_reentrancyBlocker)
|
||||
{
|
||||
added = _answerTable.TryAdd(req.QuestionId, pendingAnswer);
|
||||
added = _answerTable.ReplacementTryAdd(req.QuestionId, pendingAnswer);
|
||||
}
|
||||
|
||||
if (!added)
|
||||
@ -876,7 +878,7 @@ namespace Capnp.Rpc
|
||||
|
||||
lock (_reentrancyBlocker)
|
||||
{
|
||||
exists = _pendingDisembargos.Remove(disembargo.Context.ReceiverLoopback, out tcs);
|
||||
exists = _pendingDisembargos.ReplacementTryRemove(disembargo.Context.ReceiverLoopback, out tcs);
|
||||
}
|
||||
|
||||
if (exists)
|
||||
@ -950,7 +952,7 @@ namespace Capnp.Rpc
|
||||
|
||||
lock (_reentrancyBlocker)
|
||||
{
|
||||
exists = _answerTable.Remove(finish.QuestionId, out answer);
|
||||
exists = _answerTable.ReplacementTryRemove(finish.QuestionId, out answer);
|
||||
}
|
||||
|
||||
if (exists)
|
||||
@ -988,7 +990,7 @@ namespace Capnp.Rpc
|
||||
if (rc.RefCount == 0)
|
||||
{
|
||||
_exportTable.Remove(id);
|
||||
_revExportTable.Remove(rc.Cap, out uint _);
|
||||
_revExportTable.ReplacementTryRemove(rc.Cap, out uint _);
|
||||
}
|
||||
}
|
||||
catch (System.Exception)
|
||||
|
@ -5,10 +5,16 @@
|
||||
/// </summary>
|
||||
public class RpcException : System.Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructs an instance.
|
||||
/// </summary>
|
||||
public RpcException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs an instance with message and inner exception.
|
||||
/// </summary>
|
||||
public RpcException(string message, System.Exception innerException) : base(message, innerException)
|
||||
{
|
||||
}
|
||||
|
@ -101,6 +101,9 @@ namespace Capnp.Rpc
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finalizer
|
||||
/// </summary>
|
||||
~Skeleton()
|
||||
{
|
||||
Dispose(false);
|
||||
|
@ -4,6 +4,7 @@ using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
@ -53,17 +54,26 @@ namespace Capnp.Rpc
|
||||
public Task WhenConnected { get; }
|
||||
|
||||
async Task ConnectAsync(string host, int port)
|
||||
{
|
||||
for (int retry = 0; ; retry++)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _client.ConnectAsync(host, port);
|
||||
|
||||
return;
|
||||
}
|
||||
catch (SocketException exception) when (retry < 240 && exception.SocketErrorCode == SocketError.AddressAlreadyInUse)
|
||||
{
|
||||
await Task.Delay(1000);
|
||||
}
|
||||
catch (SocketException exception)
|
||||
{
|
||||
throw new RpcException("TcpRpcClient is unable to connect", exception);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
async Task Connect(string host, int port)
|
||||
{
|
||||
await ConnectAsync(host, port);
|
||||
@ -103,6 +113,7 @@ namespace Capnp.Rpc
|
||||
{
|
||||
_rpcEngine = new RpcEngine();
|
||||
_client = new TcpClient();
|
||||
_client.ExclusiveAddressUse = false;
|
||||
|
||||
WhenConnected = Connect(host, port);
|
||||
}
|
||||
@ -119,7 +130,7 @@ namespace Capnp.Rpc
|
||||
throw new InvalidOperationException("Connection not yet established");
|
||||
}
|
||||
|
||||
if (!WhenConnected.IsCompletedSuccessfully)
|
||||
if (!WhenConnected.ReplacementTaskIsCompletedSuccessfully())
|
||||
{
|
||||
throw new InvalidOperationException("Connection not successfully established");
|
||||
}
|
||||
@ -143,8 +154,9 @@ namespace Capnp.Rpc
|
||||
Logger.LogError("Unable to join connection task within timeout");
|
||||
}
|
||||
}
|
||||
catch (System.Exception)
|
||||
catch (System.Exception e)
|
||||
{
|
||||
Logger.LogError(e, "Failure disposing client");
|
||||
}
|
||||
|
||||
if (_pumpThread != null && !_pumpThread.Join(500))
|
||||
|
@ -14,12 +14,34 @@ namespace Capnp.Rpc
|
||||
/// </summary>
|
||||
public class TcpRpcServer: IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Models an incoming connection.
|
||||
/// </summary>
|
||||
public interface IConnection
|
||||
{
|
||||
/// <summary>
|
||||
/// Server-side port
|
||||
/// </summary>
|
||||
int LocalPort { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Receive message counter
|
||||
/// </summary>
|
||||
long RecvCount { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Sent message counter
|
||||
/// </summary>
|
||||
long SendCount { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether the RPC engine is currently computing.
|
||||
/// </summary>
|
||||
bool IsComputing { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether the connection is idle, waiting for data to receive.
|
||||
/// </summary>
|
||||
bool IsWaitingForData { get; }
|
||||
}
|
||||
|
||||
@ -169,10 +191,17 @@ namespace Capnp.Rpc
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (!_acceptorThread.Join(500))
|
||||
{
|
||||
Logger.LogError("Unable to join TCP acceptor thread within timeout");
|
||||
}
|
||||
}
|
||||
catch (ThreadStateException)
|
||||
{
|
||||
// If acceptor thread was not yet started this is not a problem. Ignore.
|
||||
}
|
||||
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
@ -188,12 +217,23 @@ namespace Capnp.Rpc
|
||||
{
|
||||
_rpcEngine = new RpcEngine();
|
||||
_listener = new TcpListener(localAddr, port);
|
||||
_listener.Start();
|
||||
_listener.ExclusiveAddressUse = false;
|
||||
|
||||
_acceptorThread = new Thread(() =>
|
||||
for (int retry = 0; retry < 5; retry++)
|
||||
{
|
||||
AcceptClients();
|
||||
});
|
||||
try
|
||||
{
|
||||
_listener.Start();
|
||||
break;
|
||||
}
|
||||
catch (SocketException socketException)
|
||||
{
|
||||
Logger.LogWarning($"Failed to listen on port {port}, attempt {retry}: {socketException}");
|
||||
Thread.Sleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
_acceptorThread = new Thread(AcceptClients);
|
||||
|
||||
_acceptorThread.Start();
|
||||
}
|
||||
|
@ -37,12 +37,18 @@ namespace Capnp.Rpc
|
||||
if (promisedAnswer is PendingQuestion pendingQuestion && pendingQuestion.RpcEndpoint == Impatient.AskingEndpoint)
|
||||
{
|
||||
async void SetupCancellation()
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var registration = cancellationToken.Register(promisedAnswer.Dispose))
|
||||
{
|
||||
await promisedAnswer.WhenReturned;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
SetupCancellation();
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using Capnp;
|
||||
using Capnp.Rpc;
|
||||
using System;
|
||||
|
@ -7,7 +7,14 @@ namespace Capnp
|
||||
/// </summary>
|
||||
public struct SegmentSlice
|
||||
{
|
||||
/// <summary>
|
||||
/// Segment index
|
||||
/// </summary>
|
||||
public uint SegmentIndex;
|
||||
|
||||
/// <summary>
|
||||
/// Word offset within segment
|
||||
/// </summary>
|
||||
public int Offset;
|
||||
}
|
||||
}
|
||||
|
@ -285,9 +285,9 @@ namespace Capnp
|
||||
public static float ReadDataFloat<T>(this T d, ulong bitOffset, float defaultValue = 0)
|
||||
where T : IStructDeserializer
|
||||
{
|
||||
int defaultBits = BitConverter.SingleToInt32Bits(defaultValue);
|
||||
int defaultBits = defaultValue.ReplacementSingleToInt32Bits();
|
||||
int bits = (int)d.StructReadData(bitOffset, 32) ^ defaultBits;
|
||||
return BitConverter.Int32BitsToSingle(bits);
|
||||
return bits.ReplacementInt32ToSingleBits();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -301,8 +301,8 @@ namespace Capnp
|
||||
public static void WriteData<T>(this T d, ulong bitOffset, float value, float defaultValue = 0.0f)
|
||||
where T : IStructSerializer
|
||||
{
|
||||
int bits = BitConverter.SingleToInt32Bits(value);
|
||||
int defaultBits = BitConverter.SingleToInt32Bits(defaultValue);
|
||||
int bits = value.ReplacementSingleToInt32Bits();
|
||||
int defaultBits = defaultValue.ReplacementSingleToInt32Bits();
|
||||
WriteData(d, bitOffset, bits, defaultBits);
|
||||
}
|
||||
|
||||
|
@ -406,9 +406,10 @@ namespace Capnp
|
||||
/// <exception cref="ArgumentNullException"><paramref name="target"/> is null</exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException"><paramref name="slot"/> out of range</exception>
|
||||
/// <exception cref="InvalidOperationException"><list type="bullet">
|
||||
/// <item><description>This state does neither describe a struct, nor a list of pointers</description></item></list>
|
||||
/// <item><description>Another state is already linked to the specified position (sorry, no overwrite allowed)</description></item></list>
|
||||
/// <item><description>This state and <paramref name="target"/> belong to different message builder, and<paramref name="allowCopy"/> is false</description></item></list>
|
||||
/// <item><description>This state does neither describe a struct, nor a list of pointers</description></item>
|
||||
/// <item><description>Another state is already linked to the specified position (sorry, no overwrite allowed)</description></item>
|
||||
/// <item><description>This state and <paramref name="target"/> belong to different message builder, and<paramref name="allowCopy"/> is false</description></item>
|
||||
/// </list>
|
||||
/// </exception>
|
||||
protected void Link(int slot, SerializerState target, bool allowCopy = true)
|
||||
{
|
||||
@ -461,7 +462,7 @@ namespace Capnp
|
||||
/// If this state describes a list of pointers: List element index.</param>
|
||||
/// <param name="capabilityIndex">capability index inside the capability table</param>
|
||||
/// <exception cref="InvalidOperationException"><list type="bullet">
|
||||
/// <item><description>This state does neither describe a struct, nor a list of pointers</description></item></list>
|
||||
/// <item><description>This state does neither describe a struct, nor a list of pointers</description></item>
|
||||
/// <item><description>Another state is already linked to the specified position (sorry, no overwrite allowed)</description></item></list>
|
||||
/// </exception>
|
||||
protected void LinkToCapability(int slot, uint capabilityIndex)
|
||||
@ -706,8 +707,8 @@ namespace Capnp
|
||||
/// <param name="count">Number of bits to read</param>
|
||||
/// <returns>Data bits which were read</returns>
|
||||
/// <exception cref="InvalidOperationException">The object was not determined to be a struct</exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException">The data slice specified by <paramref name="bitOffset"/> and <paramref name="bitCount"/>
|
||||
/// is not completely within the struct's data section, misaligned, exceeds one word, or <paramref name="bitCount"/> is negative</exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException">The data slice specified by <paramref name="bitOffset"/> and <paramref name="count"/>
|
||||
/// is not completely within the struct's data section, misaligned, exceeds one word, or <paramref name="count"/> is negative</exception>
|
||||
public ulong StructReadData(ulong bitOffset, int count)
|
||||
{
|
||||
if (Kind != ObjectKind.Struct)
|
||||
@ -818,6 +819,13 @@ namespace Capnp
|
||||
/// <exception cref="IndexOutOfRangeException"><paramref name="index"/> is out of bounds.</exception>
|
||||
public SerializerState TryGetPointer(int index) => TryGetPointer<SerializerState>(index);
|
||||
|
||||
/// <summary>
|
||||
/// Reads text from a struct field or list element.
|
||||
/// </summary>
|
||||
/// <param name="index">If the underlying object is a struct: index into the struct's pointer section.
|
||||
/// If the underlying object is a list of pointers: Element index</param>
|
||||
/// <param name="defaultText">String to return in case of null</param>
|
||||
/// <returns>The decoded text</returns>
|
||||
public string ReadText(int index, string defaultText = null)
|
||||
{
|
||||
var b = BuildPointer(index);
|
||||
@ -1068,7 +1076,11 @@ namespace Capnp
|
||||
{
|
||||
var bytes = ListGetBytes();
|
||||
if (bytes.Length == 0) return string.Empty;
|
||||
#if NETSTANDARD2_0
|
||||
return Encoding.UTF8.GetString(bytes.Slice(0, bytes.Length - 1).ToArray());
|
||||
#else
|
||||
return Encoding.UTF8.GetString(bytes.Slice(0, bytes.Length - 1));
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -1164,8 +1176,8 @@ namespace Capnp
|
||||
/// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is out of bounds.</exception>
|
||||
public void ListWriteValue(int index, float value, float defaultValue = 0)
|
||||
{
|
||||
int rcastValue = BitConverter.SingleToInt32Bits(value);
|
||||
int rcastDefaultValue = BitConverter.SingleToInt32Bits(defaultValue);
|
||||
int rcastValue = value.ReplacementSingleToInt32Bits();
|
||||
int rcastDefaultValue = defaultValue.ReplacementSingleToInt32Bits();
|
||||
ListWriteValue(index, rcastValue, rcastDefaultValue);
|
||||
}
|
||||
|
||||
@ -1256,7 +1268,7 @@ namespace Capnp
|
||||
/// <summary>
|
||||
/// Adds an entry to the capability table if the provided capability does not yet exist.
|
||||
/// </summary>
|
||||
/// <param name="capability">The capability, in one of the following forms:<list type="bullet">
|
||||
/// <param name="obj">The capability, in one of the following forms:<list type="bullet">
|
||||
/// <item><description>Low-level capability object (<code>Rpc.ConsumedCapability</code>)</description></item>
|
||||
/// <item><description>Proxy object (<code>Rpc.Proxy</code>)</description></item>
|
||||
/// <item><description>Skeleton object (<code>Rpc.Skeleton</code>)</description></item>
|
||||
@ -1297,7 +1309,7 @@ namespace Capnp
|
||||
/// </list></param>
|
||||
/// <exception cref="ArgumentOutOfRangeException"><paramref name="slot"/> is out of range.</exception>
|
||||
/// <exception cref="InvalidOperationException"><list type="bullet">
|
||||
/// <item><description>This state does neither describe a struct, nor a list of pointers</description></item></list>
|
||||
/// <item><description>This state does neither describe a struct, nor a list of pointers</description></item>
|
||||
/// <item><description>Another state is already linked to the specified position (sorry, no overwrite allowed)</description></item></list>
|
||||
/// </exception>
|
||||
public void LinkObject<T>(int slot, T obj)
|
||||
@ -1355,7 +1367,7 @@ namespace Capnp
|
||||
/// <param name="slot">Index into this struct's pointer table.</param>
|
||||
/// <returns>The proxy instance</returns>
|
||||
/// <exception cref="ArgumentOutOfRangeException"><paramref name="slot"/> is out of range.</exception>
|
||||
/// <exception cref="ArgumentException">The desired interface does not qualify as capability interface (<see cref="Rpc.ProxyAttribute")/></exception>
|
||||
/// <exception cref="ArgumentException">The desired interface does not qualify as capability interface (<see cref="Rpc.ProxyAttribute"/>)</exception>
|
||||
/// <exception cref="InvalidOperationException">This state does not represent a struct.</exception>
|
||||
public T ReadCap<T>(int slot) where T : class
|
||||
{
|
||||
|
80
Capnp.Net.Runtime/UtilityExtensions.cs
Normal file
80
Capnp.Net.Runtime/UtilityExtensions.cs
Normal file
@ -0,0 +1,80 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Capnp
|
||||
{
|
||||
internal static class UtilityExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// This method exists until NET Standard 2.1 is released
|
||||
/// </summary>
|
||||
/// <param name="thisDict"></param>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <typeparam name="K"></typeparam>
|
||||
/// <typeparam name="V"></typeparam>
|
||||
/// <returns></returns>
|
||||
#if NETSTANDARD2_0
|
||||
public static bool ReplacementTryAdd<K, V>(this Dictionary<K, V> thisDict, K key, V value)
|
||||
{
|
||||
if (thisDict.ContainsKey(key)) return false;
|
||||
thisDict.Add(key, value);
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
public static bool ReplacementTryAdd<K, V>(this Dictionary<K, V> thisDict, K key, V value) => thisDict.TryAdd(key, value);
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// This method exists until NET Standard 2.1 is released
|
||||
/// </summary>
|
||||
/// <param name="thisDict"></param>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <typeparam name="K"></typeparam>
|
||||
/// <typeparam name="V"></typeparam>
|
||||
/// <returns></returns>
|
||||
#if NETSTANDARD2_0
|
||||
public static bool ReplacementTryRemove<K, V>(this Dictionary<K, V> thisDict, K key, out V value)
|
||||
{
|
||||
if (!thisDict.ContainsKey(key))
|
||||
{
|
||||
value = default;
|
||||
return false;
|
||||
}
|
||||
value = thisDict[key];
|
||||
return thisDict.Remove(key);
|
||||
}
|
||||
#else
|
||||
public static bool ReplacementTryRemove<K, V>(this Dictionary<K, V> thisDict, K key, out V value) => thisDict.Remove(key, out value);
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// This method exists until NET Standard 2.1 is released
|
||||
/// </summary>
|
||||
/// <param name="task"></param>
|
||||
/// <returns></returns>
|
||||
#if NETSTANDARD2_0
|
||||
public static bool ReplacementTaskIsCompletedSuccessfully(this Task task)
|
||||
{
|
||||
return task.IsCompleted && !task.IsCanceled && !task.IsFaulted;
|
||||
}
|
||||
#else
|
||||
public static bool ReplacementTaskIsCompletedSuccessfully(this Task task) => task.IsCompletedSuccessfully;
|
||||
#endif
|
||||
|
||||
#if NETSTANDARD2_0
|
||||
public static int ReplacementSingleToInt32Bits(this float value) => BitConverter.ToInt32(BitConverter.GetBytes(value), 0);
|
||||
#else
|
||||
public static int ReplacementSingleToInt32Bits(this float value) => BitConverter.SingleToInt32Bits(value);
|
||||
#endif
|
||||
|
||||
#if NETSTANDARD2_0
|
||||
public static float ReplacementInt32ToSingleBits(this int value) => BitConverter.ToSingle(BitConverter.GetBytes(value), 0);
|
||||
#else
|
||||
public static float ReplacementInt32ToSingleBits(this int value) => BitConverter.Int32BitsToSingle(value);
|
||||
#endif
|
||||
}
|
||||
}
|
@ -5,13 +5,28 @@ using System.Text;
|
||||
namespace Capnp
|
||||
{
|
||||
/// <summary>
|
||||
/// Pointer tag, <see cref="https://capnproto.org/encoding.html"/>
|
||||
/// Pointer tag, see https://capnproto.org/encoding.html/>
|
||||
/// </summary>
|
||||
public enum PointerKind : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Struct pointer
|
||||
/// </summary>
|
||||
Struct = 0,
|
||||
|
||||
/// <summary>
|
||||
/// List pointer
|
||||
/// </summary>
|
||||
List = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Far pointer
|
||||
/// </summary>
|
||||
Far = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Other (capability) pointer
|
||||
/// </summary>
|
||||
Other = 3
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Capnp.Net.Runtime", "Capnp.
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "capnpc-csharp", "capnpc-csharp\capnpc-csharp.csproj", "{D19E5EA7-D35B-4A1F-99CB-ED136316B577}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Capnp.Net.Runtime.Tests", "Capnp.Net.Runtime.Tests\Capnp.Net.Runtime.Tests.csproj", "{9ED38750-F83F-4B10-B3A3-4FD6183F9E86}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Capnp.Net.Runtime.Tests.Std20", "Capnp.Net.Runtime.Tests\Capnp.Net.Runtime.Tests.Std20.csproj", "{9ED38750-F83F-4B10-B3A3-4FD6183F9E86}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Capnp.Net.Runtime.Tests.Core21", "Capnp.Net.Runtime.Tests.Core21\Capnp.Net.Runtime.Tests.Core21.csproj", "{58E8FFC8-D207-4B0F-842A-58ED9D3D9EEF}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
@ -23,14 +25,14 @@ Global
|
||||
{D19E5EA7-D35B-4A1F-99CB-ED136316B577}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D19E5EA7-D35B-4A1F-99CB-ED136316B577}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D19E5EA7-D35B-4A1F-99CB-ED136316B577}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8C17F147-D784-4584-80FF-21BE03AC0D17}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8C17F147-D784-4584-80FF-21BE03AC0D17}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8C17F147-D784-4584-80FF-21BE03AC0D17}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8C17F147-D784-4584-80FF-21BE03AC0D17}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9ED38750-F83F-4B10-B3A3-4FD6183F9E86}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9ED38750-F83F-4B10-B3A3-4FD6183F9E86}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9ED38750-F83F-4B10-B3A3-4FD6183F9E86}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9ED38750-F83F-4B10-B3A3-4FD6183F9E86}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{58E8FFC8-D207-4B0F-842A-58ED9D3D9EEF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{58E8FFC8-D207-4B0F-842A-58ED9D3D9EEF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{58E8FFC8-D207-4B0F-842A-58ED9D3D9EEF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{58E8FFC8-D207-4B0F-842A-58ED9D3D9EEF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -1,8 +1,6 @@
|
||||
using Capnp;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace CapnpC
|
||||
{
|
||||
@ -18,9 +16,14 @@ namespace CapnpC
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Cap'n Proto C# code generator backend");
|
||||
Console.WriteLine("expecting binary-encoded code generation request from standard input");
|
||||
|
||||
input = Console.OpenStandardInput();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
WireFrame segments;
|
||||
|
||||
using (input)
|
||||
@ -34,5 +37,11 @@ namespace CapnpC
|
||||
var codeGen = new Generator.CodeGenerator(model, new Generator.GeneratorOptions());
|
||||
codeGen.Generate();
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Console.Error.WriteLine(exception.Message);
|
||||
Environment.ExitCode = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,19 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
<RootNamespace>CapnpC</RootNamespace>
|
||||
<LangVersion>7.1</LangVersion>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
<Authors>Christian Köllner and contributors</Authors>
|
||||
<Description>Cap'n Proto C# code generator backend</Description>
|
||||
<Copyright>Christian Köllner and contributors</Copyright>
|
||||
<PackageProjectUrl>https://github.com/c80k/capnproto-dotnetcore</PackageProjectUrl>
|
||||
<RepositoryType>Git</RepositoryType>
|
||||
<PackageTags>capnp capnpc RPC serialization cerealization</PackageTags>
|
||||
<Version>1.0.0</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
|
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>capnpc-csharp-win-x86</id>
|
||||
<version>1.0.0</version>
|
||||
<authors>Christian Köllner and contributors</authors>
|
||||
<owners>Christian Köllner and contributors</owners>
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<!--<license type="expression">MIT</license>-->
|
||||
<licenseUrl>https://licenses.nuget.org/MIT</licenseUrl>
|
||||
<projectUrl>https://github.com/c80k/capnproto-dotnetcore</projectUrl>
|
||||
<description>Cap'n Proto C# code generator backend, self-contained Windows x86</description>
|
||||
<copyright>Christian Köllner and contributors</copyright>
|
||||
<tags>capnp capnpc RPC serialization cerealization</tags>
|
||||
<!--<repository type="Git" />-->
|
||||
</metadata>
|
||||
<files>
|
||||
<file src="chocolateyinstall.ps1" target="tools" />
|
||||
<file src="chocolateyuninstall.ps1" target="tools" />
|
||||
<file src=".\bin\**" target="tools" />
|
||||
</files>
|
||||
</package>
|
6
chocolatey/capnpc-csharp-win-x86/chocolateyinstall.ps1
Normal file
6
chocolatey/capnpc-csharp-win-x86/chocolateyinstall.ps1
Normal file
@ -0,0 +1,6 @@
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
$toolsDir = "$(Split-Path -parent $MyInvocation.MyCommand.Definition)"
|
||||
|
||||
choco install capnproto
|
||||
Install-Binfile -Name capnpc-csharp -Path "$toolsDir\capnpc-csharp.exe"
|
3
chocolatey/capnpc-csharp-win-x86/chocolateyuninstall.ps1
Normal file
3
chocolatey/capnpc-csharp-win-x86/chocolateyuninstall.ps1
Normal file
@ -0,0 +1,3 @@
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
Uninstall-BinFile capnpc-sharp
|
22
chocolatey/capnpc-csharp/capnpc-csharp.nuspec
Normal file
22
chocolatey/capnpc-csharp/capnpc-csharp.nuspec
Normal file
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>capnpc-csharp-win-x86</id>
|
||||
<version>1.0.0</version>
|
||||
<authors>Christian Köllner and contributors</authors>
|
||||
<owners>Christian Köllner and contributors</owners>
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<!--<license type="expression">MIT</license>-->
|
||||
<licenseUrl>https://licenses.nuget.org/MIT</licenseUrl>
|
||||
<projectUrl>https://github.com/c80k/capnproto-dotnetcore</projectUrl>
|
||||
<description>Cap'n Proto C# code generator backend, portable .NET Core 2.1</description>
|
||||
<copyright>Christian Köllner and contributors</copyright>
|
||||
<tags>capnp capnpc RPC serialization cerealization</tags>
|
||||
<!--<repository type="Git" />-->
|
||||
</metadata>
|
||||
<files>
|
||||
<file src="chocolateyinstall.ps1" target="tools" />
|
||||
<file src="chocolateyuninstall.ps1" target="tools" />
|
||||
<file src=".\bin\**" target="tools" />
|
||||
</files>
|
||||
</package>
|
5
chocolatey/capnpc-csharp/chocolateyinstall.ps1
Normal file
5
chocolatey/capnpc-csharp/chocolateyinstall.ps1
Normal file
@ -0,0 +1,5 @@
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
$toolsDir = "$(Split-Path -parent $MyInvocation.MyCommand.Definition)"
|
||||
|
||||
Install-Binfile -Name capnpc-csharp -Path "dotnet" -Command "$toolsDir\capnpc-csharp.dll"
|
3
chocolatey/capnpc-csharp/chocolateyuninstall.ps1
Normal file
3
chocolatey/capnpc-csharp/chocolateyuninstall.ps1
Normal file
@ -0,0 +1,3 @@
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
Uninstall-BinFile capnpc-sharp
|
2464
chocolatey/deploy/capnpc-csharp.deps.json
Normal file
2464
chocolatey/deploy/capnpc-csharp.deps.json
Normal file
File diff suppressed because it is too large
Load Diff
3
chocolatey/deploy/capnpc-csharp.runtimeconfig.json
Normal file
3
chocolatey/deploy/capnpc-csharp.runtimeconfig.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"runtimeOptions": {}
|
||||
}
|
8
scripts/capnpc-csharp-install-win-x86.ps1
Normal file
8
scripts/capnpc-csharp-install-win-x86.ps1
Normal file
@ -0,0 +1,8 @@
|
||||
$id = "capnpc-csharp-win-x86"
|
||||
|
||||
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
$installDir = "$scriptDir\..\chocolatey\install"
|
||||
|
||||
if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) { Start-Process powershell.exe "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`"" -Verb RunAs; exit }
|
||||
|
||||
choco install $id -s $installDir --force
|
8
scripts/capnpc-csharp-install.ps1
Normal file
8
scripts/capnpc-csharp-install.ps1
Normal file
@ -0,0 +1,8 @@
|
||||
$id = "capnpc-csharp"
|
||||
|
||||
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
$installDir = "$scriptDir\..\chocolatey\install"
|
||||
|
||||
if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) { Start-Process powershell.exe "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`"" -Verb RunAs; exit }
|
||||
|
||||
choco install $id -s $installDir --force
|
12
scripts/capnpc-csharp-pack.ps1
Normal file
12
scripts/capnpc-csharp-pack.ps1
Normal file
@ -0,0 +1,12 @@
|
||||
$id = "capnpc-csharp"
|
||||
$id_win_x86 = "capnpc-csharp-win-x86"
|
||||
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
$chocoDir = "$scriptDir\..\chocolatey"
|
||||
$csprojDir = "$scriptDir\..\capnpc-csharp"
|
||||
$csprojFile = "capnpc-csharp.csproj"
|
||||
|
||||
dotnet publish -c Release -r win-x86 --self-contained -o "$chocoDir\$id_win_x86\bin" "$csprojDir\$csprojFile"
|
||||
dotnet publish -c Release -o "$chocoDir\$id\bin" "$csprojDir\$csprojFile"
|
||||
|
||||
choco pack "$chocoDir\$id\$id.nuspec" --outputdirectory "$chocoDir\$id\bin"
|
||||
choco pack "$chocoDir\$id_win_x86\$id_win_x86.nuspec" --outputdirectory "$chocoDir\$id_win_x86\bin"
|
Loading…
x
Reference in New Issue
Block a user