From 7fa1acd3679561217b6b060fa57d24335f9d6f74 Mon Sep 17 00:00:00 2001 From: Bernard Normier Date: Mon, 13 Apr 2026 17:44:21 -0400 Subject: [PATCH 1/7] Fix Ice TODOs, update docs.zeroc.com references --- .../ice-definitions/struct-types.md | 2 +- .../icerpc/ice-protocol/protocol-frames.md | 153 ++++++++++++++---- content/icerpc/invocation/service-address.md | 2 +- content/slice/encoding/user-defined-types.md | 3 - 4 files changed, 120 insertions(+), 40 deletions(-) diff --git a/content/icerpc-for-ice-users/ice-definitions/struct-types.md b/content/icerpc-for-ice-users/ice-definitions/struct-types.md index 50abc6bf..7fce5f83 100644 --- a/content/icerpc-for-ice-users/ice-definitions/struct-types.md +++ b/content/icerpc-for-ice-users/ice-definitions/struct-types.md @@ -79,4 +79,4 @@ public readonly partial record struct Point [IceDecoder]: csharp:IceRpc.Ice.Codec.IceDecoder [IceEncoder]: csharp:IceRpc.Ice.Codec.IceEncoder -[cs-readonly]: TODO +[cs-readonly]: https://docs.zeroc.com/ice/3.8/csharp/slice-metadata-directives#SliceMetadataDirectives-cs:readonly diff --git a/content/icerpc/ice-protocol/protocol-frames.md b/content/icerpc/ice-protocol/protocol-frames.md index a3081b1a..1a31aa3b 100644 --- a/content/icerpc/ice-protocol/protocol-frames.md +++ b/content/icerpc/ice-protocol/protocol-frames.md @@ -6,7 +6,7 @@ description: Understand how requests and responses are sent over ice. ## Ice interop This section describes the ice protocol as implemented by IceRPC. The ice protocol as implemented by Ice is described -in the [Ice Manual][protocol-and-encoding], where it's known as version 1.0 of the Ice protocol. +in the [Ice Manual][ice-protocol], where it's known as version 1.0 of the Ice protocol. Both implementations are naturally compatible to allow Ice and IceRPC applications to communicate with each others. @@ -24,11 +24,32 @@ The ice protocol sends requests, responses and other information over a duplex c All ice protocol frames have the same layout: a header followed by a body. The format of the body depends on the frame type. -Frames and types from this page are defined using [Slice]. - -The header is a compact struct defined as follows: - -TODO: ice definitions +Frames and types from this page are defined using [Ice's interface definition language]. + +The header is an Ice struct defined as follows: + +```ice +enum FrameType +{ + Request = 0, + RequestBatch = 1, + Reply = 2, + ValidateConnection = 3, + CloseConnection = 4, +} + +struct HeaderData +{ + int magic; // always 0x49 0x63 0x65 0x50 i.e. "IceP". + byte protocolMajor; // always 1 + byte protocolMinor; // always 0 + byte encodingMajor; // always 1 + byte encodingMinor; // always 0 + FrameType frameType; + byte compressionStatus; + int frameSize; +} +``` The `compressionStatus` field is not used or supported by IceRPC. It must be set to 0. @@ -39,7 +60,29 @@ The `frameSize` represents the total number of bytes in the frame, including the A request frame carries an ice request. It consists of a header with the `Request` type followed by a `RequestData` body: -TODO: ice definitions +```ice +enum OperationMode { Normal = 0, Idempotent = 2 } + +struct Identity +{ + string name; + string category; +} + +sequence Facet; +dictionary Context; + +struct RequestData +{ + int requestId; + Identity id; + Facet facet; + string operation; + OperationMode mode; + Context context; + Encapsulation params; +} +``` A `requestId` with a value greater than 0 uniquely identifies a two-way request on a connection, and must not be reused while a response for this request is outstanding. The `requestId` 0 is reserved for one-way requests; a one-way request @@ -48,7 +91,7 @@ has no corresponding response. The `id` field corresponds to the path of the outgoing request's service address encoded as an [Ice identity](/icerpc-for-ice-users/rpc-core/ice-identity). -The `facet` field corresponds to the fragment of the outgoing request's service address encoded as a `Sequence`. +The `facet` field corresponds to the fragment of the outgoing request's service address encoded as a `sequence`. This sequence is empty when the fragment is empty; otherwise, it has a single element with the fragment. The `mode` encodes the value of the `Idempotent` [request field][request-fields]. The default is `Normal`. @@ -66,46 +109,78 @@ send batch requests and does not accept incoming batch request frames. A response frame carries an ice response. It consists of a header with the `Reply` type followed by a `ReplyData` body: -TODO: ice definitions +```ice +enum ReplyStatus +{ + Ok = 0, + UserException, + ObjectNotExist, + FacetNotExist, + OperationNotExist, + UnknownLocalException, + UnknownUserException, + UnknownException, + InvalidData, + Unauthorized +} + +struct ReplyData +{ + int requestId; + ReplyStatus replyStatus; + byte[...] replyPayload; // pseudo-Ice +} +``` The `requestId` field identifies the request associated with this response. The `replyStatus` encodes the response's [status code][status-code] as follows: -| Status code | Encoded as reply status | -| --------------------- | -------------------------- | -| Ok | Ok | -| ApplicationError | UserException | -| NotFound | ObjectNotExistException | -| NotImplemented | OperationNotExistException | -| Any other status code | UnknownException | +| Status code | Encoded as reply status | +| --------------------- | ------------------------| +| Ok | Ok | +| ApplicationError | UserException | +| NotFound | ObjectNotExist | +| NotImplemented | OperationNotExist | +| InvalidData | InvalidData | +| Unauthorized | Unauthorized | +| Any other status code | UnknownException | When IceRPC receives a response frame, it creates an incoming response with a status code decoded from the reply status: -| Reply status | Decoded as status code | -| -------------------------- | ---------------------- | -| Ok | Ok | -| UserException | ApplicationError | -| ObjectNotExistException | NotFound | -| FacetNotExistException | NotFound | -| OperationNotExistException | NotImplemented | -| Unknown exceptions | InternalError | +| Reply status | Decoded as status code | +| ------------------| ---------------------- | +| Ok | Ok | +| UserException | ApplicationError | +| ObjectNotExist | NotFound | +| FacetNotExist | NotFound | +| OperationNotExist | NotImplemented | +| InvalidData | InvalidData | +| Unauthorized | Unauthorized | +| All other values | InternalError | The format of the `replyPayload` depends on the reply status: -| Reply status | Format of the reply payload | -| ------------------- | --------------------------------------------------------------------- | -| Ok | An [encapsulation](#encapsulation) that holds the response's payload. | -| UserException | An [encapsulation](#encapsulation) that holds the response's payload. | -| NotExist exceptions | A `RequestFailedData` encoded with the Ice encoding. | -| Unknown exceptions | The response's error message encoded with the Ice encoding. | +| Reply status | Format of the reply payload | +| ----------------| --------------------------------------------------------------------- | +| Ok | An [encapsulation](#encapsulation) that holds the response's payload. | +| UserException | An [encapsulation](#encapsulation) that holds the response's payload. | +| NotExist values | A `RequestFailedData` encoded with the Ice encoding. | +| Other values | The response's error message encoded with the Ice encoding. | ### RequestFailedData `RequestFailedData` is a struct that holds the request's path, fragment and operation. The path is encoded as an -`Identity` and the fragment is encoded as a `Sequence`: +`Identity` and the fragment is encoded as a `sequence`: -TODO: ice definitions +```ice +struct RequestFailedData +{ + Identity path; + Facet facet; + string operation; +} +``` IceRPC always encodes the path, fragment and operation of the current incoming request in `RequestFailedData` when sending a response with status code `NotFound` or `NotImplemented` in an ice response frame. @@ -124,7 +199,15 @@ from the peer with these status codes. An encapsulation is a holder for a request or response payload. It holds the payload and encodes the payload size (as the encapsulation size, equal to the payload size plus 6) and an encoding version: -TODO: ice definitions +```ice +struct Encapsulation +{ + int size; // payload size + 6 + byte encodingMajor; // always 1 + byte encodingMinor; // always 1 + byte[...] payload; // pseudo-Ice +} +``` IceRPC does not know (and does not want to know) how a request or response payload is encoded. As far as IceRPC is concerned, the payload is just a stream of bytes. It's the user of IceRPC that knows how these payloads are encoded; a @@ -143,7 +226,7 @@ Ice encoding version 1.1. For the same reason, when IceRPC receives an encapsulation, it makes sure the encoding version in this encapsulation is set to 1.1. -[protocol-and-encoding]: https://doc.zeroc.com/ice/3.7/ice-protocol-and-encoding -[Slice]: /slice +[Ice's interface definition language]: https://docs.zeroc.com/ice/3.8/csharp/the-slice-language +[ice-protocol]: https://docs.zeroc.com/ice/3.8/cpp/ice-protocol [status-code]: ../invocation/incoming-response#status-code [request-fields]: ../invocation/outgoing-request#request-field diff --git a/content/icerpc/invocation/service-address.md b/content/icerpc/invocation/service-address.md index dde44374..b082de51 100644 --- a/content/icerpc/invocation/service-address.md +++ b/content/icerpc/invocation/service-address.md @@ -118,4 +118,4 @@ Relative service addresses underpin [relative proxies] in Slice. [URI]: https://en.wikipedia.org/wiki/Uniform_Resource_Identifier [ServiceAddress]: csharp:IceRpc.ServiceAddress -[Ice facet]: https://doc.zeroc.com/ice/latest/client-server-features/facets +[Ice facet]: https://docs.zeroc.com/ice/3.8/cpp/facets diff --git a/content/slice/encoding/user-defined-types.md b/content/slice/encoding/user-defined-types.md index 9af99736..08a7f6ba 100644 --- a/content/slice/encoding/user-defined-types.md +++ b/content/slice/encoding/user-defined-types.md @@ -167,6 +167,3 @@ The contact id = 5, name = not set, age = 42 is encoded as: ``` [bit-sequence]: encoding-only-constructs#bit-sequence -[ice-manual-class-encoding]: https://doc.zeroc.com/ice/3.7/ice-protocol-and-encoding/ice-encoding/data-encoding-for-classes -[sliced-format-attribute]: /slice/language-guide/operation#slicedformat-attribute -[variable-length size]: encoding-only-constructs#variable-length-size From 3ac7a30d696c27ea94c188ef5a027a426fc57f63 Mon Sep 17 00:00:00 2001 From: Bernard Normier Date: Mon, 13 Apr 2026 17:47:29 -0400 Subject: [PATCH 2/7] Small fix --- content/icerpc/ice-protocol/protocol-frames.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content/icerpc/ice-protocol/protocol-frames.md b/content/icerpc/ice-protocol/protocol-frames.md index 1a31aa3b..ade45742 100644 --- a/content/icerpc/ice-protocol/protocol-frames.md +++ b/content/icerpc/ice-protocol/protocol-frames.md @@ -24,7 +24,7 @@ The ice protocol sends requests, responses and other information over a duplex c All ice protocol frames have the same layout: a header followed by a body. The format of the body depends on the frame type. -Frames and types from this page are defined using [Ice's interface definition language]. +Frames and types from this page are defined using [Ice's interface definition language][ice-slice]. The header is an Ice struct defined as follows: @@ -226,7 +226,7 @@ Ice encoding version 1.1. For the same reason, when IceRPC receives an encapsulation, it makes sure the encoding version in this encapsulation is set to 1.1. -[Ice's interface definition language]: https://docs.zeroc.com/ice/3.8/csharp/the-slice-language [ice-protocol]: https://docs.zeroc.com/ice/3.8/cpp/ice-protocol +[ice-slice]: https://docs.zeroc.com/ice/3.8/csharp/the-slice-language [status-code]: ../invocation/incoming-response#status-code [request-fields]: ../invocation/outgoing-request#request-field From 360c24c97c3aade6877f93d1802854b67410ee38 Mon Sep 17 00:00:00 2001 From: Bernard Normier Date: Tue, 14 Apr 2026 08:55:07 -0400 Subject: [PATCH 3/7] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- content/icerpc/ice-protocol/protocol-frames.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/icerpc/ice-protocol/protocol-frames.md b/content/icerpc/ice-protocol/protocol-frames.md index ade45742..1b176084 100644 --- a/content/icerpc/ice-protocol/protocol-frames.md +++ b/content/icerpc/ice-protocol/protocol-frames.md @@ -40,7 +40,7 @@ enum FrameType struct HeaderData { - int magic; // always 0x49 0x63 0x65 0x50 i.e. "IceP". + int magic; // always the bytes 0x49 0x63 0x65 0x50 ("IceP"), i.e. 0x50656349 in little-endian. byte protocolMajor; // always 1 byte protocolMinor; // always 0 byte encodingMajor; // always 1 From 1ff9c095b87834f5e1ee04155c5b892cc36de021 Mon Sep 17 00:00:00 2001 From: Bernard Normier Date: Tue, 14 Apr 2026 09:15:25 -0400 Subject: [PATCH 4/7] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- content/icerpc/ice-protocol/protocol-frames.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/content/icerpc/ice-protocol/protocol-frames.md b/content/icerpc/ice-protocol/protocol-frames.md index 1b176084..e9ec4970 100644 --- a/content/icerpc/ice-protocol/protocol-frames.md +++ b/content/icerpc/ice-protocol/protocol-frames.md @@ -161,12 +161,12 @@ When IceRPC receives a response frame, it creates an incoming response with a st The format of the `replyPayload` depends on the reply status: -| Reply status | Format of the reply payload | -| ----------------| --------------------------------------------------------------------- | -| Ok | An [encapsulation](#encapsulation) that holds the response's payload. | -| UserException | An [encapsulation](#encapsulation) that holds the response's payload. | -| NotExist values | A `RequestFailedData` encoded with the Ice encoding. | -| Other values | The response's error message encoded with the Ice encoding. | +| Reply status | Format of the reply payload | +| ----------------------------| --------------------------------------------------------------------- | +| Ok | An [encapsulation](#encapsulation) that holds the response's payload. | +| UserException | An [encapsulation](#encapsulation) that holds the response's payload. | +| Any *NotExist* reply status | A `RequestFailedData` encoded with the Ice encoding. | +| Other values | The response's error message encoded with the Ice encoding. | ### RequestFailedData From 3ae58d2309deb99aba731b6416d9c6daa7566530 Mon Sep 17 00:00:00 2001 From: Bernard Normier Date: Tue, 14 Apr 2026 09:18:10 -0400 Subject: [PATCH 5/7] Fix more review comments --- .../icerpc-for-ice-users/ice-definitions/struct-types.md | 3 ++- content/icerpc/ice-protocol/protocol-frames.md | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/content/icerpc-for-ice-users/ice-definitions/struct-types.md b/content/icerpc-for-ice-users/ice-definitions/struct-types.md index 7fce5f83..4c85386c 100644 --- a/content/icerpc-for-ice-users/ice-definitions/struct-types.md +++ b/content/icerpc-for-ice-users/ice-definitions/struct-types.md @@ -52,7 +52,8 @@ encodes the struct fields with an [IceEncoder]. ## cs:readonly metadata directive -You can map an Ice struct to a readonly C# struct with the `"cs:readonly"`[cs-readonly] metadata directive. For example: +You can map an Ice struct to a readonly C# struct with the [`"cs:readonly"`][cs-readonly] metadata directive. For +example: {% aside alignment="top" %} diff --git a/content/icerpc/ice-protocol/protocol-frames.md b/content/icerpc/ice-protocol/protocol-frames.md index e9ec4970..d0b1df05 100644 --- a/content/icerpc/ice-protocol/protocol-frames.md +++ b/content/icerpc/ice-protocol/protocol-frames.md @@ -8,7 +8,7 @@ description: Understand how requests and responses are sent over ice. This section describes the ice protocol as implemented by IceRPC. The ice protocol as implemented by Ice is described in the [Ice Manual][ice-protocol], where it's known as version 1.0 of the Ice protocol. -Both implementations are naturally compatible to allow Ice and IceRPC applications to communicate with each others. +Both implementations are naturally compatible to allow Ice and IceRPC applications to communicate with each other. The ice protocol implementation provided by IceRPC does not support a few non-essential features that Ice supports, namely: @@ -162,10 +162,10 @@ When IceRPC receives a response frame, it creates an incoming response with a st The format of the `replyPayload` depends on the reply status: | Reply status | Format of the reply payload | -| ----------------------------| --------------------------------------------------------------------- | +| ---------------------------- | --------------------------------------------------------------------- | | Ok | An [encapsulation](#encapsulation) that holds the response's payload. | | UserException | An [encapsulation](#encapsulation) that holds the response's payload. | -| Any *NotExist* reply status | A `RequestFailedData` encoded with the Ice encoding. | +| Any *NotExist* reply status | A `RequestFailedData` encoded with the Ice encoding. | | Other values | The response's error message encoded with the Ice encoding. | ### RequestFailedData From 64d9ad70ddf29037f8c5a8e01c2a6116468f819d Mon Sep 17 00:00:00 2001 From: Bernard Normier Date: Tue, 14 Apr 2026 09:35:35 -0400 Subject: [PATCH 6/7] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- content/icerpc/ice-protocol/protocol-frames.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content/icerpc/ice-protocol/protocol-frames.md b/content/icerpc/ice-protocol/protocol-frames.md index d0b1df05..8e894f06 100644 --- a/content/icerpc/ice-protocol/protocol-frames.md +++ b/content/icerpc/ice-protocol/protocol-frames.md @@ -137,7 +137,7 @@ The `requestId` field identifies the request associated with this response. The `replyStatus` encodes the response's [status code][status-code] as follows: | Status code | Encoded as reply status | -| --------------------- | ------------------------| +| --------------------- | ------------------------ | | Ok | Ok | | ApplicationError | UserException | | NotFound | ObjectNotExist | @@ -149,7 +149,7 @@ The `replyStatus` encodes the response's [status code][status-code] as follows: When IceRPC receives a response frame, it creates an incoming response with a status code decoded from the reply status: | Reply status | Decoded as status code | -| ------------------| ---------------------- | +| ------------------ | ---------------------- | | Ok | Ok | | UserException | ApplicationError | | ObjectNotExist | NotFound | From e0ecf80c7a78fbe2e6b143daec05e9b632724530 Mon Sep 17 00:00:00 2001 From: Bernard Normier Date: Tue, 14 Apr 2026 09:38:47 -0400 Subject: [PATCH 7/7] Fix tables --- content/icerpc/ice-protocol/protocol-frames.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content/icerpc/ice-protocol/protocol-frames.md b/content/icerpc/ice-protocol/protocol-frames.md index 8e894f06..fe6e69c0 100644 --- a/content/icerpc/ice-protocol/protocol-frames.md +++ b/content/icerpc/ice-protocol/protocol-frames.md @@ -137,7 +137,7 @@ The `requestId` field identifies the request associated with this response. The `replyStatus` encodes the response's [status code][status-code] as follows: | Status code | Encoded as reply status | -| --------------------- | ------------------------ | +| --------------------- | ----------------------- | | Ok | Ok | | ApplicationError | UserException | | NotFound | ObjectNotExist | @@ -149,7 +149,7 @@ The `replyStatus` encodes the response's [status code][status-code] as follows: When IceRPC receives a response frame, it creates an incoming response with a status code decoded from the reply status: | Reply status | Decoded as status code | -| ------------------ | ---------------------- | +| ----------------- | ---------------------- | | Ok | Ok | | UserException | ApplicationError | | ObjectNotExist | NotFound |