diff --git a/Capnp.Net.Runtime.Tests/TcpRpcStress.cs b/Capnp.Net.Runtime.Tests/TcpRpcStress.cs index 442df94..4bc3e00 100644 --- a/Capnp.Net.Runtime.Tests/TcpRpcStress.cs +++ b/Capnp.Net.Runtime.Tests/TcpRpcStress.cs @@ -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(); - if (Thread.CurrentThread.Name == null) - Thread.CurrentThread.Name = $"Test Thread {Thread.CurrentThread.ManagedThreadId}"; - } - [TestMethod] public void ResolveMain() { diff --git a/Capnp.Net.Runtime/Capnp.Net.Runtime.Std20.xml b/Capnp.Net.Runtime/Capnp.Net.Runtime.Std20.xml index d2e4c79..13cccfb 100644 --- a/Capnp.Net.Runtime/Capnp.Net.Runtime.Std20.xml +++ b/Capnp.Net.Runtime/Capnp.Net.Runtime.Std20.xml @@ -62,6 +62,16 @@ This exception gets thrown when a Cap'n Proto object could not be deserialized correctly. + + + Constructs an instance + + + + + Constructs an instance with message and inner exception + + Implements the heart of deserialization. This stateful helper struct exposes all functionality to traverse serialized data. @@ -279,6 +289,9 @@ Capability interface index within this struct's pointer table + debugging aid + debugging aid + debugging aid capability instance or null if pointer was null negative index state does not represent a struct, invalid pointer, @@ -331,8 +344,36 @@ The deserializer state to convert - - + + + Links a sub-item (struct field or list element) of this state to another state. Usually, this operation is not necessary, since objects are constructed top-down. + However, there might be some advanced scenarios where you want to reference the same object twice (also interesting for designing amplification attacks). + The Cap'n Proto serialization intrinsically supports this, since messages are object graphs, not trees. + + If this state describes a struct: Index into this struct's pointer table. + If this state describes a list of pointers: List element index. + state to be linked + Whether to deep copy the target state if it belongs to a different message builder than this state. + is null + out of range + + This state does neither describe a struct, nor a list of pointers + Another state is already linked to the specified position (sorry, no overwrite allowed) + This state and belong to different message builder, and is false + + + + + Links a sub-item (struct field or list element) of this state to a capability. + + If this state describes a struct: Index into this struct's pointer table. + If this state describes a list of pointers: List element index. + capability index inside the capability table + + This state does neither describe a struct, nor a list of pointers + Another state is already linked to the specified position (sorry, no overwrite allowed) + + Determines the underlying object to be a struct. @@ -369,7 +410,37 @@ The object type was already set to something different negative, or total word count would exceed 2^29-1 - + + + Constructs the underlying object from the given representation. + + Object representation. Must be one of the following: + + An instance implementing + null + A + A ]]> + A ]]> + A ]]> + A ]]> + A ]]> + A ]]> + A ]]> + A ]]> + A ]]> + A ]]> + A ]]> + A ]]> + Another + Another + Low-level capability object () + Proxy object () + Skeleton object () + Capability interface implementation + A ]]> whereby each list item is one of the things listed here. + + + Implements an empty . @@ -411,43 +482,47 @@ - Returns an empty . + Returns an empty ]]>/>. - Returns an empty . + Returns an empty ]]>/>. - Returns an empty . + Returns an empty ]]>/>. + + + + + Returns an empty ]]>. - - Returns an empty . + Returns an empty ]]>. - Returns an empty . + Returns an empty ]]>. - Returns an empty . + Returns an empty ]]>/>. - Returns an empty . + Returns an empty ]]>. - Returns an empty . + Returns an empty ]]>. @@ -457,17 +532,17 @@ - Returns an empty . + Returns an empty ]]>. - Returns an empty . + Returns an empty ]]>. - Returns an empty . + Returns an empty ]]>. @@ -543,6 +618,13 @@ Encountered invalid framing data, too many or too large segments Too many or too large segments, probably due to invalid framing data. + + + Deserializes the next Cap'n Proto message from given stream. + + The stream to read from + The message + This interface is intended to be implemented by schema-generated domain classes which support deserialization from @@ -876,6 +958,13 @@ The desired representation If this list cannot be represented in the desired manner. + + + Represents this list as List(Int64). + + The desired representation + If this list cannot be represented in the desired manner. + Represents this list as List(UInt64). @@ -962,7 +1051,7 @@ - Implements + Implements @@ -1039,7 +1128,12 @@ Always throws , since it is not intended to convert a capability list to anything else. - + + + Implements . + + + SerializerState specialization for a list of capabilities. @@ -1084,7 +1178,12 @@ This list's element count. - + + + Implements . + + + ListDeserializer specialization for List(Void). @@ -1403,7 +1502,11 @@ The selector function The new list representation - + + + Implements . + + SerializerState specialization for List(T) when T is a known struct (i.e. a list of fixed-width composites). @@ -1625,7 +1728,18 @@ Provides extension methods for - + + + LINQ-like "Select" operator for , 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./> + + Source element type + Target element type + Source list + Selector function + A read-only list in which each element corresponds to the source element after applying the selector function + or is null. + Applies a selector function to each list element and stores the result in a new list. @@ -1662,6 +1776,28 @@ Helper struct to support tail calls + + + Wraps a SerializerState + + object to wrap + + + + Wraps a PendingQuestion + + object to wrap + + + + SerializerState, if applicable + + + + + PendingQuestion, if applicable + + Generic Proxy implementation which exposes the (usually protected) Call method. @@ -1673,13 +1809,13 @@ Capability implementation Proxy - is null. + is null. No found on implemented interface(s). - Mismatch between generic type arguments (if capability interface is generic). - Mismatch between generic type arguments (if capability interface is generic). + Mismatch between generic type arguments (if capability interface is generic). + Mismatch between generic type arguments (if capability interface is generic). Problem with instatiating the Skeleton (constructor threw exception). - Caller does not have permission to invoke the Skeleton constructor. - Problem with building the Skeleton type, or problem with loading some dependent class. + Caller does not have permission to invoke the Skeleton constructor. + Problem with building the Skeleton type, or problem with loading some dependent class. @@ -1746,6 +1882,9 @@ Capability interface. Must be annotated with . low-level capability + debugging aid + debugging aid + debugging aid The Proxy instance which implements . is null. did not qualify as capability interface. @@ -1824,11 +1963,53 @@ Capability interface type The task + debugging aid + debugging aid + debugging aid A proxy for the given task. is null. did not quality as capability interface. + + + Checks whether a given task belongs to a pending RPC and requests a tail call if applicable. + + Task result type + Task to request + Converts the task's result to a SerializerState + Tail-call aware task + + + + Overload for tuple-typed tasks + + + + + Overload for tuple-typed tasks + + + + + Overload for tuple-typed tasks + + + + + Overload for tuple-typed tasks + + + + + Overload for tuple-typed tasks + + + + + Overload for tuple-typed tasks + + Low-level capability which as imported from a remote peer. @@ -1841,6 +2022,16 @@ See descriptions of these attributes for further details. + + + Constructs an instance. + + + + + Constructs an instance with message an inner exception. + + A promised answer due to RPC. @@ -1892,6 +2083,18 @@ A path from an outer Cap'n Proto struct to an inner (probably deeply nested) struct member. + + + Path to the bootstrap capability (which is an empty path) + + + + + Deserializes a MemberAccessPath from Cap'n Proto representation. + + Cap'n Proto representation + The MemberAccessPath + Constructs a path from qualifiers. @@ -1914,6 +2117,13 @@ Now we already have a suitable design pattern, mainly to show the abstract concept behind a member access path. + + + Deserializes a MemberAccess instance from Cap'n Proto representation. + + Cap'n Proto representation + Deserialized instance + Serializes this instance to a . @@ -1984,6 +2194,72 @@ the ongoing call. + + + Question lifetime management state + + + + + The question has not yet been sent. + + + + + Tail call flag + + + + + The question has been sent. + + + + + The question has been answered. + + + + + A 'finish' request was sent to the peer, indicating that no further requests will refer + to this question. + + + + + Question object was disposed. + + + + + Question object was finalized by GC. + This flag should only be observable when debugging the finalizer itself. + + + + + Eventually returns the server answer + + + + + Refer to a (possibly nested) member of this question's (possibly future) result and return + it as a capability. + + Access path + Low-level capability + The referenced member does not exist or does not resolve to a capability pointer. + + + + Finalizer + + + + + Implements . + + Combines multiple skeletons to represent objects which implement multiple interfaces. @@ -2024,6 +2300,11 @@ Will eventually give the resolved capability, if this is a promised capability. + + + Underlying low-level capability + + Whether is this a broken capability. @@ -2041,13 +2322,23 @@ An answer promise This instance was disposed, or transport-layer stream was disposed. Capability is broken. - An I/O error occurs. + An I/O error occurs. + + + + Constructs a null instance. + Dispose pattern implementation + + + Finalizer + + Dispose pattern implementation @@ -2106,6 +2397,16 @@ Thrown when an RPC-related error condition occurs. + + + Constructs an instance. + + + + + Constructs an instance with message and inner exception. + + A skeleton is a wrapper around a capability interface implementation which adapts it in the way it is @@ -2135,6 +2436,11 @@ Dispose pattern implementation + + + Finalizer + + Skeleton for a specific capability interface. @@ -2262,6 +2568,36 @@ Cap'n Proto RPC TCP server. + + + Models an incoming connection. + + + + + Server-side port + + + + + Receive message counter + + + + + Sent message counter + + + + + Whether the RPC engine is currently computing. + + + + + Whether the connection is idle, waiting for data to receive. + + Gets the number of currently active inbound TCP connections. @@ -2352,6 +2688,16 @@ Helper struct to represent the tuple (segment index, offset) + + + Segment index + + + + + Word offset within segment + + Provides extensions to the and interfaces for type-safe reading and writing. @@ -2646,8 +2992,37 @@ anymore (e.g. changing from struct to list, or modifying the struct's section sizes). - - + + + Links a sub-item (struct field or list element) of this state to another state. Usually, this operation is not necessary, since objects are constructed top-down. + However, there might be some advanced scenarios where you want to reference the same object twice (also interesting for designing amplification attacks). + The Cap'n Proto serialization intrinsically supports this, since messages are object graphs, not trees. + + If this state describes a struct: Index into this struct's pointer table. + If this state describes a list of pointers: List element index. + state to be linked + Whether to deep copy the target state if it belongs to a different message builder than this state. + is null + out of range + + This state does neither describe a struct, nor a list of pointers + Another state is already linked to the specified position (sorry, no overwrite allowed) + This state and belong to different message builder, and is false + + + + + + Links a sub-item (struct field or list element) of this state to a capability. + + If this state describes a struct: Index into this struct's pointer table. + If this state describes a list of pointers: List element index. + capability index inside the capability table + + This state does neither describe a struct, nor a list of pointers + Another state is already linked to the specified position (sorry, no overwrite allowed) + + Determines the underlying object to be a struct. @@ -2715,8 +3090,8 @@ Number of bits to read Data bits which were read The object was not determined to be a struct - The data slice specified by and - is not completely within the struct's data section, misaligned, exceeds one word, or is negative + The data slice specified by and + is not completely within the struct's data section, misaligned, exceeds one word, or is negative @@ -2772,6 +3147,15 @@ is out of bounds. + + + Reads text from a struct field or list element. + + 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 + String to return in case of null + The decoded text + Encodes text into a struct field or list element. @@ -2975,7 +3359,7 @@ Adds an entry to the capability table if the provided capability does not yet exist. - The capability, in one of the following forms: + The capability, in one of the following forms: Low-level capability object (Rpc.ConsumedCapability) Proxy object (Rpc.Proxy) Skeleton object (Rpc.Skeleton) @@ -2984,8 +3368,41 @@ Index of the given capability in the capability table The underlying message builder was not configured for capability table support. - - + + + Links a sub-item (struct field or list element) of this state to another object. + In contrast to , this method also accepts deserializer states, domain objects, capabilites, and lists thereof. + If necessary, it will perform a deep copy. + + If this state describes a struct: Index into this struct's pointer table. + If this state describes a list of pointers: List element index. + Object to be linked. Must be one of the following: + Another + A (will always deep copy) + An object implementing + A low-level capability object () + A proxy object () + A skeleton object () + A capability interface implementation + A of one of the things listed here. + + is out of range. + + This state does neither describe a struct, nor a list of pointers + Another state is already linked to the specified position (sorry, no overwrite allowed) + + + + + Reads a struct field as capability and returns a proxy to that capability. + + Desired capability interface + Index into this struct's pointer table. + The proxy instance + is out of range. + The desired interface does not qualify as capability interface () + This state does not represent a struct. + Reads a struct field as capability and returns a bare (generic) proxy to that capability. @@ -3022,7 +3439,6 @@ This method exists until NET Standard 2.1 is released - @@ -3042,7 +3458,27 @@ - Pointer tag, + Pointer tag, see https://capnproto.org/encoding.html/> + + + + + Struct pointer + + + + + List pointer + + + + + Far pointer + + + + + Other (capability) pointer diff --git a/Capnp.Net.Runtime/DeserializationException.cs b/Capnp.Net.Runtime/DeserializationException.cs index 9db5b60..a9dfcaa 100644 --- a/Capnp.Net.Runtime/DeserializationException.cs +++ b/Capnp.Net.Runtime/DeserializationException.cs @@ -7,10 +7,16 @@ namespace Capnp /// public class DeserializationException : Exception { + /// + /// Constructs an instance + /// public DeserializationException(string message) : base(message) { } + /// + /// Constructs an instance with message and inner exception + /// public DeserializationException(string message, Exception innerException): base(message, innerException) { diff --git a/Capnp.Net.Runtime/DeserializerState.cs b/Capnp.Net.Runtime/DeserializerState.cs index f32ab86..5fed754 100644 --- a/Capnp.Net.Runtime/DeserializerState.cs +++ b/Capnp.Net.Runtime/DeserializerState.cs @@ -637,6 +637,9 @@ namespace Capnp /// /// Capability interface /// index within this struct's pointer table + /// debugging aid + /// debugging aid + /// debugging aid /// capability instance or null if pointer was null /// negative index /// state does not represent a struct, invalid pointer, diff --git a/Capnp.Net.Runtime/DynamicSerializerState.cs b/Capnp.Net.Runtime/DynamicSerializerState.cs index 2ac3bc8..793c8f9 100644 --- a/Capnp.Net.Runtime/DynamicSerializerState.cs +++ b/Capnp.Net.Runtime/DynamicSerializerState.cs @@ -61,8 +61,8 @@ namespace Capnp /// is null /// out of range /// - /// This state does neither describe a struct, nor a list of pointers - /// Another state is already linked to the specified position (sorry, no overwrite allowed) + /// This state does neither describe a struct, nor a list of pointers + /// Another state is already linked to the specified position (sorry, no overwrite allowed) /// This state and belong to different message builder, and is false /// 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. /// capability index inside the capability table /// - /// This state does neither describe a struct, nor a list of pointers + /// This state does neither describe a struct, nor a list of pointers /// Another state is already linked to the specified position (sorry, no overwrite allowed) /// public new void LinkToCapability(int slot, uint capabilityIndex) => base.LinkToCapability(slot, capabilityIndex); @@ -123,24 +123,25 @@ namespace Capnp /// An instance implementing /// null /// A - /// A - /// A - /// A - /// A - /// A - /// A - /// A - /// A - /// A - /// A + /// A ]]> + /// A ]]> + /// A ]]> + /// A ]]> + /// A ]]> + /// A ]]> + /// A ]]> + /// A ]]> + /// A ]]> + /// A ]]> + /// A ]]> + /// A ]]> /// Another /// Another /// Low-level capability object () /// Proxy object () /// Skeleton object () /// Capability interface implementation - /// A whereby each list item is one of the things listed here. + /// A ]]> whereby each list item is one of the things listed here. /// /// public void SetObject(object obj) diff --git a/Capnp.Net.Runtime/EmptyListDeserializer.cs b/Capnp.Net.Runtime/EmptyListDeserializer.cs index e843204..ac7be4f 100644 --- a/Capnp.Net.Runtime/EmptyListDeserializer.cs +++ b/Capnp.Net.Runtime/EmptyListDeserializer.cs @@ -21,47 +21,47 @@ namespace Capnp public override IReadOnlyList Cast(Func cons) => new EmptyList(); /// - /// Returns an empty . + /// Returns an empty ]]>/>. /// public override IReadOnlyList CastBool() => new EmptyList(); /// - /// Returns an empty . + /// Returns an empty ]]>/>. /// public override IReadOnlyList CastByte() => new EmptyList(); /// - /// Returns an empty . + /// Returns an empty ]]>/>. /// public override IReadOnlyList CastDouble() => new EmptyList(); /// - /// Returns an empty + /// Returns an empty ]]>. /// public override IReadOnlyList CastFloat() => new EmptyList(); /// - /// Returns an empty . + /// Returns an empty ]]>. /// public override IReadOnlyList CastInt() => new EmptyList(); /// - /// Returns an empty . + /// Returns an empty ]]>. /// public override IReadOnlyList CastList() => new EmptyList(); /// - /// Returns an empty . + /// Returns an empty ]]>/>. /// public override IReadOnlyList CastLong() => new EmptyList(); /// - /// Returns an empty . + /// Returns an empty ]]>. /// public override IReadOnlyList CastSByte() => new EmptyList(); /// - /// Returns an empty . + /// Returns an empty ]]>. /// public override IReadOnlyList CastShort() => new EmptyList(); @@ -71,17 +71,17 @@ namespace Capnp public override string CastText() => string.Empty; /// - /// Returns an empty . + /// Returns an empty ]]>. /// public override IReadOnlyList CastUInt() => new EmptyList(); /// - /// Returns an empty . + /// Returns an empty ]]>. /// public override IReadOnlyList CastULong() => new EmptyList(); /// - /// Returns an empty . + /// Returns an empty ]]>. /// public override IReadOnlyList CastUShort() => new EmptyList(); } diff --git a/Capnp.Net.Runtime/Framing.cs b/Capnp.Net.Runtime/Framing.cs index 4c5e32c..e9707ce 100644 --- a/Capnp.Net.Runtime/Framing.cs +++ b/Capnp.Net.Runtime/Framing.cs @@ -31,6 +31,11 @@ namespace Capnp } } + /// + /// Deserializes the next Cap'n Proto message from given stream. + /// + /// The stream to read from + /// The message public static WireFrame ReadWireFrame(this BinaryReader reader) { uint scount = reader.ReadUInt32(); diff --git a/Capnp.Net.Runtime/ListDeserializer.cs b/Capnp.Net.Runtime/ListDeserializer.cs index 78f4105..cfe2acd 100644 --- a/Capnp.Net.Runtime/ListDeserializer.cs +++ b/Capnp.Net.Runtime/ListDeserializer.cs @@ -360,12 +360,12 @@ namespace Capnp return Cast(sd => sd.ReadDataUInt(0)); } - public virtual IReadOnlyList CastLong() /// /// Represents this list as List(Int64). /// /// The desired representation /// If this list cannot be represented in the desired manner. + public virtual IReadOnlyList CastLong() { return Cast(sd => sd.ReadDataLong(0)); } diff --git a/Capnp.Net.Runtime/ListOfBitsDeserializer.cs b/Capnp.Net.Runtime/ListOfBitsDeserializer.cs index 1cc4061..7415ffb 100644 --- a/Capnp.Net.Runtime/ListOfBitsDeserializer.cs +++ b/Capnp.Net.Runtime/ListOfBitsDeserializer.cs @@ -50,7 +50,7 @@ namespace Capnp } /// - /// Implements + /// Implements /// /// public IEnumerator GetEnumerator() diff --git a/Capnp.Net.Runtime/ListOfCapsDeserializer.cs b/Capnp.Net.Runtime/ListOfCapsDeserializer.cs index a1668c6..c80eff3 100644 --- a/Capnp.Net.Runtime/ListOfCapsDeserializer.cs +++ b/Capnp.Net.Runtime/ListOfCapsDeserializer.cs @@ -56,7 +56,7 @@ namespace Capnp } /// - /// Implements + /// Implements . /// /// public IEnumerator GetEnumerator() diff --git a/Capnp.Net.Runtime/ListOfCapsSerializer.cs b/Capnp.Net.Runtime/ListOfCapsSerializer.cs index b7207e9..960a8e3 100644 --- a/Capnp.Net.Runtime/ListOfCapsSerializer.cs +++ b/Capnp.Net.Runtime/ListOfCapsSerializer.cs @@ -95,7 +95,7 @@ namespace Capnp } /// - /// Implements + /// Implements . /// /// public IEnumerator GetEnumerator() diff --git a/Capnp.Net.Runtime/ListOfStructsDeserializer.cs b/Capnp.Net.Runtime/ListOfStructsDeserializer.cs index 04f0bdd..0b42b07 100644 --- a/Capnp.Net.Runtime/ListOfStructsDeserializer.cs +++ b/Capnp.Net.Runtime/ListOfStructsDeserializer.cs @@ -66,7 +66,7 @@ namespace Capnp } /// - /// Implements + /// Implements . /// public IEnumerator GetEnumerator() { diff --git a/Capnp.Net.Runtime/ReadOnlyListExtensions.cs b/Capnp.Net.Runtime/ReadOnlyListExtensions.cs index 9ff9097..656ec19 100644 --- a/Capnp.Net.Runtime/ReadOnlyListExtensions.cs +++ b/Capnp.Net.Runtime/ReadOnlyListExtensions.cs @@ -38,7 +38,7 @@ namespace Capnp } /// - /// LINQ-like "Select" operator for , 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./> /// /// Source element type diff --git a/Capnp.Net.Runtime/Rpc/AnswerOrCounterquestion.cs b/Capnp.Net.Runtime/Rpc/AnswerOrCounterquestion.cs index 0755b53..1cdd5d6 100644 --- a/Capnp.Net.Runtime/Rpc/AnswerOrCounterquestion.cs +++ b/Capnp.Net.Runtime/Rpc/AnswerOrCounterquestion.cs @@ -12,17 +12,32 @@ _obj = obj; } + /// + /// Wraps a SerializerState + /// + /// object to wrap public static implicit operator AnswerOrCounterquestion (SerializerState answer) { return new AnswerOrCounterquestion(answer); } + /// + /// Wraps a PendingQuestion + /// + /// object to wrap public static implicit operator AnswerOrCounterquestion (PendingQuestion counterquestion) { return new AnswerOrCounterquestion(counterquestion); } + /// + /// SerializerState, if applicable + /// public SerializerState Answer => _obj as SerializerState; + + /// + /// PendingQuestion, if applicable + /// public PendingQuestion Counterquestion => _obj as PendingQuestion; } } diff --git a/Capnp.Net.Runtime/Rpc/BareProxy.cs b/Capnp.Net.Runtime/Rpc/BareProxy.cs index 9739e5a..8f133bc 100644 --- a/Capnp.Net.Runtime/Rpc/BareProxy.cs +++ b/Capnp.Net.Runtime/Rpc/BareProxy.cs @@ -10,13 +10,13 @@ /// /// Capability implementation /// Proxy - /// is null. + /// is null. /// No found on implemented interface(s). - /// Mismatch between generic type arguments (if capability interface is generic). - /// Mismatch between generic type arguments (if capability interface is generic). + /// Mismatch between generic type arguments (if capability interface is generic). + /// Mismatch between generic type arguments (if capability interface is generic). /// Problem with instatiating the Skeleton (constructor threw exception). - /// Caller does not have permission to invoke the Skeleton constructor. - /// Problem with building the Skeleton type, or problem with loading some dependent class. + /// Caller does not have permission to invoke the Skeleton constructor. + /// Problem with building the Skeleton type, or problem with loading some dependent class. public static BareProxy FromImpl(object impl) { return new BareProxy(LocalCapability.Create(CapabilityReflection.CreateSkeleton(impl))); diff --git a/Capnp.Net.Runtime/Rpc/CapabilityReflection.cs b/Capnp.Net.Runtime/Rpc/CapabilityReflection.cs index 87f4441..98b7fe0 100644 --- a/Capnp.Net.Runtime/Rpc/CapabilityReflection.cs +++ b/Capnp.Net.Runtime/Rpc/CapabilityReflection.cs @@ -252,6 +252,9 @@ namespace Capnp.Rpc /// /// Capability interface. Must be annotated with . /// low-level capability + /// debugging aid + /// debugging aid + /// debugging aid /// The Proxy instance which implements . /// is null. /// did not qualify as capability interface. diff --git a/Capnp.Net.Runtime/Rpc/Impatient.cs b/Capnp.Net.Runtime/Rpc/Impatient.cs index c5b9e27..e49d8e0 100644 --- a/Capnp.Net.Runtime/Rpc/Impatient.cs +++ b/Capnp.Net.Runtime/Rpc/Impatient.cs @@ -81,6 +81,9 @@ namespace Capnp.Rpc /// /// Capability interface type /// The task + /// debugging aid + /// debugging aid + /// debugging aid /// A proxy for the given task. /// is null. /// did not @@ -101,6 +104,13 @@ namespace Capnp.Rpc set { _askingEndpoint.Value = value; } } + /// + /// Checks whether a given task belongs to a pending RPC and requests a tail call if applicable. + /// + /// Task result type + /// Task to request + /// Converts the task's result to a SerializerState + /// Tail-call aware task public static async Task MaybeTailCall(Task task, Func func) { if (TryGetAnswer(task) is PendingQuestion pendingQuestion && @@ -115,31 +125,49 @@ namespace Capnp.Rpc } } + /// + /// Overload for tuple-typed tasks + /// public static Task MaybeTailCall(Task<(T1, T2)> task, Func func) { return MaybeTailCall(task, (ValueTuple t) => func(t.Item1, t.Item2)); } + /// + /// Overload for tuple-typed tasks + /// public static Task MaybeTailCall(Task<(T1, T2, T3)> task, Func func) { return MaybeTailCall(task, (ValueTuple t) => func(t.Item1, t.Item2, t.Item3)); } + /// + /// Overload for tuple-typed tasks + /// public static Task MaybeTailCall(Task<(T1, T2, T3, T4)> task, Func func) { return MaybeTailCall(task, (ValueTuple t) => func(t.Item1, t.Item2, t.Item3, t.Item4)); } + /// + /// Overload for tuple-typed tasks + /// public static Task MaybeTailCall(Task<(T1, T2, T3, T4, T5)> task, Func func) { return MaybeTailCall(task, (ValueTuple t) => func(t.Item1, t.Item2, t.Item3, t.Item4, t.Item5)); } + /// + /// Overload for tuple-typed tasks + /// public static Task MaybeTailCall(Task<(T1, T2, T3, T4, T5, T6)> task, Func func) { return MaybeTailCall(task, (ValueTuple t) => func(t.Item1, t.Item2, t.Item3, t.Item4, t.Item5, t.Item6)); } + /// + /// Overload for tuple-typed tasks + /// public static Task MaybeTailCall(Task<(T1, T2, T3, T4, T5, T6, T7)> task, Func func) { return MaybeTailCall(task, (ValueTuple t) => func(t.Item1, t.Item2, t.Item3, t.Item4, t.Item5, t.Item6, t.Item7)); diff --git a/Capnp.Net.Runtime/Rpc/InvalidCapabilityInterfaceException.cs b/Capnp.Net.Runtime/Rpc/InvalidCapabilityInterfaceException.cs index 7df17ca..2ce9466 100644 --- a/Capnp.Net.Runtime/Rpc/InvalidCapabilityInterfaceException.cs +++ b/Capnp.Net.Runtime/Rpc/InvalidCapabilityInterfaceException.cs @@ -7,10 +7,16 @@ /// public class InvalidCapabilityInterfaceException : System.Exception { + /// + /// Constructs an instance. + /// public InvalidCapabilityInterfaceException(string message) : base(message) { } + /// + /// Constructs an instance with message an inner exception. + /// public InvalidCapabilityInterfaceException(string message, System.Exception innerException) : base(message, innerException) { } diff --git a/Capnp.Net.Runtime/Rpc/MemberAccessPath.cs b/Capnp.Net.Runtime/Rpc/MemberAccessPath.cs index 00ca7b5..7b887c8 100644 --- a/Capnp.Net.Runtime/Rpc/MemberAccessPath.cs +++ b/Capnp.Net.Runtime/Rpc/MemberAccessPath.cs @@ -9,8 +9,16 @@ namespace Capnp.Rpc /// public class MemberAccessPath { + /// + /// Path to the bootstrap capability (which is an empty path) + /// public static readonly MemberAccessPath BootstrapAccess = new MemberAccessPath(new List()); + /// + /// Deserializes a MemberAccessPath from Cap'n Proto representation. + /// + /// Cap'n Proto representation + /// The MemberAccessPath public static MemberAccessPath Deserialize(PromisedAnswer.READER promisedAnswer) { var ops = new MemberAccess[promisedAnswer.Transform.Count]; @@ -55,6 +63,11 @@ namespace Capnp.Rpc /// public abstract class MemberAccess { + /// + /// Deserializes a MemberAccess instance from Cap'n Proto representation. + /// + /// Cap'n Proto representation + /// Deserialized instance public static MemberAccess Deserialize(PromisedAnswer.Op.READER op) { switch (op.which) diff --git a/Capnp.Net.Runtime/Rpc/PendingQuestion.cs b/Capnp.Net.Runtime/Rpc/PendingQuestion.cs index 68623e8..af32001 100644 --- a/Capnp.Net.Runtime/Rpc/PendingQuestion.cs +++ b/Capnp.Net.Runtime/Rpc/PendingQuestion.cs @@ -15,15 +15,47 @@ namespace Capnp.Rpc /// public sealed class PendingQuestion: IPromisedAnswer { + /// + /// Question lifetime management state + /// [Flags] public enum State { + /// + /// The question has not yet been sent. + /// None = 0, + + /// + /// Tail call flag + /// TailCall = 1, + + /// + /// The question has been sent. + /// Sent = 2, + + /// + /// The question has been answered. + /// Returned = 4, + + /// + /// A 'finish' request was sent to the peer, indicating that no further requests will refer + /// to this question. + /// FinishRequested = 8, + + /// + /// Question object was disposed. + /// Disposed = 16, + + /// + /// Question object was finalized by GC. + /// This flag should only be observable when debugging the finalizer itself. + /// 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; } + + /// + /// Eventually returns the server answer + /// public Task WhenReturned => _tcs.Task; + internal bool IsTailCall { get => StateFlags.HasFlag(State.TailCall); @@ -189,6 +226,13 @@ namespace Capnp.Rpc DeleteMyQuestion(); } + /// + /// Refer to a (possibly nested) member of this question's (possibly future) result and return + /// it as a capability. + /// + /// Access path + /// Low-level capability + /// The referenced member does not exist or does not resolve to a capability pointer. public ConsumedCapability Access(MemberAccessPath access) { lock (ReentrancyBlocker) @@ -296,11 +340,17 @@ namespace Capnp.Rpc ReleaseCaps(target, inParams); } + /// + /// Finalizer + /// ~PendingQuestion() { Dispose(false); } + /// + /// Implements . + /// public void Dispose() { Dispose(true); diff --git a/Capnp.Net.Runtime/Rpc/Proxy.cs b/Capnp.Net.Runtime/Rpc/Proxy.cs index 9e4380c..bd341ef 100644 --- a/Capnp.Net.Runtime/Rpc/Proxy.cs +++ b/Capnp.Net.Runtime/Rpc/Proxy.cs @@ -35,6 +35,9 @@ namespace Capnp.Rpc } } + /// + /// Underlying low-level capability + /// protected internal ConsumedCapability ConsumedCap { get; private set; } /// @@ -68,7 +71,7 @@ namespace Capnp.Rpc /// An answer promise /// This instance was disposed, or transport-layer stream was disposed. /// Capability is broken. - /// An I/O error occurs. + /// An I/O error occurs. 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; } + /// + /// Constructs a null instance. + /// public Proxy() { } @@ -135,6 +141,9 @@ namespace Capnp.Rpc } } + /// + /// Finalizer + /// ~Proxy() { #if DebugFinalizers diff --git a/Capnp.Net.Runtime/Rpc/RpcException.cs b/Capnp.Net.Runtime/Rpc/RpcException.cs index fdee0eb..9629cf9 100644 --- a/Capnp.Net.Runtime/Rpc/RpcException.cs +++ b/Capnp.Net.Runtime/Rpc/RpcException.cs @@ -5,10 +5,16 @@ /// public class RpcException : System.Exception { + /// + /// Constructs an instance. + /// public RpcException(string message) : base(message) { } + /// + /// Constructs an instance with message and inner exception. + /// public RpcException(string message, System.Exception innerException) : base(message, innerException) { } diff --git a/Capnp.Net.Runtime/Rpc/Skeleton.cs b/Capnp.Net.Runtime/Rpc/Skeleton.cs index a0de624..9bbc793 100644 --- a/Capnp.Net.Runtime/Rpc/Skeleton.cs +++ b/Capnp.Net.Runtime/Rpc/Skeleton.cs @@ -101,6 +101,9 @@ namespace Capnp.Rpc { } + /// + /// Finalizer + /// ~Skeleton() { Dispose(false); diff --git a/Capnp.Net.Runtime/Rpc/TcpRpcServer.cs b/Capnp.Net.Runtime/Rpc/TcpRpcServer.cs index 0eee043..54ceedf 100644 --- a/Capnp.Net.Runtime/Rpc/TcpRpcServer.cs +++ b/Capnp.Net.Runtime/Rpc/TcpRpcServer.cs @@ -14,12 +14,34 @@ namespace Capnp.Rpc /// public class TcpRpcServer: IDisposable { + /// + /// Models an incoming connection. + /// public interface IConnection { + /// + /// Server-side port + /// int LocalPort { get; } + + /// + /// Receive message counter + /// long RecvCount { get; } + + /// + /// Sent message counter + /// long SendCount { get; } + + /// + /// Whether the RPC engine is currently computing. + /// bool IsComputing { get; } + + /// + /// Whether the connection is idle, waiting for data to receive. + /// bool IsWaitingForData { get; } } diff --git a/Capnp.Net.Runtime/Rpc/rpc.cs b/Capnp.Net.Runtime/Rpc/rpc.cs index 35b0269..61139b0 100644 --- a/Capnp.Net.Runtime/Rpc/rpc.cs +++ b/Capnp.Net.Runtime/Rpc/rpc.cs @@ -1,3 +1,5 @@ +#pragma warning disable CS1591 + using Capnp; using Capnp.Rpc; using System; diff --git a/Capnp.Net.Runtime/SegmentSlice.cs b/Capnp.Net.Runtime/SegmentSlice.cs index 68e3e76..22f5c9d 100644 --- a/Capnp.Net.Runtime/SegmentSlice.cs +++ b/Capnp.Net.Runtime/SegmentSlice.cs @@ -7,7 +7,14 @@ namespace Capnp /// public struct SegmentSlice { + /// + /// Segment index + /// public uint SegmentIndex; + + /// + /// Word offset within segment + /// public int Offset; } } diff --git a/Capnp.Net.Runtime/SerializerState.cs b/Capnp.Net.Runtime/SerializerState.cs index c92fa9d..14c994d 100644 --- a/Capnp.Net.Runtime/SerializerState.cs +++ b/Capnp.Net.Runtime/SerializerState.cs @@ -406,9 +406,10 @@ namespace Capnp /// is null /// out of range /// - /// This state does neither describe a struct, nor a list of pointers - /// Another state is already linked to the specified position (sorry, no overwrite allowed) - /// This state and belong to different message builder, and is false + /// This state does neither describe a struct, nor a list of pointers + /// Another state is already linked to the specified position (sorry, no overwrite allowed) + /// This state and belong to different message builder, and is false + /// /// 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. /// capability index inside the capability table /// - /// This state does neither describe a struct, nor a list of pointers + /// This state does neither describe a struct, nor a list of pointers /// Another state is already linked to the specified position (sorry, no overwrite allowed) /// protected void LinkToCapability(int slot, uint capabilityIndex) @@ -706,8 +707,8 @@ namespace Capnp /// Number of bits to read /// Data bits which were read /// The object was not determined to be a struct - /// The data slice specified by and - /// is not completely within the struct's data section, misaligned, exceeds one word, or is negative + /// The data slice specified by and + /// is not completely within the struct's data section, misaligned, exceeds one word, or is negative public ulong StructReadData(ulong bitOffset, int count) { if (Kind != ObjectKind.Struct) @@ -818,6 +819,13 @@ namespace Capnp /// is out of bounds. public SerializerState TryGetPointer(int index) => TryGetPointer(index); + /// + /// Reads text from a struct field or list element. + /// + /// 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 + /// String to return in case of null + /// The decoded text public string ReadText(int index, string defaultText = null) { var b = BuildPointer(index); @@ -1260,7 +1268,7 @@ namespace Capnp /// /// Adds an entry to the capability table if the provided capability does not yet exist. /// - /// The capability, in one of the following forms: + /// The capability, in one of the following forms: /// Low-level capability object (Rpc.ConsumedCapability) /// Proxy object (Rpc.Proxy) /// Skeleton object (Rpc.Skeleton) @@ -1301,7 +1309,7 @@ namespace Capnp /// /// is out of range. /// - /// This state does neither describe a struct, nor a list of pointers + /// This state does neither describe a struct, nor a list of pointers /// Another state is already linked to the specified position (sorry, no overwrite allowed) /// public void LinkObject(int slot, T obj) @@ -1359,7 +1367,7 @@ namespace Capnp /// Index into this struct's pointer table. /// The proxy instance /// is out of range. - /// The desired interface does not qualify as capability interface ( + /// The desired interface does not qualify as capability interface () /// This state does not represent a struct. public T ReadCap(int slot) where T : class { diff --git a/Capnp.Net.Runtime/UtilityExtensions.cs b/Capnp.Net.Runtime/UtilityExtensions.cs index ac448cf..09d6a14 100644 --- a/Capnp.Net.Runtime/UtilityExtensions.cs +++ b/Capnp.Net.Runtime/UtilityExtensions.cs @@ -55,7 +55,6 @@ namespace Capnp /// This method exists until NET Standard 2.1 is released /// /// - /// /// #if NETSTANDARD2_0 public static bool ReplacementTaskIsCompletedSuccessfully(this Task task) diff --git a/Capnp.Net.Runtime/WirePointer.cs b/Capnp.Net.Runtime/WirePointer.cs index 9dfb8d0..9b41a67 100644 --- a/Capnp.Net.Runtime/WirePointer.cs +++ b/Capnp.Net.Runtime/WirePointer.cs @@ -5,13 +5,28 @@ using System.Text; namespace Capnp { /// - /// Pointer tag, + /// Pointer tag, see https://capnproto.org/encoding.html/> /// public enum PointerKind : byte { + /// + /// Struct pointer + /// Struct = 0, + + /// + /// List pointer + /// List = 1, + + /// + /// Far pointer + /// Far = 2, + + /// + /// Other (capability) pointer + /// Other = 3 }