DDS-XRCE 1.0 — Spec Coverage
Source: internal/standards/cache/omg/dds-xrce-1.0.pdf (166 pages, OMG formal/2020-02-01) —
OMG DDS-XRCE 1.0
Item-by-item audit against the PDF according to
internal/spec-coverage/PROCESS.md. Page numbers are PDF pages (PDF page =
printed page + 8). Every field of the types of §7.7 and Annex A, every
submessage with its flags and payload, every check and every return value of
the operations of §7.8, every rule of the reliable streams, every row of
Table 5, Table 6 and Table 15 and every transport mapping is an item of its
own. done stands only where code and test cover the requirement; a test
citation names the test function as file::module::name. A repository
citation names file, symbol and, where it helps, the line (l.); the lines refer
to the state with which this file was checked in. Every statement about
behaviour is read from the code; the cited tests ran on the Linux test host,
this audit runs none. Where code carries a requirement but no test checks it,
the item is partial and the note names the missing test.
Context: DDS-XRCE is spread over these parts of ZeroDDS:
crates/xrce/· docs.rs — the message codec (MessageHeader,Submessage, the 16 payloads), the types of §7.7 (ObjectId,ObjectVariant,ResultStatus,ObjectInfo,SampleInfo,TransportLocator),CLIENT_RepresentationandAGENT_Representation(handshake), reliable streams (reliable), fragmentation (fragment), continuous reading (continuous_read), the object store per client (object_store), transports for UDP, TCP and a serial line (transport_*), DTLS and TLS behind the featuresdtlsandtls, a generator of CREATE messages from an XML file (xml_config).crates/xrce-agent/· docs.rs —XrceAgent(client registry, object stores, sample queue per reader); behind the featuredaemonthe session logic (daemon::session::SessionEngine), the reading of representations (daemon::entity_repr), profiles (daemon::profiles), the connection tozerodds-dcps(daemon::dcps_bridge::RealDdsPort), listeners for UDP, TCP and serial (daemon::transport), discovery (daemon::discovery) and the binaryzerodds-xrce-agentd.crates/xrce-client/· docs.rs —XrceClient, a synchronous client over the traitClientTransport.crates/endpoint-e2e/tests/xrce_write_framing.rs— checks the WRITE_DATA frames of the endpoint SDKs of further languages against the codec ofcrates/xrce.
The specification defines no programming interface of the client (§8.1, p. 57: “Do not have a standard API”). The endpoint SDKs of the languages are therefore not listed as items; the ZeroDDS C API has no functions for XRCE.
Several structures have different forms in §7/§8 and in Annex A
(CLIENT_Representation, SampleInfo, the binary forms of the objects and
others). The item names the form the code follows; the form of the other place
is an item of its own. Where the code follows the form eProsima Micro-XRCE-DDS
3.0.1 sends, this rests on the capture under
tools/wire-capture/xrce-sessions/; a run against an eProsima agent or client
is not part of this audit.
The specification names dds_xrce_types.idl and dds_xrce_model.xmi as
normative machine-readable files (p. 1). They are not in the cache; a
comparison with them is missing.
Open items: none.
§1 Scope
§1 Scope
Spec: §1, p. 11 — “This specification defines an XRCE Protocol between a resource constrained, low-powered device (client) and an Agent (the server). […] The specification’s purpose and scope are to ensure that applications based on different vendors’ implementations of the XRCE Protocol and XRCE Agent are compatible and interoperable.”
Repo: —
Tests: —
Status: n/a (informative) — overview; protocol and agent are listed
item by item from §7 on.
§2 Conformance
§2 Ten profiles as conformance points
Spec: §2, p. 12 — “This specification defines ten profiles. Each constitutes a separate conformance point”.
Repo: —
Tests: —
Status: n/a (informative) — mapping; whether a profile is met follows
from the status of the mapped items. The tests in
crates/xrce/tests/profile_conformance.rs only check that the values of
SubmessageId decode; they show no behaviour.
§2 Read Access profile
Spec: §2, p. 12 — “Provides the clients the ability to read data on pre-configured Topics with pre-configured QoS policies. Requires implementation of all submessage types except for CREATE, INFO, WRITE_DATA, and DELETE, including the associated behaviors.”
Repo: —
Tests: —
Status: n/a (informative) — mapping: items on §8.3.5 (all submessages
except CREATE, INFO, WRITE_DATA, DELETE), §7.8.5, §8.4.3, §8.4.14. GET_INFO
without a session and InfoMask (ca0cf7e08bf), the DATA formats (fd5253ca805),
MAX_SAMPLES_ZERO (8bcb1d00161) and pre-configured DataReaders (2ba972cd270)
are carried in those items.
§2 Write Access profile
Spec: §2, p. 12 — “Provides the clients the ability to write data on pre-configured Topics with pre-configured QoS policies. Requires implementation of all submessage types except for CREATE, INFO, READ_DATA, DATA, and DELETE, including the associated behaviors.”
Repo: —
Tests: —
Status: n/a (informative) — mapping: items on §8.3.5, §7.8.4, §8.4.2,
§8.4.14. STATUS on WRITE_DATA (869304e6b63), the sequence formats of WRITE_DATA
(f40bd568ad1) and pre-configured DataWriters (2ba972cd270) are carried in those
items.
§2 Configure Entities profile
Spec: §2, p. 12 — “Provides the clients the ability define DomainParticipant, Topic, Publisher, Subscriber, DataWriter, and DataReader entities using pre-configured QoS policies and data-types. Requires implementation of the CREATE_CLIENT, DELETE_CLIENT, CREATE, and DELETE submessage and the associated behaviors.”
Repo: —
Tests: —
Status: n/a (informative) — mapping: items on §7.8.2, §7.8.3, §7.7.3 and
Table 6. Table 10 has no DELETE_CLIENT submessage; delete_client runs over
DELETE (§8.3.5.4). The participant check for Publisher and Subscriber
(505c2e56d24) and the DDS-XML forms of the representations (9d5c64dc398,
b97657ef4ec) are carried in those items.
§2 Configure QoS profile
Spec: §2, p. 12 — “Provides client the ability to define QoS profiles to be used by DDS entities. Requires implementation of the CREATE submessage and the associated behaviors for object kind OBJK_QOSPROFILE.”
Repo: —
Tests: —
Status: n/a (informative) — mapping: items on §7.7.3.2, Table 6
OBJK_QOSPROFILE and §8.4.7. The DDS-XML form of the QosProfile is implemented
(9d5c64dc398, b97657ef4ec); which policies the agent applies is in the items on
§7.1.
§2 Configure types profile
Spec: §2, p. 12 — “Provides client the ability to explicitly define data types to be used for DDS Topics. Requires implementation of the CREATE submessage and the associated behaviors for object kind OBJK_TYPE.”
Repo: —
Tests: —
Status: n/a (informative) — mapping: items on §7.7.3.3, Table 6 OBJK_TYPE
and §8.4.8. A <types> that refers to types the agent already knows
(§7.7.3.3.2) is done there.
§2 Discovery access profile
Spec: §2, p. 12 — “Provides the clients the ability to discover the Topics and Types available on the DDS Global Data Space. Requires implementation of the GET_INFO and INFO submessage and the associated behaviors.”
Repo: —
Tests: —
Status: n/a (informative) — mapping: items on §7.8.2.2, §7.8.3.3,
§8.3.5.3, §8.3.5.7 and §7.7.13. GET_INFO returns the agent (also without a
session), the objects of the client and the objects configured for it
(ca0cf7e08bf, 2ba972cd270). The agent has no query for the Topics and Types of
the Global Data Space; session.rs, dds_port.rs and dcps_bridge.rs hold no
code for it.
§2 File based configuration profile
Spec: §2, p. 12 — “Provides a standard way to configure the Agent using XML files. Requires implementation of the file-based configuration mechanism described in clause 9.3”.
Repo: —
Tests: —
Status: n/a (informative) — mapping: items on §9.3 and Table 15.
§2 UDP Transport profile
Spec: §2, p. 12 — “Implements the mapping of the protocol to the UDP transport. Requires implementing the mechanisms described in clause 11.2 (UDP Transport).”
Repo: —
Tests: —
Status: n/a (informative) — mapping: items on §11.2.
§2 TCP Transport profile
Spec: §2, p. 12 — “Implements the mapping of the protocol to the TCP transport. Requires implementing the mechanisms described in clause 11.3 (TCP Transport).”
Repo: —
Tests: —
Status: n/a (informative) — mapping: items on §11.3.
§2 Complete profile
Spec: §2, p. 12 — “Complete profile. Requires implementation of the complete specification.”
Repo: —
Tests: —
Status: n/a (informative) — mapping: all items of this document.
§3 References
§3.1 [IETF RFC-1982] Serial Number Arithmetic
Spec: §3.1, p. 13 — “[IETF RFC-1982] Serial Number Arithmetic.”
Repo: —
Tests: —
Status: n/a (informative) — reference; the requirement is in the item on
§8.3.2.3.
§3.1 [IDL] IDL 4.2
Spec: §3.1, p. 13 — “[IDL] Interface Definition Language (IDL), version 4.2”.
Repo: —
Tests: —
Status: n/a (informative) — reference; the types of Annex A are written
in IDL and listed as items on §7.7 and Annex A.
§3.1 [DDS] DDS 1.4
Spec: §3.1, p. 13 — “[DDS] Data Distribution Service for Real-Time Systems Specification, version 1.4”.
Repo: —
Tests: —
Status: n/a (informative) — reference; DDS entities in the items on
Table 6, the filter syntax in the item on Table 9.
§3.1 [DDS-XML] DDS Consolidated XML Syntax 1.0
Spec: §3.1, p. 13 — “[DDS-XML] DDS Consolidated XML Syntax, version 1.0”.
Repo: —
Tests: —
Status: n/a (informative) — reference; the XML forms in the items on
§7.7.3 and §9.3.
§3.1 [DDS-XTYPES] XTypes 1.2
Spec: §3.1, p. 13 — “[DDS-XTYPES] Extensible And Dynamic Topic Types for DDS, version 1.2”.
Repo: —
Tests: —
Status: n/a (informative) — reference; XCDR2 in the item on §7.7.
§3.1 [UML] 2.5
Spec: §3.1, p. 13 — “[UML] Unified Modeling Language, version 2.5”.
Repo: —
Tests: —
Status: n/a (informative) — reference for the diagrams.
§3.1 [UDP] RFC 768
Spec: §3.1, p. 13 — “[UDP] User Datagram Protocol, IETF RFC 768”.
Repo: —
Tests: —
Status: n/a (informative) — reference; the mapping in the items on
§11.2.
§3.1 [TCP] RFC 793
Spec: §3.1, p. 13 — “[TCP] Transmission Control Protocol, STD 7, IETF RFC 793”.
Repo: —
Tests: —
Status: n/a (informative) — reference; the mapping in the items on
§11.3.
§3.1 [DTLS] RFC 6347
Spec: §3.1, p. 13 — “[DTLS] Datagram Transport Layer Security, version 1.2, IETF RFC 6347”.
Repo: —
Tests: —
Status: n/a (informative) — reference; the specification names DTLS in
§11.2 (p. 99) as an option. crates/xrce/src/transport_dtls.rs (feature
dtls) is named in the item on §11.2.
§3.1 [TLS] RFC 5246
Spec: §3.1, p. 13 — “[TLS] The Transport Layer Security (TLS) Protocol, version 1.2, IETF RFC 5246”.
Repo: —
Tests: —
Status: n/a (informative) — reference; the specification names TLS in
§11.3 (p. 100–101) as an option. crates/xrce/src/transport_tls.rs (feature
tls) is named in the item on §11.3.
§3.1 [IETF RFC-1662] PPP in HDLC-like Framing
Spec: §3.1, p. 13 — “[IETF RFC-1662] PPP in HDLC-like Framing.”
Repo: —
Tests: —
Status: n/a (informative) — reference; the framing in the items on
Annex C.
§3.2 [SMART] Smart Transducers 1.0
Spec: §3.2, p. 13 — “[SMART] Smart Transducers Specification, version 1.0”.
Repo: —
Tests: —
Status: n/a (informative) — non-normative reference.
§4 Terms and Definitions
§4 Terms
Spec: §4, p. 14 — definitions of “Data Distribution Service (DDS)”, “DDS Domain”, “DDS DomainParticipant”, “DDS Global Data Space”, “GUID”.
Repo: —
Tests: —
Status: n/a (informative) — terms.
§5 Symbols
§5 Acronyms
Spec: §5, p. 15 — DDS, IDL, RTPS, XRCE.
Repo: —
Tests: —
Status: n/a (informative) — acronyms.
§6 Additional Information
§6.1 Changes to Adopted OMG Specifications
Spec: §6.1, p. 16 — “This specification does not change any adopted OMG specification.”
Repo: —
Tests: —
Status: n/a (informative) — note.
§6.2 Acknowledgements
Spec: §6.2, p. 16 — submitting companies (Real-Time Innovations, eProsima, TwinOaks Computing).
Repo: —
Tests: —
Status: n/a (informative) — acknowledgement.
§7.1 General
§7.1 The agent is a DDS participant
Spec: §7.1, p. 17 — “The XRCE Agent is a DDS Participant in the DDS Global Data Space. The DDS-XRCE protocol allows the client to use the XRCE Agent as a proxy in order to produce and consume data in the DDS Global Data Space.”
Repo: crates/xrce-agent/src/daemon/dcps_bridge.rs (RealDdsPort,
runtime_for: one DcpsRuntime per domain)
Tests: crates/xrce-agent/tests/e2e_udp_loopback.rs::e2e_udp_loopback_keyed_dispose_reliable_besteffort_and_fragments
Status: done — the test writes and reads through a DomainParticipant of
zerodds-dcps with no XRCE on the other side.
§7.1 UML model of the agent
Spec: §7.1, p. 17 — “this specification defines a UML model for the XRCE Agent. This model, called the DDS-XRCE Object Model, defines the objects, interfaces, and operations to be implemented by the agent.”
Repo: —
Tests: —
Status: n/a (informative) — mapping; the objects are in the items on
§7.4 to §7.6, the operations in §7.8.
§7.1 Every topic with every QoS
Spec: §7.1, p. 17 — “Despite being simpler, the DDS-XRCE Object Model provides XRCE clients complete access to the DDS Global Data space. Any DDS Topic may be published or subscribed to on any DDS with any QoS.”
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (apply_qos_profile, qos_policy, TopicQos, participant_qos_of); crates/xrce-agent/src/daemon/dcps_bridge.rs (create_writer, create_reader, create_participant_with)
Tests: crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_qos_of_a_topic_is_the_default_of_its_endpoints, crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_qos_of_an_xml_participant_is_applied, crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_participant_qos_profile_reference_is_applied, crates/xrce-agent/src/daemon/dcps_bridge.rs::tests::a_participant_qos_is_applied_to_the_participant
Status: done — every policy the DDS entity has is applied: on an endpoint RELIABILITY, DURABILITY, DURABILITY_SERVICE, HISTORY, DEADLINE, LATENCY_BUDGET, LIFESPAN, LIVELINESS, OWNERSHIP, OWNERSHIP_STRENGTH, DESTINATION_ORDER, TRANSPORT_PRIORITY, TIME_BASED_FILTER, PARTITION, USER_DATA, TOPIC_DATA, RESOURCE_LIMITS; on a Publisher and Subscriber PARTITION, GROUP_DATA, PRESENTATION, ENTITY_FACTORY; on a Topic as the default of its endpoints (TopicQos); on a DomainParticipant USER_DATA (a runtime of its own) and ENTITY_FACTORY, from the qos_profile_reference of the binary form and from <domain_participant_qos> of the XML form (0b67c04800c, 3906abf91b8). What the runtime cannot do is not accepted and ignored: STATUS_ERR_INCOMPATIBLE, unless unsupported_qos: ignore (a setting for the profile files of other vendors).
### §7.1 QoS the agent cannot apply
Spec: §7.1, p. 17 — as above.
Repo: crates/xrce-agent/src/daemon/session.rs (plan_not_applied, create_core); crates/xrce-agent/src/daemon/entity_repr.rs (apply_qos_profile); crates/xrce-agent/src/daemon/config.rs (unsupported_qos)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::qos_the_agent_cannot_apply_is_refused_unless_ignoring_is_named, crates/xrce-agent/src/daemon/config.rs::tests::unsupported_qos_is_refused_unless_ignoring_is_named
Status: done — a QoS the agent cannot apply (WRITER_DATA_LIFECYCLE with autodispose off, READER_DATA_LIFECYCLE with an autopurge delay, an element of a vendor dialect) makes the CREATE STATUS_ERR_INCOMPATIBLE; nothing is stored. unsupported_qos: ignore creates the object without it and reports what is missing (SessionEvent::RepresentationNotApplied). A policy without meaning for the kind of endpoint (a TIME_BASED_FILTER of a writer) is not part of its QoS and is not reported. 3906abf91b8.
§7.2 XRCE Client
§7.2 Reasons for an object model of its own
Spec: §7.2, p. 18 — three reasons: (1) “These clients expect a simplified interface with no callbacks, and use parameters encoded in text.” (2) “The DDS-XRCE DDS Object Model must overcome intermittent connectivity by introducing a ‘session,’ which can exist across repeated sleep-wakeup cycles by a device.” (3) “it is desirable to have an access control model that authenticates each client application/principal”.
Repo: —
Tests: —
Status: n/a (informative) — rationale. The session is in the items on
§8.2.2 and §7.8.2.1, access control in the item on §7.4 AccessController.
§7.2 Kinds of clients
Spec: §7.2, p. 19 — simple devices without discovery, devices that activate and deactivate “data push”, clients that create objects themselves, and clients that use sequence numbers and timestamps.
Repo: —
Tests: —
Status: n/a (informative) — description; switching delivery on and off is
in the item on Table 9 max_samples.
§7.3 XRCE Agent
§7.3 Presence of the client in the DDS data space
Spec: §7.3, p. 19 — “The purpose of the DDS-XRCE Agent (XRCE Agent) is to establish and maintain the presence of the XRCE Client in the DDS data-space.”
Repo: crates/xrce-agent/src/daemon/session.rs (SessionEngine,
apply_dds_create); crates/xrce-agent/src/daemon/dcps_bridge.rs
(RealDdsPort::create_writer, create_reader)
Tests: crates/xrce-agent/tests/e2e_udp_loopback.rs::e2e_udp_loopback_keyed_dispose_reliable_besteffort_and_fragments
Status: done
§7.3 Pre-configured and client-created resources
Spec: §7.3, p. 19 — “Resources may be preconfigured with well-known names, or dynamically created by an XRCE Client.”
Repo: crates/xrce-agent/src/daemon/profiles.rs
(AgentProfiles::predefined_objects);
crates/xrce-agent/src/daemon/definitions.rs (SystemDefinitions);
crates/xrce-agent/src/daemon/session.rs (SessionEngine::ensure_predefined,
make_client_applications); crates/xrce-agent/src/daemon/config.rs (keys
xml_profile_files, client_applications)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::references_resolve_against_the_profile_files,
crates/xrce-agent/src/daemon/session.rs::tests::a_client_writes_through_a_preconfigured_data_writer_without_a_create,
crates/xrce-agent/src/daemon/session.rs::tests::a_create_client_makes_the_objects_configured_for_the_client,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_reference_is_read_like_the_profile_it_names
Status: done — resources created by the client: CREATE. Configured
resources: the files of §9.3 (<types>, <qos_library>, <domain_library>,
<domain_participant_library>, <application_library>) from
xml_profile_files: are provided under the ObjectId from the MD5 of their name
(468aa0940da, 452ffeb7f84, 9d5c64dc398, 2ba972cd270).
§7.3 Writing through a pre-configured resource without CREATE
Spec: §7.3, p. 19 — “a Client that has access to this resource can write data using this resource simply by referring to the existing ‘MySquareWriter’. The Client does not have to create a resource.”
Repo: crates/xrce-agent/src/daemon/session.rs
(SessionEngine::ensure_predefined, called from handle_write_data,
handle_read_data, handle_get_info and handle_create)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_client_writes_through_a_preconfigured_data_writer_without_a_create,
crates/xrce-agent/src/daemon/session.rs::tests::a_client_reads_through_a_preconfigured_data_reader_without_a_create,
crates/xrce-agent/src/daemon/session.rs::tests::a_preconfigured_object_is_made_only_for_a_client_allowed_to_create_it
Status: done — WRITE_DATA on the ObjectId of a configured DataWriter makes
the DomainParticipant with everything inside it for the client (2ba972cd270);
the access rules apply. An ObjectId with no configuration gives
STATUS_ERR_UNKNOWN_REFERENCE.
§7.3 Queries by the client
Spec: §7.3, p. 19 — “This specification enables Clients to be in charge of when data is received, and to request the XRCE Agent to return data that matches a set of constraints. […] an XRCE Client queries the XRCE Agent when it wakes up.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_read_data,
pump_read); crates/xrce-agent/src/lib.rs (XrceAgent::pull_sample)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::read_data_elapsed_time_is_measured_from_the_real_request_time,
crates/xrce-agent/src/lib.rs::tests::after_submit_pull_returns_sample_in_fifo_order
Status: done
§7.3 DDS-RTPS towards the other participants
Spec: §7.3, p. 20 — “the standard interactions occurring with the XRCE Client use the DDS-XRCE protocol, while interactions with other DDS domain participants use the DDS-RTPS protocol.”
Repo: crates/xrce-agent/src/daemon/dcps_bridge.rs (RealDdsPort)
Tests: crates/xrce-agent/tests/e2e_udp_loopback.rs::e2e_udp_loopback_keyed_dispose_reliable_besteffort_and_fragments
Status: done
§7.3 Shared or dedicated DDS entities
Spec: §7.3, p. 19 — “a resource ‘MySquareWriter’ may be associated with a DDS DataWriter shared by many DDS-XRCE clients, or an XRCE Client may have its own dedicated ‘MySquareWriter’”.
Repo: —
Tests: —
Status: n/a (informative) — implementation freedom; the duty to behave
“as if” is in the item on §10.3.
§7.4 Model Overview
§7.4 Root as singleton and factory
Spec: §7.4, p. 21 — “The Root singleton is the entry point for the service. It functions as a factory for all the Objects managed by the XRCE Agent.”
Repo: crates/xrce-agent/src/daemon/session.rs (SessionEngine);
crates/xrce-agent/src/lib.rs (XrceAgent)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::create_client_happy_path_registers_and_replies_ok
Status: done
§7.4 ProxyClient
Spec: §7.4, p. 21 — “The ProxyClient class models the XRCE Client application that interacts with the XRCE Agent using the XRCE protocol.”
Repo: crates/xrce-agent/src/lib.rs (XrceAgent::register_client, one
ObjectStore per ClientKey)
Tests: crates/xrce-agent/src/lib.rs::tests::multiple_clients_isolated
Status: done
§7.4 An application belongs to one ProxyClient
Spec: §7.4, p. 21 — “Each Application object is associated with a single XRCE ProxyClient and gets its access rights from those assigned to the XRCE Client.”
Repo: crates/xrce-agent/src/lib.rs (XrceAgent::create_object);
crates/xrce-agent/src/daemon/access.rs (AccessController::permits, rules per
ClientKey, ObjectKind application); crates/xrce-agent/src/daemon/session.rs
(SessionEngine::permit)
Tests: crates/xrce-agent/src/lib.rs::tests::create_application_object_via_objk_application,
crates/xrce-agent/src/lib.rs::tests::multiple_clients_isolated,
crates/xrce-agent/src/daemon/session.rs::tests::create_without_permission_is_denied_and_stores_nothing
Status: done — an Application is held in the object store of its client;
its rights are the client’s rules in the AccessController (1c430db8a67,
5f7a8652d95). Read from the code: the check takes the ClientKey and the
ObjectKind of the object; no test has an Application as the refused object.
§7.4 Application with DomainParticipants
Spec: §7.4, p. 21 — “The Application class models a software application that connects with the XRCE Client and manages the DDS objects needed to publish and subscribe data on one or more DDS Domains. An XRCE Application can be associated with zero of more DomainParticipant objects.”
Repo: crates/xrce-agent/src/daemon/session.rs (plan_dds_create returns
DdsCreate::Application, create_nested makes the DomainParticipants, each
under the ObjectId of its name); crates/xrce-agent/src/daemon/definitions.rs
(ApplicationDef, ParticipantDef)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_create_client_makes_the_objects_configured_for_the_client,
crates/xrce-agent/src/daemon/session.rs::tests::what_a_configuration_client_defines_is_referenced_by_another_client,
crates/xrce-agent/src/daemon/session.rs::tests::a_participant_definition_creates_the_objects_inside_it
Status: done — an Application from an <application_library> makes its
DomainParticipants with everything inside them, also for a client it is assigned
to in client_applications: (9d5c64dc398, 2ba972cd270).
§7.4 AccessController
Spec: §7.4, p. 21 — “The AccessController is responsible for making decisions regarding the resources and operations a particular XRCE ProxyClient is allowed to perform. It contains rules that associate a Client with privileges, which determine which DDS domain an application executing on behalf of a client may join, which DDS Topics the application can read and write, and so on.”
Repo: crates/xrce-agent/src/daemon/access.rs (AccessController, Rule,
Subject, Operation); crates/xrce-agent/src/daemon/session.rs
(SessionEngine::permit, permits, deny_create_client);
crates/xrce-agent/src/daemon/config.rs (keys authorized_client_keys,
required_client_properties, access_rules)
Tests: crates/xrce-agent/src/daemon/access.rs::tests::a_controller_without_rules_restricts_nothing,
crates/xrce-agent/src/daemon/access.rs::tests::the_first_matching_rule_decides_and_no_match_denies,
crates/xrce-agent/src/daemon/access.rs::tests::domains_kinds_and_topic_prefixes_narrow_a_rule,
crates/xrce-agent/src/daemon/access.rs::tests::only_configured_client_keys_are_authorized,
crates/xrce-agent/src/daemon/session.rs::tests::a_client_key_not_configured_in_the_agent_is_denied,
crates/xrce-agent/src/daemon/session.rs::tests::create_without_permission_is_denied_and_stores_nothing,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_and_delete_without_permission_are_denied,
crates/xrce-agent/src/daemon/session.rs::tests::write_and_read_without_permission_are_denied,
crates/xrce-agent/src/daemon/session.rs::tests::a_rule_can_limit_the_domains_a_client_joins
Status: done — rules per client for operation, ObjectKind, DDS domain and
topic; an operation no rule matches is answered with STATUS_ERR_DENIED as soon
as one rule exists, a controller without rules restricts nothing (1c430db8a67,
5f7a8652d95).
§7.4 DomainParticipant as a proxy
Spec: §7.4, p. 21 — “The DDS-XRCE DomainParticipant is a proxy for a DDS DomainParticipant and models the association with a DDS domain and the capability of the Application to publish and subscribe to Topics on that domain.”
Repo: crates/xrce-agent/src/daemon/dcps_bridge.rs
(RealDdsPort::create_participant_with, runtime_for)
Tests: crates/xrce-agent/src/daemon/dcps_bridge.rs::tests::full_chain_against_a_real_leased_domain,
crates/xrce-agent/src/daemon/dcps_bridge.rs::tests::two_large_samples_reach_a_default_reader_on_the_same_agent
Status: done — all XRCE DomainParticipants of a domain share one
DcpsRuntime, except a participant with USER_DATA (a runtime of its own per
domain and value); §10.3 allows that as long as the behaviour looks as if each
client had entities of its own.
§7.5 XRCE DDS Proxy Objects
§7.5 Proxy objects delegate to DDS objects
Spec: §7.5, p. 22 — “These proxy objects allow the client application to participate as first-class citizens on the DDS network by delegating the actual DDS behavior and DDS-RTPS protocol implementation to the proxy DDS objects.” Figure 5: DomainParticipant, Publisher, Subscriber, DataWriter, DataReader, Topic, QosProfile and Qos as values.
Repo: crates/xrce-agent/src/daemon/session.rs (apply_dds_create);
crates/xrce-agent/src/daemon/dcps_bridge.rs
(RealDdsPort::create_participant_with, create_publisher,
create_subscriber, create_writer, create_reader)
Tests: crates/xrce-agent/tests/replay_foreign_session.rs::replay_creates_the_dds_entities_the_real_clients_describe,
crates/xrce-agent/tests/e2e_udp_loopback.rs::e2e_udp_loopback_keyed_dispose_reliable_besteffort_and_fragments,
crates/xrce-agent/src/daemon/dcps_bridge.rs::tests::a_publisher_is_a_dds_entity_of_its_participants_domain
Status: done — DataWriter and DataReader are DDS endpoints in the
DcpsRuntime, Publisher and Subscriber each have a DDS entity of their own in
the participant (505c2e56d24), the Topic is held as name and type in the state
of the RealDdsPort, QosProfile and Qos enter as values.
§7.5 Publisher and Subscriber as a DDS entity
Spec: §7.5, p. 22 — as above.
Repo: crates/xrce-agent/src/daemon/dds_port.rs
(DdsPort::create_publisher, create_subscriber, ContainerSpec);
crates/xrce-agent/src/daemon/dcps_bridge.rs (RealDdsPort::create_container,
container_for); crates/xrce-agent/src/daemon/session.rs
(DdsCreate::Container)
Tests: crates/xrce-agent/src/daemon/dcps_bridge.rs::tests::a_publisher_is_a_dds_entity_of_its_participants_domain,
crates/xrce-agent/src/daemon/session.rs::tests::a_publisher_and_a_subscriber_get_a_dds_entity_with_their_policies,
crates/xrce-agent/src/daemon/session.rs::tests::a_publisher_or_subscriber_needs_an_existing_participant,
crates/xrce-agent/src/daemon/dds_port.rs::tests::publisher_and_subscriber_need_their_participant_and_endpoints_need_them,
crates/xrce-agent/src/daemon/dds_port.rs::tests::a_publisher_that_does_not_autoenable_refuses_its_writers
Status: done — Publisher and Subscriber are a group entity in the
participant of their domain; PRESENTATION and ENTITY_FACTORY from the XML forms
take effect (ENTITY_FACTORY autoenable_created_entities: false refuses the
endpoints under it), PARTITION and GROUP_DATA reach the endpoints through their
EndpointQos. A participant that does not exist gives
STATUS_ERR_UNKNOWN_REFERENCE (505c2e56d24). GROUP_DATA is announced with the
endpoint, not with an announcement of the Publisher of its own.
§7.6 XRCE Object Identification
§7.6 ObjectId unique per agent and ClientKey
Spec: §7.6, p. 22 — “This implies that the ObjectId shall be unique within the scope of an Agent and a ClientKey.”
Repo: crates/xrce/src/object_store.rs (ObjectStore);
crates/xrce-agent/src/lib.rs (XrceAgent::register_client, one object store
per ClientKey)
Tests: crates/xrce/src/object_store.rs::tests::create_strict_on_existing_returns_conflict,
crates/xrce-agent/src/lib.rs::tests::multiple_clients_isolated
Status: done
§7.6 ObjectId configured in the agent or chosen by the client
Spec: §7.6, p. 22 — “The value of the ObjectId for a particular object shall be configured on the XRCE Agent or specified by the XRCE Client at the time the object is created.”
Repo: crates/xrce/src/object_id.rs (ObjectId::from_reference);
crates/xrce-agent/src/daemon/session.rs (handle_create, ensure_predefined)
Tests: crates/xrce/src/object_id.rs::tests::from_reference_matches_the_examples_of_the_spec,
crates/xrce-agent/src/daemon/session.rs::tests::a_client_writes_through_a_preconfigured_data_writer_without_a_create,
crates/xrce-agent/src/daemon/session.rs::tests::the_object_id_is_the_prefix_and_the_kind_of_the_representation,
crates/xrce-agent/tests/replay_foreign_session.rs::replay_matches_the_real_agents_create_client_create_and_delete_replies
Status: done — the ObjectId the client chose is taken over; the
ObjectId configured in the agent is the one from the MD5 of the name per §9.3
and Table 16 (468aa0940da, 2ba972cd270).
§7.6 OBJECTID_INVALID {0x00, 0x00}
Spec: §7.6, p. 23 — “The value {0x00, 0x00} is referred as OBJECTID_INVALID and represents an invalid object.”
Repo: crates/xrce/src/object_id.rs (OBJECTID_INVALID = 0x0000,
OBJECTID_SESSION = 0xFFFF); crates/xrce/src/object_store.rs
(ObjectStore::create refuses OBJECTID_INVALID)
Tests: crates/xrce/src/object_id.rs::tests::invalid_object_id_is_all_zeros,
crates/xrce/src/object_id.rs::tests::reserved_object_ids_per_spec_7_6_and_annex_a,
crates/xrce/src/object_store.rs::tests::create_invalid_object_id_rejected
Status: done — OBJECTID_INVALID is {0x00, 0x00}, 0xFFFF is
OBJECTID_SESSION of Annex A (daf2a618f74); the constants of the SDKs in
endpoints/ follow (6f674508b96).
§7.6 OBJECTID_CLIENT {0xFF, 0xFE}
Spec: §7.6, p. 23 — “The value {0xFF, 0xFE} is referred as OBJECTID_CLIENT and represents the XRCE ProxyClient object.”
Repo: crates/xrce/src/object_id.rs (OBJECTID_CLIENT);
crates/xrce-agent/src/daemon/session.rs (handle_delete)
Tests: crates/xrce/src/object_id.rs::tests::client_singleton_has_kind_client,
crates/xrce-client/src/lib.rs::tests::disconnect_sends_delete_client_and_clears_state
Status: done
§7.6 Two reserved values
Spec: §7.6, p. 23 — “There are two reserved values for ObjectId.”
Repo: —
Tests: —
Status: n/a (informative) — Annex A (p. 103) names four values
(OBJECTID_INVALID, OBJECTID_AGENT, OBJECTID_CLIENT, OBJECTID_SESSION);
the two further ones are listed as items on Annex A.
§7.6 Resource name instead of ObjectId
Spec: §7.6, p. 23 — “Alternatively, objects may also be identified by a string resourceName. The format of this name depends on the resource and provides a way to refer to a resource configured on the agent using a configuration file or similar means.”
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (referenced);
crates/xrce-agent/src/daemon/profiles.rs (AgentProfiles);
crates/xrce-agent/src/daemon/definitions.rs (SystemDefinitions)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::references_resolve_against_the_profile_files,
crates/xrce-agent/src/daemon/session.rs::tests::a_topic_is_created_by_name_or_by_register_type_ref,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_reference_is_read_like_the_profile_it_names
Status: done — a name resolves against the agent’s files: the
profile_name of a profile file and the DDS-XML names (Library::Element,
Table 15) of the libraries of §9.3 (452ffeb7f84, 9d5c64dc398).
§7.7 Data types used to model operations on XRCE Objects
§7.7 IDL as in Annex A, XCDR2 encoding
Spec: §7.7, p. 23 — “The IDL definitions for the data types shall be as specified in Annex A IDL Types. When serializing these types into a binary representation the encoding shall follow the rules defined in in [DDS-XTYPES] for XCDR version 2 encoding.”
Repo: crates/xrce/src/ (codecs per type, see the following items;
encoding.rs: UnannotatedTypes, RepresentationTimestamps);
crates/xrce-agent/src/daemon/binary_forms.rs (XCDR2 reader of the binary
forms)
Tests: crates/xrce/tests/foreign_frames.rs::every_client_datagram_decodes_and_writes_back,
crates/xrce/tests/foreign_frames.rs::every_agent_datagram_decodes_and_writes_back,
crates/xrce/tests/unannotated_types.rs::the_default_is_appendable_with_a_dheader
Status: done — the payloads of the submessages and the types of Annex A
are read and written as XCDR2. Types without @extensibility are APPENDABLE
with a DHEADER; the FINAL form of the reference implementation is the setting
unannotated_types: final (7f85e76debd). Extensions beyond Annex A are in the
items of the individual types, among them requested_mtu behind properties of
the CLIENT_Representation. The classic CDR form of the binary objects of the
eProsima client stays as a fallback (entity_repr.rs, Cdr).
§7.7 Alignment, DHEADER and byte order of the Annex A types
Spec: §7.7, p. 23 — as above.
Repo: crates/xrce/src/handshake.rs (encode_properties,
decode_properties); crates/xrce/src/transport_locator.rs;
crates/xrce/src/submessages/read_data.rs; crates/xrce/src/object_info.rs;
crates/xrce-agent/src/daemon/binary_forms.rs
Tests: crates/xrce/src/handshake.rs::tests::padding_counts_from_the_start_of_the_payload,
crates/xrce/src/handshake.rs::tests::a_big_endian_client_representation_with_properties_reads_back,
crates/xrce/src/transport_locator.rs::tests::padding_is_counted_from_the_start_of_the_payload,
crates/xrce/src/transport_locator.rs::tests::by_default_the_union_and_its_case_have_a_dheader,
crates/xrce/src/submessages/read_data.rs::tests::the_content_filter_is_a_string_with_a_nul_and_an_aligned_length,
crates/xrce/src/submessages/read_data.rs::tests::annex_b_4_2_read_data_with_filter_and_delivery_control,
crates/xrce/src/object_info.rs::tests::agent_activity_info_has_a_dheader_and_a_locator_sequence,
crates/xrce/src/object_info.rs::tests::object_info_puts_the_activity_before_the_config,
crates/xrce-agent/src/daemon/binary_forms.rs::tests::annex_a_topic_has_a_dheader,
crates/xrce/tests/unannotated_types.rs::both_forms_are_read_in_either_setting
Status: done — the deviations are fixed: PropertySeq with lengths
aligned to 4 (ca0cf7e08bf); TransportLocator with alignment, DHEADER and
numeric ports (299b3a41398); content_filter_expression as an XCDR2 string and
DataDeliveryControl with a DHEADER (b589558e671); AGENT_ActivityInfo,
DATAREADER_ActivityInfo, DATAWRITER_ActivityInfo, ObjectInfo and
ActivityInfoVariant per Annex A (ca0cf7e08bf); the binary forms of Annex A as
XCDR2 with a DHEADER (f548fee2522); CLIENT_Representation,
AGENT_Representation, ObjectInfo and the locators in the byte order of the E
flag (b9255734bfb).
§7.7.1 Data and Samples
§7.7.1 Five formats and the values of DataFormat
Spec: §7.7.1, p. 23 — “The five possible representation are: SampleData, Sample, SampleDataSeq, SampleSeq, and SamplePackedData. They respectively correspond to the DataFormat values FORMAT_DATA, FORMAT_DATA_SEQ, FORMAT_SAMPLE, FORMAT_SAMPLE_SEQ, and FORMAT_PACKED.”
Repo: crates/xrce/src/submessages/write_data.rs (DataFormat,
AnyWriteData); crates/xrce/src/submessages/data.rs (AnyData)
Tests: crates/xrce/src/submessages/write_data.rs::tests::any_write_data_dispatches_every_format,
crates/xrce/src/submessages/data.rs::tests::any_data_dispatches_every_format,
crates/xrce/src/submessages/read_data.rs::tests::the_data_format_octet_has_the_values_of_annex_a
Status: done — the code maps as Table 1 and Annex A do (SampleDataSeq to
FORMAT_DATA_SEQ, Sample to FORMAT_SAMPLE; values 0x00, 0x02, 0x08, 0x0A,
0x0E). The “respectively” list of this sentence maps Sample to FORMAT_DATA_SEQ
and names SamplePackedData and FORMAT_PACKED, which Annex A does not have.
§7.7.1 SampleData
Spec: §7.7.1, p. 23 — “@extensibility(FINAL) struct SampleData { XCDRSerializedBuffer serialized_data; }; In this structure the XCDRSerializedBuffer represents the bytes resulting from serializing the application-specific data type that is being sent using the XCDR version 2 rules defined in clause 7.4 of [DDS-XTYPES].”
Repo: crates/xrce/src/submessages/write_data.rs
(WriteDataPayload::encode_body, try_from_submessage);
crates/xrce/src/submessages/data.rs (DataPayload)
Tests: crates/xrce/src/submessages/write_data.rs::tests::write_data_matches_the_annex_b_example,
crates/xrce/src/submessages/data.rs::tests::data_base_object_request_precedes_the_sample
Status: done — serialized_data runs without a length of its own to the
end of the submessage, as in Annex B.3.1 (submessageLength = 6). Annex A
does not define XCDRSerializedBuffer.
§7.7.1 SampleInfoFlags
Spec: §7.7.1, p. 23 — “@bit_bound(8) bitmask SampleInfoFlags { @position(0) INSTANCE_STATE_UNREGISTERED, @position(1) INSTANCE_STATE_DISPOSED, @position(2) VIEW_STATE_NEW, @position(3) SAMPLE_STATE_READ, };”
Repo: crates/xrce/src/sample_info.rs (SampleInfoFlags)
Tests: crates/xrce/src/sample_info.rs::tests::sample_info_flags_bit_positions,
crates/xrce/src/sample_info.rs::tests::sample_info_flags_all_four_bits_independent
Status: done
§7.7.1 SampleInfo with sequence_number and session_time_offset
Spec: §7.7.1, p. 24 — “@extensibility(FINAL) struct SampleInfo { SampleInfoFlags state; unsigned long sequence_number; unsigned long session_time_offset; // milliseconds up to 53 days };”
Repo: crates/xrce/src/sample_info.rs (SampleInfo,
WIRE_SIZE = 12)
Tests: crates/xrce/src/sample_info.rs::tests::sample_info_matches_annex_b_5_3_layout,
crates/xrce/src/sample_info.rs::tests::sample_info_roundtrip_be
Status: done — state, 3 bytes of padding, two unsigned long. Annex A
(p. 115) defines SampleInfo differently; that is an item of its own on
Annex A.
§7.7.1 Sample
Spec: §7.7.1, p. 24 — “@extensibility(FINAL) struct Sample { SampleInfo info; SampleData data; };”
Repo: crates/xrce/src/submessages/write_data.rs
(WriteDataPayloadSample); crates/xrce/src/submessages/data.rs
(DataPayloadSample)
Tests: crates/xrce/src/submessages/write_data.rs::tests::write_data_sample_matches_annex_b_5_3_layout,
crates/xrce/src/submessages/data.rs::tests::data_sample_matches_annex_b_5_3_layout
Status: done
§7.7.1 DeciSecond and SampleInfoDelta
Spec: §7.7.1, p. 24 — “typedef unsigned short DeciSecond; // 10e-1 seconds @extensibility(FINAL) struct SampleInfoDelta { SampleInfoFlags state; octet seq_number_delta; DeciSecond timestamp_delta; // In 1/10 of seconds };”
Repo: crates/xrce/src/sample_info.rs (SampleInfoDelta,
WIRE_SIZE = 4)
Tests: crates/xrce/src/sample_info.rs::tests::sample_info_delta_roundtrip,
crates/xrce/src/sample_info.rs::tests::sample_info_delta_decode_short_is_eof
Status: done
§7.7.1 SampleDelta
Spec: §7.7.1, p. 24 — “@extensibility(FINAL) struct SampleDelta { SampleInfoDelta info_delta; SampleData data; };”
Repo: crates/xrce/src/submessages/write_data.rs
(WriteDataPayloadPackedSamples::elements); crates/xrce/src/sample_info.rs
(SampleInfoDelta::decode); crates/xrce-agent/src/daemon/session.rs
(SessionEngine::split_write_items, SessionEngine::data_submessages)
Tests: crates/xrce/src/submessages/write_data.rs::tests::write_data_packed_samples_matches_annex_b_5_5_layout,
crates/xrce-agent/src/daemon/session.rs::tests::packed_samples_resolve_their_deltas_against_the_base
Status: done — the layout per element is mapped; in the codec the elements stay
one block (elements) because SampleData carries no length. The agent
separates them on WRITE_DATA by the type of the topic (split_write_items,
f40bd568ad1) and writes them on READ_DATA (data_submessages, fd5253ca805).
§7.7.1 PackedSamples
Spec: §7.7.1, p. 24 — “@extensibility(FINAL) struct PackedSamples {
SampleInfo info_base; sequence
Repo: crates/xrce/src/submessages/write_data.rs
(WriteDataPayloadPackedSamples); crates/xrce/src/submessages/data.rs
(DataPayloadPackedSamples)
Tests: crates/xrce/src/submessages/data.rs::tests::data_packed_samples_matches_annex_b_5_5_layout,
crates/xrce-agent/src/daemon/session.rs::tests::a_read_for_packed_samples_is_answered_with_one_packed_samples,
crates/xrce-agent/src/daemon/session.rs::tests::packed_samples_resolve_their_deltas_against_the_base
Status: done — the agent reads the form on WRITE_DATA (f40bd568ad1) and writes it on READ_DATA (fd5253ca805).
§7.7.2 DataRepresentation
§7.7.2 DataRepresentation as a union over DataFormat
Spec: §7.7.2, p. 24 and p. 26 — “The DataRepresentation is defined as a union discriminated by a DataFormat. Depending on the discriminator it selects one of the formats defined in clause 7.7.1.” “union DataRepresentation switch(DataFormat) { case FORMAT_DATA: SampleData data; case FORMAT_SAMPLE: Sample sample; case FORMAT_DATA_SEQ: SampleDataSeq data_seq; case FORMAT_SAMPLE_SEQ: SampleSeq sample_seq; case FORMAT_PACKED_SAMPLES: PackedSamples packed_samples; };”
Repo: crates/xrce/src/submessages/write_data.rs (AnyWriteData,
discriminator from the flags through DataFormat::from_flag_bits)
Tests: crates/xrce/src/submessages/write_data.rs::tests::any_write_data_dispatches_every_format
Status: done — the discriminator is in the submessage flags (§8.3.5.8.1), not in the payload.
§7.7.2 Table 1 FORMAT_DATA
Spec: §7.7.2, Table 1, p. 25 — “FORMAT_DATA struct SampleData […] Contains the data for a single sample without additional sample information.”
Repo: crates/xrce/src/submessages/write_data.rs (WriteDataPayload)
Tests: crates/xrce/src/submessages/write_data.rs::tests::write_data_roundtrip_format_data
Status: done
§7.7.2 Table 1 FORMAT_DATA_SEQ
Spec: §7.7.2, Table 1, p. 25 — “FORMAT_DATA_SEQ struct SampleDataSeq […] Contains a sequence of data samples.”
Repo: crates/xrce/src/submessages/write_data.rs
(WriteDataPayloadDataSeq); crates/xrce-agent/src/daemon/session.rs
(SessionEngine::split_write_items, SessionEngine::data_submessages)
Tests: crates/xrce/src/submessages/write_data.rs::tests::write_data_data_seq_matches_annex_b_5_2_layout,
crates/xrce-agent/src/daemon/session.rs::tests::a_data_seq_is_split_by_the_type_and_written_sample_by_sample,
crates/xrce-agent/src/daemon/session.rs::tests::a_read_for_data_seq_is_answered_with_one_data_seq,
crates/xrce-agent/src/daemon/session.rs::tests::the_sequence_formats_split_at_the_size_of_a_submessage
Status: done — number of elements and the elements as one block. The agent separates the elements on WRITE_DATA by the type of the topic and writes each one (f40bd568ad1); on READ_DATA it writes one DATA_SEQ per submessage (fd5253ca805). Assumption, not measured: the elements sit back to back with no padding, each read from alignment origin 0 (Annex B.5.2 shows only elements of 4 bytes).
§7.7.2 Table 1 FORMAT_SAMPLE with a timestamp relative to the session
Spec: §7.7.2, Table 1, p. 25 — “The SampleInfo holds the DDS InstanceState, SampleState, and ViewState of the corresponding DDS Sample. It also contains the sample sequence number and timestamp. The timestamp is represented as an offset relative to the session timestamp established when the session was created. The session timestamp corresponds to the client_timestamp attribute in CLIENT_Representation”.
Repo: crates/xrce-agent/src/daemon/session.rs (data_submessages, source_offset_ms, handle_write_data); crates/xrce/src/sample_info.rs (SampleInfo)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::the_sample_info_is_what_the_datareader_gave, crates/xrce-agent/src/daemon/session.rs::tests::the_client_timestamp_is_the_session_timestamp
Status: done — state, sequence number and offset are carried. In WRITE_DATA the offset is the time after the start of the session and becomes the source timestamp (f40bd568ad1). In READ_DATA the agent sends FORMAT_SAMPLE with the writer’s source timestamp as the offset and the state of the DataReader (5c2466a4563). The start of the session is the client_timestamp of the CREATE_CLIENT (8b73c291192).
### §7.7.2 Content of the SampleInfo and reference point of the timestamp
Spec: §7.7.2, Table 1, p. 25 — as above.
Repo: crates/xrce-agent/src/daemon/dds_port.rs (PolledSample, DdsPort::poll_samples); crates/xrce-agent/src/daemon/dcps_bridge.rs (spawn_reader_pump, ReaderQueue::push); crates/xrce-agent/src/daemon/session.rs (data_submessages, session_start); crates/xrce-client/src/lib.rs (session_time_offset_ms)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::the_sample_info_is_what_the_datareader_gave, crates/xrce-agent/src/daemon/session.rs::tests::the_client_timestamp_is_the_session_timestamp
Status: done — DdsPort::poll_samples returns PolledSample (payload, SampleInfoFlags, source timestamp): VIEW_STATE_NEW for the first sample of an instance, INSTANCE_STATE_DISPOSED/_UNREGISTERED for a dispose or unregister the DataReader reports (a sample without data), SAMPLE_STATE_READ never (a sample is handed over once). FORMAT_DATA and FORMAT_DATA_SEQ have no SampleInfo and send no markers. The reference point is the client_timestamp (representation_timestamps: present) or the agent’s clock; the client writes the milliseconds since connect as the offset. 5c2466a4563, 8b73c291192.
### §7.7.2 Table 1 FORMAT_SAMPLE_SEQ
Spec: §7.7.2, Table 1, p. 25 — “FORMAT_SAMPLE_SEQ struct SampleSeq […] Contains a sequence of samples, each containing both the data and the additional sample information.”
Repo: crates/xrce/src/submessages/write_data.rs
(WriteDataPayloadSampleSeq); crates/xrce-agent/src/daemon/session.rs
(SessionEngine::split_write_items, SessionEngine::data_submessages)
Tests: crates/xrce/src/submessages/write_data.rs::tests::write_data_sample_seq_matches_annex_b_5_4_layout,
crates/xrce-agent/src/daemon/session.rs::tests::a_sample_seq_carries_state_and_time_per_sample,
crates/xrce-agent/src/daemon/session.rs::tests::a_read_for_sample_seq_is_answered_with_one_sample_seq
Status: done — the agent reads the form on WRITE_DATA (state and time per sample,
f40bd568ad1) and writes it on READ_DATA (fd5253ca805). What the SampleInfo
holds on reading is in the open item on §7.7.2.
§7.7.2 Table 1 FORMAT_PACKED_SAMPLES and resulting_info
Spec: §7.7.2, Table 1, p. 25 — “This representation is limited to samples that are close in sequence number (no more than 256 apart) and timestamp (100 minutes). […] resulting_info.state := info_delta.state resulting_info.sequence_number := info_base.sequence_number + info_delta.seq_number_delta resulting_info. session_time_offset := info_base. session_time_offset + info_delta.timestamp_delta”
Repo: crates/xrce/src/sample_info.rs (SampleInfoDelta::resolve);
crates/xrce-agent/src/daemon/session.rs (SessionEngine::data_submessages)
Tests: crates/xrce/src/sample_info.rs::tests::sample_info_delta_resolve_adds_to_base,
crates/xrce/src/sample_info.rs::tests::sample_info_delta_resolve_wraps_on_overflow,
crates/xrce-agent/src/daemon/session.rs::tests::packed_samples_resolve_their_deltas_against_the_base,
crates/xrce-agent/src/daemon/session.rs::tests::a_read_for_packed_samples_is_answered_with_one_packed_samples
Status: done — resolve converts timestamp_delta (tenths of a second) with 100 to
milliseconds; the formula of the spec adds quantities in milliseconds and
tenths of a second without a conversion. The agent reads the form on
WRITE_DATA and writes it on READ_DATA with at most 256 elements per submessage
(the range of seq_number_delta, an octet); it writes timestamp_delta and
state as 0 (f40bd568ad1, fd5253ca805).
§7.7.3 ObjectVariant
§7.7.3 ObjectVariant as a union over ObjectKind
Spec: §7.7.3, p. 26 — “The ObjectVariant type is defined as a union discriminated by ObjectKind. Each value of the discriminator selects an appropriate object representation for that kind.”
Repo: crates/xrce/src/object_repr.rs (ObjectVariant::encode_for_kind, decode_for_kind, ObjectVariantExtra)
Tests: crates/xrce/src/object_repr.rs::tests::encode_for_kind_round_trips_every_objk_kind_with_its_own_trailing_field,
crates/xrce/src/object_repr.rs::tests::participant_representation_matches_the_captured_create_bytes,
crates/xrce/src/object_repr.rs::tests::subscriber_representation_matches_the_captured_create_bytes
Status: done — ObjectKind as an octet, then the representation of the
kind and its trailing field (domain_id or the container’s ObjectId).
§7.7.3 Several formats per kind
Spec: §7.7.3, p. 26 — “For a given ObjectKind the, ObjectVariant type also supports multiple representation formats. Each format is identified by a value of the RepresentationFormat.”
Repo: crates/xrce/src/object_repr.rs (ObjectVariant,
encode_with_pad, decode_with_pad)
Tests: crates/xrce/src/object_repr.rs::tests::by_reference_roundtrip_le,
crates/xrce/src/object_repr.rs::tests::by_xml_string_roundtrip_be,
crates/xrce/src/object_repr.rs::tests::in_binary_roundtrip
Status: done
§7.7.3.1 Object Representation Formats
§7.7.3.1 Three values of RepresentationFormat
Spec: §7.7.3.1, p. 26 — “There are three RepresentationFormat values: REPRESENTATION_BY_REFERENCE, REPRESENTATION_AS_XML_STRING, and REPRESENTATION_IN_BINARY.” Annex A, p. 106: 0x01, 0x02, 0x03.
Repo: crates/xrce/src/object_repr.rs (repr_disc)
Tests: crates/xrce/src/object_repr.rs::tests::discriminator_returns_correct_byte,
crates/xrce/src/object_repr.rs::tests::unknown_discriminator_rejected
Status: done
§7.7.3.1 Three or two formats per kind
Spec: §7.7.3.1, p. 26 — “Some object kinds support all three formats; in this case the corresponding representation extends the type struct OBJK_Representation3_Base. Other object kinds support only two formats, and therefore, extend the type struct OBJK_RepresentationRefAndXML_Base or the type OBJK_RepresentationBinAndXML_Base.”
Repo: crates/xrce/src/object_repr.rs (decode_for_kind); crates/xrce-agent/src/daemon/session.rs
(format_is_allowed)
Tests: crates/xrce/src/object_repr.rs::tests::encode_for_kind_round_trips_every_objk_kind_with_its_own_trailing_field,
crates/xrce-agent/src/daemon/session.rs::tests::the_formats_of_each_kind_are_enforced
Status: done — decode_for_kind reads all three discriminators; the agent admits per
kind only the formats of the spec: Participant and Topic all three, Type,
QosProfile and Application reference and XML, Publisher, Subscriber,
DataWriter and DataReader binary and XML. Any other format is
STATUS_ERR_INVALID_DATA (0429eab4fb2). The setting is in the item “Allowed
formats per kind”.
§7.7.3.1 Allowed formats per kind
Spec: §7.7.3.1, p. 26 — as above.
Repo: crates/xrce-agent/src/daemon/session.rs (format_is_allowed, check in SessionEngine::handle_create);
crates/xrce-agent/src/daemon/config.rs (key representation_formats)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::the_formats_of_each_kind_are_enforced,
crates/xrce-agent/src/daemon/session.rs::tests::references_resolve_against_the_profile_files,
crates/xrce-agent/src/daemon/config.rs::tests::the_representation_formats_can_be_widened
Status: done — the normative reading (§7.7.3.1, Annex A) is the default: a CREATE in a
format that the union of the kind does not have is STATUS_ERR_INVALID_DATA
with a CreateRefused event. The other reading is the setting
representation_formats: spec | any (default spec); any admits all
formats, for example for the Micro XRCE-DDS client, which creates Publishers,
Subscribers, DataWriters and DataReaders by *_ref (not measured, the capture
has XML and binary only). Both readings are tested (0429eab4fb2).
§7.7.3.1 OBJK_Representation3Formats
Spec: §7.7.3.1, p. 26–27 — “union OBJK_Representation3Formats
switch(RepresentationFormat) { case REPRESENTATION_BY_REFERENCE :
string
Repo: crates/xrce/src/object_repr.rs (ObjectVariant,
encode_with_pad: length, characters and NUL for the strings, length
and octets for the sequence)
Tests: crates/xrce/src/object_repr.rs::tests::topic_representation_matches_the_captured_create_bytes,
crates/xrce/src/object_repr.rs::tests::in_binary_roundtrip
Status: done — the bound REFERENCE_MAX_LEN is an item of its own.
§7.7.3.1 OBJK_RepresentationRefAndXMLFormats
Spec: §7.7.3.1, p. 27 — “union OBJK_RepresentationRefAndXMLFormats
switch(RepresentationFormat) { case REPRESENTATION_BY_REFERENCE :
string
Repo: crates/xrce/src/object_repr.rs (ObjectVariant::ByReference,
ByXmlString)
Tests: crates/xrce/src/object_repr.rs::tests::object_variant_xml_form_supports_topic_qosprofile_application
Status: done — the encoding of the two cases; that IN_BINARY must not
occur here is in the open item “Allowed formats per kind not checked”.
§7.7.3.1 OBJK_RepresentationBinAndXMLFormats
Spec: §7.7.3.1, p. 27 — “union OBJK_RepresentationBinAndXMLFormats
switch(RepresentationFormat) { case REPRESENTATION_IN_BINARY :
sequence
Repo: crates/xrce/src/object_repr.rs (ObjectVariant::InBinary,
ByXmlString)
Tests: crates/xrce/src/object_repr.rs::tests::subscriber_representation_matches_the_captured_create_bytes
Status: done — as above for BY_REFERENCE.
§7.7.3.1 Base types with the member representation
Spec: §7.7.3.1, p. 27 — “struct OBJK_RepresentationRefAndXML_Base { OBJK_RepresentationRefAndXMLFormats representation; }; struct OBJK_RepresentationBinAndXML_Base { OBJK_RepresentationBinAndXMLFormats representation; }; struct OBJK_Representation3_Base { OBJK_Representation3Formats representation; };”
Repo: crates/xrce/src/object_repr.rs (encode_for_kind)
Tests: crates/xrce/src/object_repr.rs::tests::encode_for_kind_round_trips_every_objk_kind_with_its_own_trailing_field
Status: done
§7.7.3.1 REFERENCE_MAX_LEN = 128
Spec: §7.7.3.1, p. 26 — “const long REFERENCE_MAX_LEN = 128;” with
string<REFERENCE_MAX_LEN> object_reference.
Repo: crates/xrce/src/object_repr.rs (REFERENCE_MAX_LEN, check in
ObjectVariant::encode_with_pad and decode_with_pad)
Tests: crates/xrce/src/object_repr.rs::tests::a_reference_longer_than_reference_max_len_is_refused
Status: done — reading and writing refuse a reference of more than 128 characters; 128 characters are allowed (58aad3ce5d7).
§7.7.3.1 Further formats such as JSON
Spec: §7.7.3.1, p. 27–28 — “It is expected that additional representations may be added after they are defined in other OMG specifications.”
Repo: —
Tests: —
Status: n/a (informative) — outlook.
§7.7.3.1.1 Reference to a description known to the agent
Spec: §7.7.3.1.1, p. 28 — “The REPRESENTATION_BY_REFERENCE represents the object using an object_reference encoded in a string. The string shall refer by name to a description already known to the XRCE Agent.”
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (referenced, participant,
participant_definition, application_definition); crates/xrce-agent/src/daemon/profiles.rs
(AgentProfiles::entity, AgentProfiles::qos_profile); crates/xrce-agent/src/daemon/definitions.rs
(SystemDefinitions); crates/xrce-agent/src/daemon/session.rs (plan_dds_create)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::references_resolve_against_the_profile_files,
crates/xrce-agent/src/daemon/session.rs::tests::what_a_configuration_client_defines_is_referenced_by_another_client,
crates/xrce-agent/src/daemon/session.rs::tests::a_client_writes_through_a_preconfigured_data_writer_without_a_create,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_reference_is_read_like_the_profile_it_names
Status: done — Participant, Topic, Publisher, Subscriber, DataWriter and DataReader
resolve against profile_name of a profile file in the Fast DDS format;
QosProfile (Lib::Profile), Application (Lib::App) and DomainParticipant
(Lib::Participant) against the libraries of the files and against the
definitions of other clients (452ffeb7f84, 9d5c64dc398, 2ba972cd270). An
unknown reference is STATUS_ERR_UNKNOWN_REFERENCE. Publisher, Subscriber,
DataWriter and DataReader by reference exist only with
representation_formats: any. Type and Domain are in the items on §7.7.3.3.1
and §7.7.3.4.1.
§7.7.3.1.1 object_reference as DDS-XML elementNameReference
Spec: §7.7.3.1.1, p. 28 — “The object_reference shall be a string formatted as defined by the XSD simpleType elementNameReference defined in the [DDS-XML] specification file dds-xml_domain_definitions_nonamespace.xsd.”
Repo: crates/xrce/src/object_repr.rs (element_name_reference); crates/xrce-agent/src/daemon/session.rs (handle_create)
Tests: crates/xrce/src/object_repr.rs::tests::element_name_references_follow_the_xsd_pattern, crates/xrce-agent/src/daemon/session.rs::tests::an_object_reference_must_be_an_element_name_reference
Status: done — the agent checks the object_reference of a CREATE as the XSD type elementNameReference (dds-xml_qos_definitions_nonamespace.xsd): whiteSpace collapse, then the pattern ((::)?[a-zA-Z0-9_.])+. A string of another shape is STATUS_ERR_INVALID_DATA, a well-formed one the agent does not hold STATUS_ERR_UNKNOWN_REFERENCE; references of the form Library::Name are resolved against the libraries of DDS-XML (9d5c64dc398, 452ffeb7f84). 1b9eed094c3.
### §7.7.3.1.1 Pre-configuration off-line or through the protocol
Spec: §7.7.3.1.1, p. 28 — “The pre-configuration may be done off-line prior to starting the XRCE Agent or may be done on-line using the DDS-XRCE protocol in combination with the REPRESENTATION_AS_XML_STRING.”
Repo: crates/xrce-agent/src/daemon/profiles.rs (AgentProfiles::load, AgentProfiles::add_profiles);
crates/xrce-agent/src/daemon/session.rs (SessionEngine::definition_to_register, rebuild_profiles)
Tests: crates/xrce-agent/src/daemon/profiles.rs::tests::the_eprosima_refs_file_indexes_every_entity_profile,
crates/xrce-agent/src/daemon/profiles.rs::tests::types_and_qos_libraries_in_a_dds_document_are_read,
crates/xrce-agent/src/daemon/session.rs::tests::what_a_configuration_client_defines_is_referenced_by_another_client
Status: done — off-line through xml_profile_files: (<types>, <qos_library>,
<domain_library>, <domain_participant_library>,
<application_library>; 452ffeb7f84). Through the protocol: a CREATE with the
XML of a QosProfile, Type, Application or DomainParticipant makes a definition
that other clients use by reference for as long as the object of the creating
client exists (9d5c64dc398).
§7.7.3.1.1 Example of a reference
Spec: §7.7.3.1.1, p. 28 — “The following string is an example of an object_reference used to represent an XRCE QosProfile: ‘MyQosLibrary::MyQosProfile’.”
Repo: —
Tests: —
Status: n/a (informative) — example.
§7.7.3.1.1 Kinds with a reference
Spec: §7.7.3.1.1, p. 28 — “This format is available for the XRCE Object kinds that can be configured as libraries in the XRCE Agent. These are XRCE Type, QosProfile, Domain, DomainParticipan, and Application.”
Repo: crates/xrce-agent/src/daemon/session.rs (format_is_allowed); crates/xrce-agent/src/daemon/config.rs (key
representation_formats)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::the_formats_of_each_kind_are_enforced,
crates/xrce-agent/src/daemon/session.rs::tests::references_resolve_against_the_profile_files,
crates/xrce-agent/src/daemon/config.rs::tests::the_representation_formats_can_be_widened
Status: done — the default is the reading of Annex A: reference for Participant and Topic
(OBJK_Representation3_Base) and for Type, QosProfile and Application
(OBJK_RepresentationRefAndXML_Base); Publisher, Subscriber, DataWriter and
DataReader have binary and XML only. The spec contradicts itself:
OBJK_TOPIC_Representation has a reference (§7.7.3.7.1, p. 33), §8.4.10 and
§8.4.11 (p. 82–83) name it for DataWriter and DataReader as well. The other
reading is the setting representation_formats: any (0429eab4fb2); both are
tested.
§7.7.3.1.2 XML as in DDS-XML
Spec: §7.7.3.1.2, p. 28–29 — “The string shall contain an XML element formatted according to the [DDS-XML] specification. The format of the string is defined for each Object kind in clauses 7.7.3.2 to 7.7.3.11.”
Repo: crates/xrce-agent/src/daemon/entity_repr.rs; crates/xrce-agent/src/daemon/definitions.rs
Tests: crates/xrce-agent/tests/spec_items_session.rs::a_type_by_reference_names_a_known_type_by_its_fully_qualified_name, crates/xrce-agent/tests/spec_items_session.rs::a_subscriber_in_xml_has_its_qos_and_its_nested_data_reader
Status: done — Type, QosProfile, Application, DomainParticipant (with the objects it holds), Topic, Publisher, Subscriber, DataWriter and DataReader are read as DDS-XML (9d5c64dc398, b97657ef4ec). A <types> may reference types already known (item on §7.7.3.3.2). Creating a Domain by CREATE is not defined by the specification (§7.7.3.4).
### §7.7.3.1.2 DDS-XML forms of entities
Spec: §7.7.3.1.2, p. 28–29 — as above.
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (endpoint_from_xml, container_from_xml, topic_from_xml, apply_qos_profile); crates/xrce-agent/src/daemon/definitions.rs
Tests: crates/xrce-agent/tests/spec_items_session.rs::a_subscriber_in_xml_has_its_qos_and_its_nested_data_reader, crates/xrce-agent/tests/spec_items_session.rs::a_data_reader_in_xml_has_its_qos_and_its_content_filter, crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_qos_of_a_topic_is_the_default_of_its_endpoints
Status: done — read and tested: register_type_ref, topic_ref as the name of the topic, <datawriter_qos>/<datareader_qos> with base_name, qos_profile_ref, <publisher_qos>, <subscriber_qos>, <topic_qos>, <domain_participant_qos>, <content_filter> and the libraries <qos_library>, <domain_library>, <domain_participant_library>, <application_library> (9d5c64dc398, b97657ef4ec, 3906abf91b8, 02c704651e4).
### §7.7.3.1.2 XML for remote configuration
Spec: §7.7.3.1.2, p. 29 — “This format is intended for remotely configuring the agent. Typically it will not be used by the XRCE Clients except in deployments where the client-to-agent connection has sufficient bandwidth.”
Repo: —
Tests: —
Status: n/a (informative) — note. The example below it (p. 29) has
wrongly closed elements (<reliability>, <data_reader_qos>,
<qos_library>).
§7.7.3.1.3 Binary as XCDR2 of the kind’s structure
Spec: §7.7.3.1.3, p. 28 — “The REPRESENTATION_IN_BINARY represents objects using a binary_representation octet sequence. The octet sequence is the result of serializing an IDL-defined data-structure that depends on the kind of object using the XCDR version 2 format defined in [DDS-XTYPES].”
Repo: crates/xrce-agent/src/daemon/binary_forms.rs (participant, topic, container, endpoint:
XCDR2 reader); crates/xrce-agent/src/daemon/entity_repr.rs (Cdr: the structures of the
eProsima Micro-XRCE-DDS client 3.0.1 as a further reading)
Tests: crates/xrce-agent/src/daemon/binary_forms.rs::tests::annex_a_topic_has_a_dheader,
crates/xrce-agent/src/daemon/binary_forms.rs::tests::the_36_octet_example_of_the_clause_is_a_topic,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_captured_binary_topic_names_its_topic_and_type,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_big_endian_binary_topic_reads_back,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_blob_of_no_form_is_refused_naming_each_reading
Status: done — the sequence<octet> is read as XCDR2 of the structure of the kind, in
both forms of the spec (Annex A with a DHEADER, the clauses as FINAL); a blob
that is none of the forms is refused, naming each reading. The eProsima
structures (classic CDR) stay as a further reading (f548fee2522).
§7.7.3.1.3 Binary forms of §7.7.3 and Annex A
Spec: §7.7.3.1.3, p. 28 — as above.
Repo: crates/xrce-agent/src/daemon/binary_forms.rs (participant, topic, container,
endpoint); crates/xrce-agent/src/daemon/entity_repr.rs (participant, topic, container,
endpoint)
Tests: crates/xrce-agent/src/daemon/binary_forms.rs::tests::participant_binary_in_both_forms,
crates/xrce-agent/src/daemon/binary_forms.rs::tests::annex_a_topic_has_a_dheader,
crates/xrce-agent/src/daemon/binary_forms.rs::tests::publisher_binary_of_annex_a,
crates/xrce-agent/src/daemon/binary_forms.rs::tests::writer_binary_of_annex_a_with_qos,
crates/xrce-agent/src/daemon/binary_forms.rs::tests::reader_binary_of_the_clause,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::an_annex_a_binary_writer_names_its_topic_and_qos,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_clause_binary_reader_names_its_topic_and_qos,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_spec_binary_participant_is_read
Status: done — Participant, Topic, Publisher, Subscriber, DataWriter and DataReader are
read in the form of Annex A (DHEADER) and the form of the clauses:
string topic_name for DataWriter and DataReader, TypeIdentifier and
type_reference for the Topic, the binary form of the Participant
(f548fee2522).
§7.7.3.1.3 Example OBJK_Topic_Binary with 36 bytes
Spec: §7.7.3.1.3, p. 29 — topic “Square”, type_reference
“MyTypes::ShapeType”, 36 bytes little-endian.
Repo: crates/xrce-agent/src/daemon/binary_forms.rs (topic); crates/xrce-agent/src/daemon/entity_repr.rs (topic)
Tests: crates/xrce-agent/src/daemon/binary_forms.rs::tests::the_36_octet_example_of_the_clause_is_a_topic,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_spec_binary_topic_names_its_topic_and_type
Status: done — the test decodes the 36 bytes of the example as a topic with
type_reference “MyTypes::ShapeType”. The characters of the example are
‘S’,‘q’,‘u’,‘e’,‘r’,‘e’; binary_forms reads them that way (743676fca9f),
the text of the spec calls the topic “Square”. In addition entity_repr reads
the same structure with “Square” as a 36-byte blob (f548fee2522).
§7.7.3.2 XRCE QosProfile
§7.7.3.2 OBJK_QOSPROFILE_Representation
Spec: §7.7.3.2, p. 29 — “struct OBJK_QOSPROFILE_Representation : OBJK_RepresentationRefAndXML_Base { };”
Repo: crates/xrce/src/object_repr.rs (decode_for_kind, no trailing
field for ObjectKind::QosProfile)
Tests: crates/xrce/src/object_repr.rs::tests::encode_for_kind_round_trips_every_objk_kind_with_its_own_trailing_field
Status: done — encoding; the effect is in the following items.
§7.7.3.2.1 Reference to a QosProfile “Lib::Profile”
Spec: §7.7.3.2.1, p. 29 — “the object_reference field shall contain the fully qualified name of a QosProfile known to the XRCE Agent. The fully qualified name is composed of the name of the Qos library and the name of the QosProfile within the library.”
Repo: crates/xrce-agent/src/daemon/session.rs (plan_dds_create, branch OBJK_QOSPROFILE); crates/xrce-agent/src/daemon/profiles.rs
(AgentProfiles::qos_profile)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::what_a_configuration_client_defines_is_referenced_by_another_client
Status: done — CREATE(OBJK_QOSPROFILE) with REPRESENTATION_BY_REFERENCE resolves
“Lib::Profile” against the QoS libraries of the files and of the definitions of
other clients; a name in no library is STATUS_ERR_UNKNOWN_REFERENCE
(9d5c64dc398).
§7.7.3.2.2 XML with one qos_library and one qos_profile
Spec: §7.7.3.2.2, p. 29 — “the string_representation field shall contain a
single
Repo: crates/xrce-agent/src/daemon/session.rs (SessionEngine::definition_to_register)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::type_and_qos_profile_xml_follow_their_clauses
Status: done — the <qos_library> with exactly one <qos_profile> is read and kept as
a definition; a library of two profiles is STATUS_ERR_INVALID_DATA
(b97657ef4ec).
§7.7.3.2.2 Reference to other QosProfiles
Spec: §7.7.3.2.2, p. 29–30 — “The REPRESENTATION_AS_XML_STRING
representation may reference other QoS profiles already known to the Agent.
[…]
Repo: crates/xrce-agent/src/daemon/session.rs (SessionEngine::definition_to_register); crates/xrce-agent/src/daemon/profiles.rs
(AgentProfiles::qos_profile)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::type_and_qos_profile_xml_follow_their_clauses
Status: done — base_name with one colon (“Q:One”) is read like “Q::One”; the
profile inherits from the profile the agent knows (b97657ef4ec). The example
writes base_name with one colon, §7.7.3.2.1 requires “::”.
§7.7.3.3 XRCE Type
§7.7.3.3 OBJK_TYPE_Representation
Spec: §7.7.3.3, p. 30 — “struct OBJK_TYPE_Representation : OBJK_RepresentationRefAndXML_Base { };”
Repo: crates/xrce/src/object_repr.rs (decode_for_kind)
Tests: crates/xrce/src/object_repr.rs::tests::encode_for_kind_round_trips_every_objk_kind_with_its_own_trailing_field,
crates/xrce-agent/src/daemon/session.rs::tests::the_formats_of_each_kind_are_enforced,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_binary_complete_type_object_is_named_by_its_own_type_name
Status: done — encoding. REPRESENTATION_IN_BINARY for OBJK_TYPE is
STATUS_ERR_INVALID_DATA with the default representation_formats: spec (item
“Allowed formats per kind”); with any, entity_repr::types reads a
TypeObject.
§7.7.3.3.1 Reference to a type with modules
Spec: §7.7.3.3.1, p. 30 — “the object_reference field shall contain the fully qualified name of an XRCE Type known to the XRCE Agent. The fully qualified name is composed of the name of the type prepended by the names of the enclosing modules.”
Repo: crates/xrce-agent/src/daemon/session.rs (plan_dds_create, find_type_definition)
Tests: crates/xrce-agent/tests/spec_items_session.rs::a_type_by_reference_names_a_known_type_by_its_fully_qualified_name
Status: done — CREATE(OBJK_TYPE) with REPRESENTATION_BY_REFERENCE resolves the name (MyModule::ShapeType) against the types of the client, of the files (<types>), of the definitions of other clients and of type_files:; an unknown name, also one without the module, is STATUS_ERR_UNKNOWN_REFERENCE (9d5c64dc398, 02c704651e4).
### §7.7.3.3.2 XML with types, one type with nested=false
Spec: §7.7.3.3.2, p. 30 — “the string_representation field shall contain a
single
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (types, nested_flags);
crates/xrce-agent/src/daemon/session.rs (DdsCreate::Types)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::type_and_qos_profile_xml_follow_their_clauses,
crates/xrce-agent/src/daemon/session.rs::tests::a_topic_gets_the_type_its_type_name_names,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::an_xml_type_library_compiles_to_named_complete_types
Status: done — <types> is read as DDS-XML and compiled; all named types are
registered. With several types exactly one must not carry nested, otherwise
STATUS_ERR_INVALID_DATA (b97657ef4ec). A topic finds its type by name
(SessionEngine::resolve_type).
§7.7.3.3.2 Annotation nested
Spec: §7.7.3.3.2, p. 30 — as above.
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (types, nested_flags)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::type_and_qos_profile_xml_follow_their_clauses
Status: done — nested_flags reads the annotation per type (also inside modules); two
types without nested="true" are STATUS_ERR_INVALID_DATA, one without and one
with nested="true" is STATUS_OK (b97657ef4ec).
§7.7.3.3.2 Reference to known types
Spec: §7.7.3.3.2, p. 30 — “The string_representation may reference other Types already known to the Agent.”
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (types); crates/xrce-agent/src/daemon/session.rs (plan_dds_create, ObjectKind::Type); crates/xml/src/typeobject_bridge.rs (bridge_library_complete_with_known)
Tests: crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_types_string_may_reference_types_the_agent_knows, crates/xrce-agent/src/daemon/session.rs::tests::a_types_string_references_a_type_created_before
Status: done — types passes the types known to the agent to zerodds_xml::bridge_library_complete_with_known(lib, known): those the same client created, those of type_files: and those of the profile files. A reference to one of them becomes its EquivalenceHashComplete; the known type is not defined again. A name that is neither in the string nor known is STATUS_ERR_UNKNOWN_REFERENCE. Not checked: whether a reference succeeds to a type another client created in binary (not as XML <types>); the types of XML <types> belong to the definitions of the agent (§9.2).
§7.7.3.4 XRCE Domain
§7.7.3.4 OBJK_DOMAIN_Representation
Spec: §7.7.3.4, p. 30–31 — “struct OBJK_DOMAIN_Representation : OBJK_RepresentationRefAndXML_Base { };”
Repo: —
Tests: —
Status: n/a (informative) — the specification gives Domain no value of ObjectKind and no case in ObjectVariant (§7.7.5, p. 39; Annex A, p. 103 and p. 111): a CREATE cannot name a Domain, there is nothing to fulfil. Kind 0x0F is OBJK_OTHER (daf2a618f74). Domains come from the <domain_library> of the files and can be referenced as Library::Domain (domain_ref, domain_reference).
### §7.7.3.4.1 Reference to a domain “Lib::Domain”
Spec: §7.7.3.4.1, p. 31 — “the object_reference field shall contain the
fully qualified name of an XRCE Domain definition known to the Agent.”
Repo: crates/xrce-agent/src/daemon/definitions.rs (domain, domain_scope); crates/xrce-agent/src/daemon/entity_repr.rs (participant)
Tests: crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_domain_reference_is_resolved_against_the_domain_libraries
Status: done — a Domain can be referenced as “Lib::Domain”: domain_ref of the DomainParticipant in XML and domain_reference of the binary form are resolved against the <domain_library> of the files (452ffeb7f84, 0b67c04800c). It cannot be the object_reference of a CREATE because the specification gives the Domain no ObjectKind (§7.7.3.4).
### §7.7.3.4.2 XML with domain_library and one domain
Spec: §7.7.3.4.2, p. 31 — “The XML shall contain a single
Repo: crates/xrce-agent/src/daemon/definitions.rs (add_domain_library)
Tests: crates/xrce-agent/src/daemon/definitions.rs::tests::a_participant_library_and_inheritance
Status: done — the <domain_library> with its <domain> elements is read from the files (also as a root; base_name, register_type, topic; 452ffeb7f84). A Domain as the content of a CREATE is not defined by the specification (§7.7.3.4).
§7.7.3.5 XRCE Application
§7.7.3.5 OBJK_APPLICATION_Representation
Spec: §7.7.3.5, p. 31 — “The OBJK_TYPE_Representation supports the REPRESENTATION_BY_REFERENCE and REPRESENTATION_AS_XML_STRING formats. […] struct OBJK_APPLICATION_Representation : OBJK_RepresentationRefAndXML_Base { };”
Repo: crates/xrce/src/object_repr.rs (decode_for_kind);
crates/xrce-agent/src/lib.rs (XrceAgent::create_object)
Tests: crates/xrce-agent/src/lib.rs::tests::create_application_object_via_objk_application,
crates/xrce-agent/src/daemon/session.rs::tests::the_formats_of_each_kind_are_enforced
Status: done — encoding and storage. The sentence names OBJK_TYPE_Representation
instead of OBJK_APPLICATION_Representation. A binary CREATE is
STATUS_ERR_INVALID_DATA (item “Allowed formats per kind”).
§7.7.3.5.1 Reference to an application “Lib::App”
Spec: §7.7.3.5.1, p. 31 — “the object_reference field shall contain the fully qualified name of an XRCE Application definition known to the Agent.”
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (application_definition); crates/xrce-agent/src/daemon/definitions.rs
(SystemDefinitions::application)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::what_a_configuration_client_defines_is_referenced_by_another_client,
crates/xrce-agent/src/daemon/session.rs::tests::a_create_client_makes_the_objects_configured_for_the_client
Status: done — “Lib::App” is resolved against the <application_library> of the files
and of the definitions of other clients; the CREATE makes the DomainParticipant
of the Application with everything inside it. An unknown Application is
STATUS_ERR_UNKNOWN_REFERENCE (9d5c64dc398, 2ba972cd270).
§7.7.3.5.2 XML with application_library and one application
Spec: §7.7.3.5.2, p. 31–32 — “The XML shall contain a single
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (application_definition); crates/xrce-agent/src/daemon/definitions.rs
(SystemDefinitions::add_application_library)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::what_a_configuration_client_defines_is_referenced_by_another_client,
crates/xrce-agent/src/daemon/definitions.rs::tests::the_example_file_defines_the_objects_of_table_16,
crates/xrce-agent/src/daemon/definitions.rs::tests::what_cannot_be_planned_is_refused
Status: done — the <application_library> with one <application> is read; its
Participants refer to types, QoS profiles, Domains and DomainParticipants of
the definitions (9d5c64dc398). The example (p. 32) creates in the Subscriber a
<data_writer name="MyReader" topic_ref="Circle"> although only “Square” is
defined; the code refuses a topic_ref to a topic the Participant does not
have.
§7.7.3.6 XRCE DomainParticipant
§7.7.3.6 OBJK_PARTICIPANT_Representation with domain_id
Spec: §7.7.3.6, p. 32 — “struct OBJK_PARTICIPANT_Representation : OBJK_Representation3_Base { short domain_id; };”
Repo: crates/xrce/src/object_repr.rs (encode_for_kind:
alignment to 2 before domain_id)
Tests: crates/xrce/src/object_repr.rs::tests::participant_representation_matches_the_captured_create_bytes
Status: done
§7.7.3.6.1 Reference to a DomainParticipant
Spec: §7.7.3.6.1, p. 32 — “the object_reference field shall contain the fully qualified name of an XRCE DomainParticipant definition known to the Agent. The fully qualified name is composed of the name of the DomainParticipant library and the name of the DomainParticipant within the library.”
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (participant, participant_definition); crates/xrce-agent/src/daemon/definitions.rs
(SystemDefinitions::participant)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_client_writes_through_a_preconfigured_data_writer_without_a_create,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_reference_is_read_like_the_profile_it_names
Status: done — the reference resolves against <participant profile_name> of a profile
file and against the <domain_participant_library> (“Lib::Participant”, for an
Application “Lib::App::Participant”); the domain comes from the definition
(domain_id or domain_ref) or from the profile (9d5c64dc398, 2ba972cd270).
§7.7.3.6.2 XML with domain_participant_library
Spec: §7.7.3.6.2, p. 32 — “the string_representation field shall contain a
single
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (participant_definition, participant_source);
crates/xrce-agent/src/daemon/definitions.rs (SystemDefinitions::add_participant_library, plan_participant)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_participant_definition_creates_the_objects_inside_it,
crates/xrce-agent/src/daemon/session.rs::tests::a_participant_definition_with_a_broken_part_creates_nothing,
crates/xrce-agent/src/daemon/definitions.rs::tests::a_participant_library_and_inheritance
Status: done — the <domain_participant_library> with one <domain_participant> is
read; the CREATE also makes the contained topics, publishers, subscribers and
endpoints (ObjectId from the name) and enables them with the Participant. If
a part fails nothing is left (9d5c64dc398).
§7.7.3.6.3 OBJK_DomainParticipant_Binary
Spec: §7.7.3.6.3, p. 33 — “struct OBJK_DomainParticipant_Binary { long domain_id; @optional string<128> domain_reference; @optional string<128> qos_profile_reference; };”
Repo: crates/xrce-agent/src/daemon/binary_forms.rs (participant); crates/xrce-agent/src/daemon/entity_repr.rs (participant)
Tests: crates/xrce-agent/src/daemon/binary_forms.rs::tests::participant_binary_in_both_forms,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_spec_binary_participant_is_read
Status: done — three readings of the blob: Annex A (DHEADER, without domain_id), the
form of the clauses (long domain_id first, FINAL) and the two octets 00 00
of the eProsima client. domain_id of the binary form and that of the
representation (short) must agree, otherwise STATUS_ERR_INVALID_DATA
(f548fee2522).
§7.7.3.6.3 domain_reference
Spec: §7.7.3.6.3, p. 33 — “Any XRCE Topic and Type definitions contained in the referenced domain are considered defined within the scope of the XRCE DomainParticipant and become available as references to construct XRCE objects contained by the DomainParticipant.”
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (participant); crates/xrce-agent/src/daemon/definitions.rs (domain_scope)
Tests: crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_domain_reference_is_resolved_against_the_domain_libraries
Status: done — domain_reference is resolved against the Domains of the <domain_library>; the domain_id of the Domain is the participant’s and must agree with the long domain_id of the binary form; a name in no library is STATUS_ERR_UNKNOWN_REFERENCE (0b67c04800c). The Domain’s topics and types are in the participant’s scope (f59909a7f2b, the next item).
### §7.7.3.6.3 Topics and types of the Domain with the binary form
Spec: §7.7.3.6.3, p. 33 — as above.
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (ParticipantDescription::scope); crates/xrce-agent/src/daemon/session.rs (participant_scopes); crates/xrce-agent/src/daemon/definitions.rs (SystemDefinitions::domain_scope)
Tests: crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_domain_reference_is_resolved_against_the_domain_libraries
Status: done — with the binary form and a domain_reference the Domain’s register_type and topics are in the participant’s scope as with the XML participant with domain_ref; a topic of the participant finds them by name.
### §7.7.3.6.3 qos_profile_reference
Spec: §7.7.3.6.3, p. 33 — “If specified, the corresponding DDS DomainPaticipant shall be created using that Qos. Otherwise, the DomainPaticipant shall be created using the DDS default Qos.”
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (participant, participant_qos_of); crates/xrce-agent/src/daemon/dds_port.rs
(DdsPort::create_participant_with)
Tests: crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_participant_qos_profile_reference_is_applied
Status: done — the participant QoS of the profile (<domain_participant_qos>) applies per
Participant: ENTITY_FACTORY by the Participant (with autoenable_created_entities
false its Publishers, Subscribers and Topics stay disabled), USER_DATA through a
DCPS runtime of its own per domain and value. Another policy in the
participant QoS is not in the XSD of DDS-XML 1.0: crates/xml refuses the file
when it is read (test a_participant_policy_outside_the_schema_is_refused); if a
resolved profile carries one anyway it is STATUS_ERR_INCOMPATIBLE. There is no
policy the schema allows in the participant QoS that the agent cannot apply
(USER_DATA and ENTITY_FACTORY are both applied). A profile without participant QoS
applies nothing; without a reference the DDS default QoS applies (0b67c04800c).
§7.7.3.7 XRCE Topic
§7.7.3.7 OBJK_TOPIC_Representation with participant_id
Spec: §7.7.3.7, p. 33 — “struct OBJK_TOPIC_Representation : OBJK_Representation3_Base { ObjectId participant_id; };”
Repo: crates/xrce/src/object_repr.rs (ObjectVariant::decode_for_kind_at,
ObjectVariantExtra::parent: ObjectId without alignment behind the variant)
Tests: crates/xrce/src/object_repr.rs::tests::topic_representation_matches_the_captured_create_bytes,
crates/xrce/src/object_repr.rs::tests::encode_for_kind_round_trips_every_objk_kind_with_its_own_trailing_field
Status: done
§7.7.3.7 The topic belongs to the DomainParticipant
Spec: §7.7.3.7, p. 33 — “Independent of the representation format, the field participant_id shall contain the ObjectId of an XRCE DomainParticipant object. The referenced or created Topic will belong to the specified DomainParticipant.”
Repo: crates/xrce-agent/src/daemon/session.rs (SessionEngine::plan_dds_create,
branch ObjectKind::Topic; participant_of_create)
Tests: crates/xrce-agent/tests/replay_foreign_session.rs::replay_creates_the_dds_entities_the_real_clients_describe,
crates/xrce-agent/src/daemon/session.rs::tests::a_topic_is_created_by_name_or_by_register_type_ref,
crates/xrce-agent/src/daemon/dds_port.rs::tests::null_port_rejects_topic_before_participant
Status: done — kind and existence of the participant are checked (wrong kind: STATUS_ERR_INVALID_DATA, missing participant: STATUS_ERR_UNKNOWN_REFERENCE), the topic is created with it. Tested are the creation under the participant and the order at port level; there is no test of the failure path of a topic at session level (505c2e56d24).
§7.7.3.7.1 Reference to the name of a topic in the participant
Spec: §7.7.3.7.1, p. 33 — “the object_reference field shall contain the bare name of an XRCE Topic defined in XRCE DomainParticipant identified by the participant_id. The Topic could be defined directly on the XRCE DomainParticipant, or else in the XRCE Domain associated with the DomainParticipant.”
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (topic, branch BY_REFERENCE:
ParticipantScope::topic, then <topic profile_name> of the profile files);
crates/xrce-agent/src/daemon/definitions.rs (SystemDefinitions::scope_of:
topics of the participant and of its Domain)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_topic_is_created_by_name_or_by_register_type_ref,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_reference_is_read_like_the_profile_it_names,
crates/xrce-agent/src/daemon/definitions.rs::tests::a_participant_library_and_inheritance
Status: done — the name is resolved against the topics of the participant
and of its Domain; a name that neither has and the profile files do not have
gives STATUS_ERR_UNKNOWN_REFERENCE. The CREATE test names a topic of the
participant; the topics of the Domain are checked by the test of
definitions.rs on the planning of a participant (9d5c64dc398).
§7.7.3.7.2 XML with one topic
Spec: §7.7.3.7.2, p. 34 — “the string_representation field shall contain a
single
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (topic_from_xml)
Tests: crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_qos_of_a_topic_is_the_default_of_its_endpoints
Status: done — <topic name=… register_type_ref=…/> (the example of the spec) is read: the registration is looked up in the participant and its Domain, its type among the types the agent knows; a registration the participant does not have gives STATUS_ERR_UNKNOWN_REFERENCE. The attribute form (type_name) and the <dataType> of Fast DDS stay readable. The QoS and the QosProfile references of the topic are applied (next item). 9d5c64dc398.
### §7.7.3.7.2 QoS of a topic and QosProfile references
Spec: §7.7.3.7.2, p. 34 — “The string_representation may reference XRCE Types or
QosProfiles already known to the XRCE Agent.”
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (TopicQos, topic_from_xml, endpoint_for_topic); crates/xrce-agent/src/daemon/session.rs (plan_dds_create)
Tests: crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_qos_of_a_topic_is_the_default_of_its_endpoints
Status: done — <topic_qos base_name=…> and qos_profile/qos_profile_ref of the <topic> are read; what the topic states is the default of the endpoints created for it (DDS 1.4 §2.2.2.3.1), the endpoint’s own representation wins; TOPIC_DATA is part of it. 3906abf91b8.
### §7.7.3.7.3 OBJK_Topic_Binary
Spec: §7.7.3.7.3, p. 34 — “struct OBJK_Topic_Binary { string<256> topic_name; @optional string<256> type_reference; @optional DDS:XTypes::TypeIdentifier type_identifier; };”
Repo: crates/xrce-agent/src/daemon/binary_forms.rs (topic, TopicBinary);
crates/xrce-agent/src/daemon/entity_repr.rs (topic, branch InBinary)
Tests: crates/xrce-agent/src/daemon/binary_forms.rs::tests::the_36_octet_example_of_the_clause_is_a_topic,
crates/xrce-agent/src/daemon/binary_forms.rs::tests::annex_a_topic_has_a_dheader,
crates/xrce-agent/src/daemon/binary_forms.rs::tests::string_bounds_are_checked,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_spec_binary_topic_names_its_topic_and_type,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_captured_binary_topic_names_its_topic_and_type,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_big_endian_binary_topic_reads_back
Status: done — XCDR2 per §7.7.3.1.3: topic_name, optional
type_reference, optional type_identifier (TypeIdentifier), string<256>
checked. The spec gives the structure twice: Annex A as APPENDABLE with a
DHEADER, the clause as FINAL without. Both forms are read (Annex A first, the
form of the blob decides, no setting), then the structure of the eProsima
client. The 36 octets of the clause’s example spell “Squere” (the text:
“Square”); the test expects the octets. f548fee2522, 743676fca9f.
§7.7.3.7.3 type_identifier
Spec: §7.7.3.7.3, p. 34 — “The type_identifier, if present, shall contain the DDS-XTYPES TypeIdentifier for the data-type. See clause 7.3.2 of [DDS-XTYPES].”
Repo: crates/xrce-agent/src/daemon/binary_forms.rs (topic:
TypeIdentifier::decode_from); crates/xrce-agent/src/daemon/session.rs
(type_name_of, plan_dds_create, branch Topic)
Tests: crates/xrce-agent/src/daemon/binary_forms.rs::tests::a_topic_with_a_type_identifier_reads_it_and_one_without_a_type_is_refused,
crates/xrce-agent/src/daemon/binary_forms.rs::tests::string_bounds_are_checked,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_spec_binary_topic_may_name_its_type_by_identifier,
crates/xrce-agent/src/daemon/session.rs::tests::a_topic_can_name_its_type_by_type_identifier
Status: done — a present type_identifier is read as the XTypes
TypeIdentifier and compared with the COMPLETE identifiers of the types known
to the agent (OBJK_TYPE of the client, type_files:); an identifier without a
match gives STATUS_ERR_UNKNOWN_REFERENCE. The bounds string<256> are checked.
f548fee2522.
§7.7.3.7.3 Not both missing, type_identifier takes precedence
Spec: §7.7.3.7.3, p. 34 — “Either type_reference or type_identifier may be used to identify the XRCE Type associated with the Topic. Either member may be omitted, but not both. If both are present the type_identifier shall take precedence.”
Repo: crates/xrce-agent/src/daemon/session.rs (plan_dds_create); crates/xrce-agent/src/daemon/binary_forms.rs (topic)
Tests: crates/xrce-agent/tests/spec_items_session.rs::a_binary_topic_takes_its_type_from_the_type_identifier_and_needs_one_of_the_two
Status: done — if both members are missing this is STATUS_ERR_INVALID_DATA (dc2fb4c0cf5, f548fee2522); with type_identifier alone the type is found; if both are there the identifier takes precedence (02c704651e4).
### §7.7.3.7.3 type_reference to a known type
Spec: §7.7.3.7.3, p. 34 — “The type_reference, if present, shall contain the fully qualified name of the type […]. The referenced type shall be known to the XRCE Agent either via pre-configuration, or as a result of a prior create operation executed on the XRCE ProxyClient; see 7.8.3.1.”
Repo: crates/xrce-agent/src/daemon/session.rs (SessionEngine::resolve_type,
find_type_definition, apply_dds_create, branch Topic)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_topic_gets_the_type_its_type_name_names,
crates/xrce-agent/src/daemon/session.rs::tests::a_configured_type_is_known_to_every_client,
crates/xrce-agent/src/daemon/session.rs::tests::a_topic_of_an_unknown_type_is_refused_when_the_agent_is_told_to
Status: done — the type is looked up first among the OBJK_TYPE of the
client (a prior CREATE), then in type_files: (pre-configuration); a topic gets
the definition of the type its name names (test with two types of the client).
An unknown type gives STATUS_ERR_UNKNOWN_REFERENCE (item below). 70963ac46ec.
§7.7.3.7.3 A topic with an unknown type
Spec: §7.7.3.7.3, p. 34 — as above.
Repo: crates/xrce-agent/src/daemon/session.rs (apply_dds_create, branch Topic;
SessionEngineConfig::forward_unknown_topic_types);
crates/xrce-agent/src/daemon/config.rs (key unknown_topic_types)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_topic_of_an_unknown_type_is_refused_when_the_agent_is_told_to,
crates/xrce-agent/src/daemon/config.rs::tests::unknown_topic_types_are_refused_unless_forwarding_is_named
Status: done — the default is the spec: a topic whose type the agent does
not know gives STATUS_ERR_UNKNOWN_REFERENCE, nothing is stored. Named setting:
agent key unknown_topic_types: forward creates the topic and reports
SessionEvent::UnknownTypeForwarding; samples then go out without a key and
without TypeInformation (the eProsima client names types the agent does not
hold). 70963ac46ec, 969c784c93b.
§7.7.3.8 XRCE Publisher
§7.7.3.8 OBJK_PUBLISHER_Representation with participant_id
Spec: §7.7.3.8, p. 34 — “struct OBJK_PUBLISHER_Representation : OBJK_RepresentationBinAndXML_Base { ObjectId participant_id; };”
Repo: crates/xrce/src/object_repr.rs (ObjectVariant::decode_for_kind_at,
ObjectVariantExtra::parent)
Tests: crates/xrce/src/object_repr.rs::tests::encode_for_kind_round_trips_every_objk_kind_with_its_own_trailing_field
Status: done — encoding; the check is in the next item.
§7.7.3.8 The publisher belongs to the DomainParticipant
Spec: §7.7.3.8, p. 34 — “the member participant_id shall contain the ObjectId of an XRCE DomainParticipant object. The referenced or created Publisher shall belong to the specified DomainParticipant.”
Repo: crates/xrce-agent/src/daemon/session.rs (plan_dds_create, branch
Publisher/Subscriber; participant_of_create; apply_dds_create:
DdsPort::create_publisher)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_publisher_or_subscriber_needs_an_existing_participant,
crates/xrce-agent/src/daemon/session.rs::tests::a_publisher_and_a_subscriber_get_a_dds_entity_with_their_policies
Status: done — kind and existence of the participant are checked (missing participant: STATUS_ERR_UNKNOWN_REFERENCE, other kind: STATUS_ERR_INVALID_DATA, nothing is stored); the publisher is created as a DDS Publisher under the participant. 505c2e56d24.
§7.7.3.8.1 XML with one publisher
Spec: §7.7.3.8.1, p. 34–35 — “the string_representation field shall
contain a single
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (container,
container_from_xml: <publisher_qos>, <qos>, nested <data_writer>);
crates/xrce-agent/src/daemon/session.rs (create_embedded)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_publisher_with_nested_data_writers_creates_them,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::an_empty_container_xml_is_a_default_container,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_container_reads_presentation_and_entity_factory
Status: done — <publisher> with <publisher_qos base_name=…> (PARTITION,
GROUP_DATA, PRESENTATION, ENTITY_FACTORY are applied) and the Fast DDS <qos>;
policies a Publisher does not have are named in not_applied. The example (p.
35) closes <publisher name="MyPublisher"/> before its child elements.
9d5c64dc398, b97657ef4ec.
§7.7.3.8.1 publisher_qos and nested DataWriters
Spec: §7.7.3.8.1, p. 35 — as above.
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (container_from_xml:
ContainerDescription::embedded); crates/xrce-agent/src/daemon/session.rs
(create_embedded)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_publisher_with_nested_data_writers_creates_them
Status: done — nested <data_writer> elements are created under the
publisher with the ObjectId of their name (§9.3); if one fails (in the test: a
topic the participant does not have, STATUS_ERR_UNKNOWN_REFERENCE), the CREATE
of the publisher fails and nothing is left. b97657ef4ec.
§7.7.3.8.2 OBJK_Publisher_Binary
Spec: §7.7.3.8.2, p. 35 — “struct OBJK_PUBLISHER_QosBinary { @optional
sequence
Repo: crates/xrce-agent/src/daemon/binary_forms.rs (container);
crates/xrce-agent/src/daemon/entity_repr.rs (container, branch InBinary)
Tests: crates/xrce-agent/src/daemon/binary_forms.rs::tests::publisher_binary_of_annex_a,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::an_annex_a_binary_publisher_gives_its_partitions,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_captured_binary_publisher_has_default_qos
Status: done — partitions and group_data are applied, publisher_name
is read and not used. Annex A (APPENDABLE, DHEADER) is read first, then the form
of the clause without a DHEADER, which the eProsima client sends as well.
f548fee2522.
§7.7.3.9 XRCE Subscriber
§7.7.3.9 OBJK_SUBSCRIBER_Representation with participant_id
Spec: §7.7.3.9, p. 35 — “struct OBJK_SUBSCRIBER_Representation : OBJK_RepresentationBinAndXML_Base { ObjectId participant_id; };”
Repo: crates/xrce/src/object_repr.rs (ObjectVariant::decode_for_kind_at)
Tests: crates/xrce/src/object_repr.rs::tests::subscriber_representation_matches_the_captured_create_bytes
Status: done — encoding.
§7.7.3.9 The subscriber belongs to the DomainParticipant
Spec: §7.7.3.9, p. 35 — “the member participant_id shall contain the ObjectId of an XRCE DomainParticipant object. The referenced or created Subscriber shall belong to the specified DomainParticipant.”
Repo: crates/xrce-agent/src/daemon/session.rs (plan_dds_create, branch
Publisher/Subscriber; participant_of_create; apply_dds_create:
DdsPort::create_subscriber)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_publisher_or_subscriber_needs_an_existing_participant,
crates/xrce-agent/src/daemon/session.rs::tests::a_publisher_and_a_subscriber_get_a_dds_entity_with_their_policies
Status: done — as for the Publisher (the same branch, both kinds in the tests). 505c2e56d24.
§7.7.3.9.1 XML with one subscriber
Spec: §7.7.3.9.1, p. 35–36 — “the string_representation field shall
contain a single
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (container_from_xml); crates/xrce-agent/src/daemon/session.rs (create_embedded)
Tests: crates/xrce-agent/tests/spec_items_session.rs::a_subscriber_in_xml_has_its_qos_and_its_nested_data_reader
Status: done — the code reads <subscriber> in the same branches as <publisher> (9d5c64dc398); the test creates a <subscriber> with <subscriber_qos> and content (02c704651e4).
### §7.7.3.9.1 subscriber_qos and nested DataReaders
Spec: §7.7.3.9.1, p. 36 — as above.
Repo: crates/xrce-agent/src/daemon/session.rs (create_embedded); crates/xrce-agent/src/daemon/entity_repr.rs (container_from_xml)
Tests: crates/xrce-agent/tests/spec_items_session.rs::a_subscriber_in_xml_has_its_qos_and_its_nested_data_reader
Status: done — the code creates the <data_reader> elements of a <subscriber> as the <data_writer> elements of a <publisher> (b97657ef4ec); the test creates a subscriber with a nested <data_reader> by CREATE and checks the partition and the reader (02c704651e4).
### §7.7.3.9.2 OBJK_Subscriber_Binary
Spec: §7.7.3.9.2, p. 36 — “struct OBJK_SUBSCRIBER_QosBinary { @optional
sequence
Repo: crates/xrce-agent/src/daemon/binary_forms.rs (container);
crates/xrce-agent/src/daemon/entity_repr.rs (container, the same reading
routine as for the Publisher)
Tests: crates/xrce-agent/src/daemon/binary_forms.rs::tests::publisher_binary_of_annex_a,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::an_annex_a_binary_publisher_gives_its_partitions,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_captured_binary_publisher_has_default_qos
Status: done — the tests read the form of the Publisher, the reading routine is the same. f548fee2522.
§7.7.3.10 XRCE DataWriter
§7.7.3.10 DATAWRITER_Representation with publisher_id
Spec: §7.7.3.10, p. 36 — “struct DATAWRITER_Representation : OBJK_RepresentationBinAndXML_Base { ObjectId publisher_id; };”
Repo: crates/xrce/src/object_repr.rs (ObjectVariant::decode_for_kind_at)
Tests: crates/xrce/src/object_repr.rs::tests::encode_for_kind_round_trips_every_objk_kind_with_its_own_trailing_field,
crates/xrce/src/object_repr.rs::tests::annex_b_2_3_writer_variant_reads_as_the_blob_and_its_publisher
Status: done — encoding.
§7.7.3.10 The DataWriter belongs to the publisher
Spec: §7.7.3.10, p. 36 — “the member publisher_id shall contain the ObjectId of an XRCE Publisher object. The referenced or created DataWriter shall belong to the specified Publisher.”
Repo: crates/xrce-agent/src/daemon/session.rs (plan_dds_create, branch
DataWriter/DataReader)
Tests: crates/xrce-agent/tests/replay_foreign_session.rs::replay_creates_the_dds_entities_the_real_clients_describe,
crates/xrce-agent/src/daemon/session.rs::tests::an_endpoint_and_its_topic_belong_to_one_participant,
crates/xrce-agent/src/daemon/session.rs::tests::a_publisher_with_nested_data_writers_creates_them
Status: done — kind and existence of the publisher are checked (missing publisher: STATUS_ERR_UNKNOWN_REFERENCE), DataWriter and topic must belong to one participant; the DataWriter inherits PARTITION and GROUP_DATA of the publisher.
§7.7.3.10.1 XML with one data_writer
Spec: §7.7.3.10.1, p. 36–37 — “the string_representation field shall
contain a single
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (endpoint,
endpoint_from_xml: attribute form, Fast DDS form, topic_ref as a name,
<datawriter_qos> / <data_writer_qos>)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_publisher_with_nested_data_writers_creates_them,
crates/xrce-agent/src/daemon/session.rs::tests::a_data_writer_states_its_qos_over_a_profile,
crates/xrce-agent/src/daemon/session.rs::tests::the_formats_of_each_kind_are_enforced,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_attribute_form_still_reads,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_eprosima_element_form_names_topic_type_and_kind,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_qos_profile_reference_applies_the_profile
Status: done — read are the DDS-XML form (<data_writer name=… topic_ref=…>, <datawriter_qos base_name=…>), the attribute form (topic_ref
as an ObjectId in hex, qos_profile, reliability) and the Fast DDS form. A
DataWriter has no BY_REFERENCE representation per §7.7.3.1; the agent key
representation_formats: any admits it (the eProsima client uses it).
9d5c64dc398, 0429eab4fb2.
§7.7.3.10.1 topic_ref as a name and data_writer_qos
Spec: §7.7.3.10.1, p. 36–37 — as above.
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (endpoint_from_xml: topic_ref,
datawriter_qos / data_writer_qos); crates/xrce-agent/src/daemon/session.rs
(resolve_topic)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_publisher_with_nested_data_writers_creates_them,
crates/xrce-agent/src/daemon/session.rs::tests::a_data_writer_states_its_qos_over_a_profile
Status: done — topic_ref="Square" is resolved as the name of a topic of
the participant (0x… stays the ObjectId); <datawriter_qos base_name=…>
applies the profile, policies of the element go over it. The code reads the
spelling <data_writer_qos> of the clause as well; the tests use
<datawriter_qos>. The example (p. 36) names the container “XRCE Susbcriber”.
9d5c64dc398.
§7.7.3.10.2 OBJK_DataWriter_Binary
Spec: §7.7.3.10.2, p. 37 — “struct OBJK_DataWriter_Binary { string topic_name; OBJK_Endpoint_QosBinary endpoint_qos; @optional unsigned long ownership_strength; };”
Repo: crates/xrce-agent/src/daemon/binary_forms.rs (endpoint, endpoint_qos);
crates/xrce-agent/src/daemon/entity_repr.rs (endpoint, branch InBinary,
apply_endpoint_binary)
Tests: crates/xrce-agent/src/daemon/binary_forms.rs::tests::writer_binary_of_annex_a_with_qos,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::an_annex_a_binary_writer_names_its_topic_and_qos,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_annex_b_binary_examples_read_as_their_qos,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_captured_binary_writer_is_reliable_keep_last_transient_local,
crates/xrce-agent/src/daemon/session.rs::tests::annex_b_2_3_create_of_a_binary_data_writer,
crates/xrce-agent/src/daemon/session.rs::tests::annex_b_2_4_create_of_a_binary_data_writer_with_qos
Status: done — topic_name, endpoint_qos and ownership_strength
(unsigned long). Annex A (APPENDABLE, qos optional) and the clause (FINAL,
endpoint_qos mandatory) are both read, Annex A first, the form of the blob
decides (no setting); then the structure of the eProsima client (ObjectId topic_id, ownership_strength with 64 bits). The Annex B.2.3 and B.2.4
examples are tested byte by byte. The form of the clause is not tested for the
DataWriter on its own, it is for the DataReader (item below). f548fee2522,
b91241aebb1.
§7.7.3.10.2 EndpointQosFlags
Spec: §7.7.3.10.2, p. 37 — “@bit_bound(16) bitmask EndpointQosFlags { @position(0) is_reliable, @position(1) is_history_keep_last, @position(2) is_ownership_exclusive, @position(3) is_durability_transient_local, @position(4) is_durability_transient, @position(5) is_durability_persistent, };”
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (spec_flags,
apply_endpoint_binary; flags, endpoint_qos_from_binary)
Tests: crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_captured_binary_writer_is_reliable_keep_last_transient_local,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_binary_writer_with_every_optional_member_reads_back,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::an_annex_a_binary_writer_names_its_topic_and_qos,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_clause_binary_reader_names_its_topic_and_qos
Status: done — bit 1 is is_history_keep_last (clause, eProsima client) or
is_history_keep_all (Annex A, p. 110) depending on the form; the form of the
blob decides (EndpointBinary::bit1_is_keep_all). The tests check both
readings. f548fee2522.
§7.7.3.10.2 OBJK_Endpoint_QosBinary
Spec: §7.7.3.10.2, p. 37 — “struct OBJK_Endpoint_QosBinary {
EndpointQosFlags qos_flags; @optional unsigned short history_depth; @optional
unsigned long deadline_msec; @optional unsigned long lifespan_msec; @optional
sequence
Repo: crates/xrce-agent/src/daemon/binary_forms.rs (endpoint_qos);
crates/xrce-agent/src/daemon/entity_repr.rs (apply_endpoint_binary,
endpoint_qos_from_binary)
Tests: crates/xrce-agent/src/daemon/binary_forms.rs::tests::writer_binary_of_annex_a_with_qos,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_binary_writer_with_every_optional_member_reads_back,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_binary_endpoint_without_qos_gets_the_role_defaults,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_annex_b_binary_examples_read_as_their_qos
Status: done — qos_flags, history_depth, deadline_msec,
lifespan_msec and user_data (all but the flags optional). f548fee2522.
§7.7.3.11 XRCE DataReader
§7.7.3.11 DATAREADER_Representation with subscriber_id
Spec: §7.7.3.11, p. 38 — “struct DATAREADER_Representation : OBJK_RepresentationBinAndXML_Base { ObjectId subscriber_id; };”
Repo: crates/xrce/src/object_repr.rs (ObjectVariant::decode_for_kind_at)
Tests: crates/xrce/src/object_repr.rs::tests::encode_for_kind_round_trips_every_objk_kind_with_its_own_trailing_field,
crates/xrce/src/object_repr.rs::tests::annex_b_2_6_reader_with_default_qos
Status: done — encoding.
§7.7.3.11 The DataReader belongs to the subscriber
Spec: §7.7.3.11, p. 38 — “the member subscriber_id shall contain the ObjectId of an XRCE Subscriber object. The referenced or created DataReader will belong to the specified Subscriber.”
Repo: crates/xrce-agent/src/daemon/session.rs (plan_dds_create, branch
DataWriter/DataReader)
Tests: crates/xrce-agent/tests/replay_foreign_session.rs::replay_creates_the_dds_entities_the_real_clients_describe,
crates/xrce-agent/src/daemon/session.rs::tests::a_client_reads_through_a_preconfigured_data_reader_without_a_create
Status: done — kind and existence of the subscriber are checked; the DataReader inherits PARTITION and GROUP_DATA of the subscriber.
§7.7.3.11.1 XML with one data_reader and filters
Spec: §7.7.3.11.1, p. 38 — “the string_representation field shall contain
a single
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (endpoint_from_xml)
Tests: crates/xrce-agent/tests/spec_items_session.rs::a_data_reader_in_xml_has_its_qos_and_its_content_filter
Status: done — tested are the attribute form, the Fast DDS form with timeBasedFilter, a <data_reader topic_ref=…> from the configuration file and <data_reader_qos> with <content_filter> (02c704651e4). A DataReader has no BY_REFERENCE representation by §7.7.3.1; representation_formats: any admits it.
### §7.7.3.11.1 data_reader_qos and content_filter
Spec: §7.7.3.11.1, p. 38 — “
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (endpoint_from_xml, apply_qos_profile)
Tests: crates/xrce-agent/tests/spec_items_session.rs::a_data_reader_in_xml_has_its_qos_and_its_content_filter
Status: done — <content_filter><expression> sets the reader’s filter (the attribute name is not used), <datareader_qos>/<data_reader_qos> apply profile and own policies; the test reads both from XML and checks QoS and filter at the DDS port (02c704651e4, 9d5c64dc398).
### §7.7.3.11.2 OBJK_DataReader_Binary
Spec: §7.7.3.11.2, p. 38–39 — “struct OBJK_DataReader_Binary { string topic_name; OBJK_Endpoint_QosBinary endpoint_qos; @optional unsigned long timebasedfilter_msec; @optional string contentbased_filter; };”
Repo: crates/xrce-agent/src/daemon/binary_forms.rs (endpoint, endpoint_qos);
crates/xrce-agent/src/daemon/entity_repr.rs (endpoint, branch InBinary,
apply_endpoint_binary)
Tests: crates/xrce-agent/src/daemon/binary_forms.rs::tests::reader_binary_of_the_clause,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_clause_binary_reader_names_its_topic_and_qos,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_annex_b_binary_examples_read_as_their_qos,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_captured_binary_reader_is_reliable_keep_last_transient_local
Status: done — topic_name, endpoint_qos, timebasedfilter_msec and
contentbased_filter (applied as the filter of the reader). The form of the
clause and Annex A are read as for the DataWriter; Annex B.2.6 and B.2.7 are
tested byte by byte. In example B.2.7 the text says five minutes, the table
180000 ms; the octets are read. f548fee2522, b91241aebb1.
§7.7.4 ObjectId
§7.7.4 ObjectId as octet[2] per client and agent
Spec: §7.7.4, p. 39 — “Each ObjectId is scoped to an XRCE Client and Agent pair. […] typedef octet ObjectId [2];”
Repo: crates/xrce/src/object_id.rs (ObjectId::to_bytes, ObjectId::from_bytes)
Tests: crates/xrce/src/object_id.rs::tests::bytes_are_big_endian,
crates/xrce/src/object_info.rs::tests::base_object_request_roundtrip
Status: done — the two octets in order, independent of the E flag.
§7.7.5 ObjectKind
§7.7.5 Values of ObjectKind
Spec: §7.7.5, p. 39 — “XRCE objects are classified into 14 kinds. […] typedef octet ObjectKind; const ObjectKind OBJK_INVALID = 0x00; […] OBJK_PARTICIPANT = 0x01; OBJK_TOPIC = 0x02; OBJK_PUBLISHER = 0x03; OBJK_SUBSCRIBER = 0x04; OBJK_DATAWRITER = 0x05; OBJK_DATAREADER = 0x06; OBJK_TYPE = 0x0A; OBJK_QOSPROFILE = 0x0B; OBJK_APPLICATION = 0x0C; OBJK_AGENT = 0x0D; OBJK_CLIENT = 0x0E;”
Repo: crates/xrce/src/object_kind.rs (constants OBJK_*, ObjectKind::from_u8)
Tests: crates/xrce/src/object_kind.rs::tests::all_spec_kinds_roundtrip,
crates/xrce/src/object_kind.rs::tests::raw_const_values_match_spec,
crates/xrce/src/object_kind.rs::tests::unknown_byte_rejected
Status: done — 13 values: the twelve of the text and OBJK_OTHER = 0x0F
(Annex A). The text names 14 kinds and lists 12. daf2a618f74.
§7.7.6 ObjectIdPrefix
§7.7.6 ObjectId from prefix and ObjectKind
Spec: §7.7.6, p. 39 — “The ObjectId of an object is composed combining 12 bits from the ObjectIdPrefix and four bits from the ObjectKind. […] typedef octet ObjectIdPrefix [2]; […] object_id[0] = objectid_prefix[0] object_id[1] = (objectid_prefix[1]&0xF0) + object_kind”
Repo: crates/xrce/src/object_id.rs (ObjectId::new, ObjectId::kind,
ObjectId::from_reference)
Tests: crates/xrce/src/object_id.rs::tests::new_packs_kind_into_lower_4_bits,
crates/xrce/src/object_id.rs::tests::bytes_are_big_endian,
crates/xrce/src/object_id.rs::tests::from_reference_matches_the_examples_of_the_spec
Status: done — in the code the prefix is the 12-bit number raw_id; a type
ObjectIdPrefix is missing. ObjectId::from_reference forms the prefix from
the first 12 bits of the MD5 (§9.3, 468aa0940da). ObjectId::new_with_mask and
kind_mask read bit 15 as “assigned by the client”; the spec does not say that
and the session does not use it.
§7.7.7 ResultStatus
§7.7.7 StatusValue
Spec: §7.7.7, p. 40 — “@bit_bound(8) enum StatusValue { @value(0x00) STATUS_OK, @value(0x01) STATUS_OK_MATCHED, @value(0x80) STATUS_ERR_DDS_ERROR, @value(0x81) STATUS_ERR_MISMATCH, @value(0x82) STATUS_ERR_ALREADY_EXISTS, @value(0x83) STATUS_ERR_DENIED, @value(0x84) STATUS_ERR_UNKNOWN_REFERENCE, @value(0x85) STATUS_ERR_INVALID_DATA, @value(0x86) STATUS_ERR_INCOMPATIBLE, @value(0x87) STATUS_ERR_RESOURCES };”
Repo: crates/xrce/src/object_info.rs (ResultStatusCode)
Tests: crates/xrce/src/object_info.rs::tests::result_status_code_all_ten_spec_values_roundtrip,
crates/xrce/src/object_info.rs::tests::result_status_code_unknown_byte_rejected
Status: done
§7.7.7 ResultStatus
Spec: §7.7.7, p. 40 — “struct ResultStatus { StatusValue status; octet implementation_status; };”
Repo: crates/xrce/src/object_info.rs (ResultStatus, encode_into, decode_at);
crates/xrce/src/encoding.rs (UnannotatedTypes)
Tests: crates/xrce/src/object_info.rs::tests::result_status_roundtrip,
crates/xrce/src/object_info.rs::tests::result_status_decode_short_returns_eof,
crates/xrce/tests/unannotated_types.rs::the_default_is_appendable_with_a_dheader,
crates/xrce/tests/unannotated_types.rs::the_final_setting_writes_the_reference_implementations_octets,
crates/xrce/tests/unannotated_types.rs::both_forms_are_read_in_either_setting
Status: done — Annex A gives ResultStatus no @extensibility: the default
is APPENDABLE with a DHEADER per DDS-XTypes 1.3 §7.3.1.2.1.8 (6 octets, 10 in
the BaseObjectReply). The octets of the reference implementation (2 and 6,
without a DHEADER) are written by the setting
encoding::UnannotatedTypes::Final (agent key unannotated_types: final); both
forms are read in either setting. 7f85e76debd, 220857a1e90.
§7.7.7 Table 2 STATUS_OK
Spec: §7.7.7, Table 2, p. 41 — “Indicates a successful execution of the operation”.
Repo: crates/xrce-agent/src/daemon/session.rs (status_reply, agent_status_reply)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::create_client_happy_path_registers_and_replies_ok,
crates/xrce-agent/src/daemon/session.rs::tests::a_successful_write_is_answered_with_status_ok,
crates/xrce-agent/tests/replay_foreign_session.rs::replay_matches_the_real_agents_create_client_create_and_delete_replies
Status: done — a successful WRITE_DATA is answered with STATUS_OK as well (869304e6b63); the eProsima agent does not reply to it.
§7.7.7 Table 2 STATUS_OK_MATCHED
Spec: §7.7.7, Table 2, p. 41 — “Indicates a successful execution of a create or update operation on a resource when the resource already existed on the Agent and the resource state already matched the one requested by the operation.”
Repo: crates/xrce/src/object_store.rs (CreateOutcome::Reused);
crates/xrce-agent/src/daemon/session.rs (handle_create)
Tests: crates/xrce/src/object_store.rs::tests::create_reuse_returns_equal_marker,
crates/xrce-agent/src/daemon/session.rs::tests::a_create_with_reuse_and_replace_updates_the_object
Status: done — a representation equal to that of the existing object gives
STATUS_OK_MATCHED with reuse and changes nothing. Table 5 spells
STATUS_OK_MATCHES, StatusValue in Annex A and in the code is STATUS_OK_MATCHED
(the name only). 3b066516f69.
§7.7.7 Table 2 STATUS_ERR_DDS_ERROR
Spec: §7.7.7, Table 2, p. 41 — “Indicates a failure in the execution of the operation caused by an error when creating or operating on the DDS resource related to the operation.”
Repo: crates/xrce-agent/src/daemon/session.rs (dds_port_error_status,
apply_dds_create); crates/xrce-agent/src/daemon/dds_port.rs
(DdsPortError::DdsError, DdsPort::enable)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_dds_entity_is_enabled_when_the_creation_has_succeeded
Status: done — if the DDS side of a CREATE cannot be enabled (enable) or
created, the reply is STATUS_ERR_DDS_ERROR, nothing is stored and the DDS side
is deleted. 70963ac46ec.
§7.7.7 Table 2 STATUS_ERR_MISMATCH
Spec: §7.7.7, Table 2, p. 41 — “Indicates a failure in the execution of a create or update operation on a resource when the resource already existed on the Agent, the state did not match the one requested by the operation, and it was not possible to change the state of the resource.”
Repo: crates/xrce/src/object_store.rs (CreateOutcome::Reused { equal: false });
crates/xrce-agent/src/daemon/session.rs (handle_create)
Tests: crates/xrce/src/object_store.rs::tests::create_reuse_returns_equal_marker,
crates/xrce-agent/src/daemon/session.rs::tests::a_create_with_reuse_and_replace_updates_the_object
Status: done — reuse without replace and an unequal representation give
STATUS_ERR_MISMATCH; with replace the object is replaced (Table 5).
3b066516f69.
§7.7.7 Table 2 STATUS_ERR_ALREADY_EXISTS
Spec: §7.7.7, Table 2, p. 41 — “Indicates a failure in the execution of a create operation due to the fact that the resource already existed.”
Repo: crates/xrce/src/object_store.rs (CreateOutcome::Conflict)
Tests: crates/xrce/src/object_store.rs::tests::create_strict_on_existing_returns_conflict
Status: done
§7.7.7 Table 2 STATUS_ERR_DENIED
Spec: §7.7.7, Table 2, p. 41 — “Indicates a failure in the execution of an operation due to lack of permissions.”
Repo: crates/xrce-agent/src/daemon/access.rs (AccessController);
crates/xrce-agent/src/daemon/session.rs (check before CREATE, DELETE,
GET_INFO, WRITE_DATA, READ_DATA)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_client_key_not_configured_in_the_agent_is_denied,
crates/xrce-agent/src/daemon/session.rs::tests::create_without_permission_is_denied_and_stores_nothing,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_and_delete_without_permission_are_denied,
crates/xrce-agent/src/daemon/session.rs::tests::write_and_read_without_permission_are_denied,
crates/xrce-agent/src/daemon/session.rs::tests::client_properties_are_checked_against_what_the_agent_requires,
crates/xrce-agent/src/daemon/session.rs::tests::an_update_needs_the_permission_to_update
Status: done — a ClientKey that is not in authorized_client_keys, a
missing client property and an operation without permission give
STATUS_ERR_DENIED; nothing is stored. 1c430db8a67, 5f7a8652d95.
§7.7.7 Table 2 STATUS_ERR_UNKNOWN_REFERENCE
Spec: §7.7.7, Table 2, p. 41 — “Indicates a failure in the execution of an operation due to the fact that the referenced resource is not known to the Agent.”
Repo: crates/xrce-agent/src/daemon/session.rs (dds_port_error_status,
handle_delete, handle_get_info, participant_of_create)
Tests: crates/xrce-agent/src/daemon/dcps_bridge.rs::tests::full_chain_against_a_real_leased_domain,
crates/xrce-agent/src/daemon/dds_port.rs::tests::null_port_rejects_topic_before_participant,
crates/xrce-agent/src/daemon/session.rs::tests::a_publisher_or_subscriber_needs_an_existing_participant,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_a_missing_object_is_an_info_with_unknown_reference,
crates/xrce-agent/src/daemon/session.rs::tests::delete_client_needs_a_proxy_client
Status: done — the tests check DdsPortError::UnknownReference, a missing
participant, a missing object in GET_INFO and the deletion of the client without
a ProxyClient; dds_port_error_status maps the port error to the value.
§7.7.7 Table 2 STATUS_ERR_INVALID_DATA
Spec: §7.7.7, Table 2, p. 41 — “Indicates a failure in the execution due to wrong on invalid input parameter data.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create,
handle_read_data, refuse_unreadable)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::read_data_with_an_unhonorable_content_filter_is_rejected_not_silently_unfiltered,
crates/xrce-agent/src/daemon/session.rs::tests::a_request_that_cannot_be_read_is_answered_invalid_data,
crates/xrce-agent/src/daemon/session.rs::tests::a_create_without_a_base_object_request_is_answered,
crates/xrce-agent/src/daemon/session.rs::tests::the_formats_of_each_kind_are_enforced
Status: done — an unreadable body of CREATE, READ_DATA, WRITE_DATA, DELETE and GET_INFO, a representation in a format the kind does not have and a filter that cannot be honored give STATUS_ERR_INVALID_DATA. 97de94f63e4, 0429eab4fb2.
§7.7.7 Table 2 STATUS_ERR_INCOMPATIBLE
Spec: §7.7.7, Table 2, p. 41 — “Indicates a failure in the execution of an operation due to an incompatibility between the Client and the Agent.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create_client,
handle_get_info: version in client_info)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::create_client_rejects_wrong_major_version,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_the_agent_checks_the_version_in_client_info
Status: done
§7.7.7 Table 2 STATUS_ERR_RESOURCES
Spec: §7.7.7, Table 2, p. 41 — “Indicates a failure in the execution of an operation due to a resource error on the Agent.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create_client, create_core, handle_message, emit_possibly_fragmented, data_submessages)
Tests: crates/xrce-agent/tests/spec_items_session.rs::create_client_over_max_clients_is_a_resource_error, crates/xrce-agent/tests/spec_items_session.rs::create_over_max_objects_per_client_is_a_resource_error, crates/xrce-agent/tests/spec_items_session.rs::a_full_reorder_buffer_of_a_reliable_stream_is_a_resource_error, crates/xrce-agent/tests/spec_items_session.rs::a_fragment_run_over_its_limit_is_a_resource_error, crates/xrce-agent/src/daemon/session.rs::tests::a_sample_too_large_for_data_is_reported
Status: done — the agent sends the value at max_clients, max_objects_per_client, a full receiver buffer, a FRAGMENT run over the limit and a sample that does not fit a DATA; each of these paths has a test (8bcb1d00161, 02c704651e4). An INFO that cannot be encoded has no test.
§7.7.8 BaseObjectRequest
§7.7.8 BaseObjectRequest
Spec: §7.7.8, p. 41 — “@extensibility(FINAL) struct BaseObjectRequest { RequestId request_id; ObjectId object_id; };”
Repo: crates/xrce/src/object_info.rs (BaseObjectRequest)
Tests: crates/xrce/src/object_info.rs::tests::base_object_request_roundtrip,
crates/xrce/src/object_info.rs::tests::base_object_request_decode_short_returns_eof
Status: done — FINAL, 4 octets without a DHEADER.
§7.7.8 request_id correlates reply and request
Spec: §7.7.8, p. 41–42 — “request_id (RequestId) identifies each request. It is used to correlate a reply with the related request. It is scoped to each XRCE Client and Agent pair. Note that it is possible to reuse a value of the request_id for future requests as long as the previous request with that value is known by Client and Agent to no longer be active.”
Repo: crates/xrce-client/src/lib.rs (allocate_request_id, request_id_octets);
crates/xrce-agent/src/daemon/session.rs (status_reply)
Tests: crates/xrce-client/src/lib.rs::tests::full_lifecycle_creates_unique_request_ids_and_real_submessages,
crates/xrce-agent/tests/replay_foreign_session.rs::replay_matches_the_real_agents_create_client_create_and_delete_replies
Status: done
§7.7.8 object_id as target and prefix
Spec: §7.7.8, p. 42 — “object_id (ObjectId) the ObjectId that is the target of the request. For requests that create objects, the object_id conveys the ObjectIdPrefix for the created object.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create: ObjectId from the
prefix of the request and the kind of the representation)
Tests: crates/xrce-agent/tests/replay_foreign_session.rs::replay_matches_the_real_agents_create_client_create_and_delete_replies,
crates/xrce-agent/src/daemon/session.rs::tests::the_object_id_is_the_prefix_and_the_kind_of_the_representation
Status: done — for the formation of the ObjectId at CREATE see the item on
§7.8.3.1 “input_objectid”. 70963ac46ec.
§7.7.9 BaseObjectReply
§7.7.9 BaseObjectReply
Spec: §7.7.9, p. 42 — “@extensibility(FINAL) struct BaseObjectReply { BaseObjectRequest related_request; ResultStatus result; };”
Repo: crates/xrce/src/object_info.rs (BaseObjectReply)
Tests: crates/xrce/src/object_info.rs::tests::base_object_reply_roundtrip,
crates/xrce/tests/unannotated_types.rs::both_forms_are_read_in_either_setting
Status: done — FINAL: related_request (4 octets) and result; the
ResultStatus inside carries its DHEADER (item ResultStatus).
§7.7.9 related_request
Spec: §7.7.9, p. 42 — “related_request contains the request_id and object_id of the request that caused the reply to be sent […]. For requests that create objects, the object_id conveys the desired ObjectId for the created object.”
Repo: crates/xrce-agent/src/daemon/session.rs (status_reply)
Tests: crates/xrce-agent/tests/replay_foreign_session.rs::replay_matches_the_real_agents_create_client_create_and_delete_replies
Status: done
§7.7.9 status on success and failure
Spec: §7.7.9, p. 42 — “If the operation succeeded the StatusValue shall be set to STATUS_OK or STATUS_OK_MATCHED. If it failed it shall be set to the value that corresponds to the type of error encountered.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create: mapping of
CreateOutcome to the status)
Tests: crates/xrce-agent/tests/replay_foreign_session.rs::replay_matches_the_real_agents_create_client_create_and_delete_replies,
crates/xrce-agent/src/daemon/session.rs::tests::a_create_with_reuse_and_replace_updates_the_object
Status: done — the text names the members status and
implementation_status; the structure has result.
§7.7.9 implementation_status
Spec: §7.7.9, p. 42 — “implementation_status (octet) provides an implementation-specific (vendor-specific) return status. The value is scoped by the XrceVendorId of the Agent. It shall only be interpreted by clients that understand the implementation status values of the XrceVendorId of the Agent that returned it.”
Repo: crates/xrce-agent/src/daemon/session.rs (status_reply: value 0);
crates/xrce-client/src/lib.rs (handle_status does not evaluate it)
Tests: crates/xrce/src/object_info.rs::tests::result_status_roundtrip
Status: done
§7.7.10 RelatedObjectRequest
§7.7.10 RelatedObjectRequest as a typedef
Spec: §7.7.10, p. 42 — “typedef RelatedObjectRequest BaseObjectRequest; The interpretation is the same as for the related_request that appears in the BaseObjectReply”.
Repo: crates/xrce/src/object_info.rs (RelatedObjectRequest)
Tests: crates/xrce/src/object_info.rs::tests::related_object_request_is_base_object_request
Status: done — the spec writes the typedef in reverse order; typedef BaseObjectRequest RelatedObjectRequest is meant.
§7.7.11 CreationMode
§7.7.11 CreationMode
Spec: §7.7.11, p. 43 — “struct CreationMode { boolean reuse; boolean replace; };”
Repo: crates/xrce/src/object_store.rs (CreationMode);
crates/xrce/src/submessages/create.rs (CREATE_FLAG_REUSE,
CREATE_FLAG_REPLACE)
Tests: crates/xrce/src/submessages/create.rs::tests::create_roundtrip_carries_reuse_replace_flags,
crates/xrce-agent/src/daemon/session.rs::tests::a_create_with_reuse_and_replace_updates_the_object
Status: done — on the wire as flags of CREATE (§8.3.5.2.1); reuse and
replace act per Table 5 (3b066516f69).
§7.7.12 ActivityInfoVariant
§7.7.12 InfoMask
Spec: §7.7.12, p. 43 — “bitmask InfoMask { @position(0) INFO_CONFIGURATION, @position(1) INFO_ACTIVITY };”
Repo: crates/xrce/src/object_info.rs (InfoMask);
crates/xrce-agent/src/daemon/session.rs (handle_get_info, object_info:
configuration and activity by the mask)
Tests: crates/xrce/src/object_info.rs::tests::info_mask_bits_and_wire_form,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_an_object_returns_the_object_variant_it_was_created_with,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_a_data_writer_reports_its_activity,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_without_an_info_mask_is_invalid_data
Status: done — InfoMask is a 32-bit bitmask (INFO_CONFIGURATION bit 0,
INFO_ACTIVITY bit 1, 32 bits per XTypes without @bit_bound) and is read from
GET_INFO; a GET_INFO without a mask gives STATUS_ERR_INVALID_DATA. ca0cf7e08bf.
§7.7.12 AGENT_ActivityInfo
Spec: §7.7.12, p. 43 — “@extensibility(APPENDABLE) struct AGENT_ActivityInfo { short availability; TransportLocatorSeq address_seq; };”
Repo: crates/xrce/src/object_info.rs (ActivityInfoVariant::Agent);
crates/xrce-agent/src/daemon/session.rs (agent_object_info)
Tests: crates/xrce/src/object_info.rs::tests::agent_activity_info_has_a_dheader_and_a_locator_sequence,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_the_agent_in_a_session_returns_activity_and_representation,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_without_a_session_is_answered_for_the_agent_only
Status: done — @extensibility(APPENDABLE): discriminator OBJK_AGENT
(0x0D; Annex A writes OBJECTID_AGENT, an ObjectId of two octets and no value
of ObjectKind), DHEADER, short availability and a TransportLocatorSeq from
the listeners of the agent. ca0cf7e08bf, 299b3a41398.
§7.7.12 DATAREADER_ActivityInfo
Spec: §7.7.12, p. 43 — “@extensibility(APPENDABLE) struct DATAREADER_ActivityInfo { short highest_acked_num; };”
Repo: crates/xrce/src/object_info.rs (ActivityInfoVariant::DataReader
l. 524, encode_into l. 574, decode_at l. 633);
crates/xrce-agent/src/daemon/session.rs (object_info l. 3002)
Tests: crates/xrce/src/object_info.rs::tests::data_reader_activity_info_is_a_dheader_and_a_short,
crates/xrce/src/object_info.rs::tests::appended_members_of_an_activity_are_skipped,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_a_data_reader_reports_its_activity
Status: done — DHEADER and short highest_acked_num; members that a newer
version appends are skipped by the reader through the DHEADER. The agent sends
the activity in the INFO to a GET_INFO of a DataReader: highest_acked_num is
the highest sequence number the client has acknowledged on the reliable stream
the READ_DATA delivers on, otherwise 0. The spec does not define the value; not
measured against another agent. Commit ca0cf7e08bf.
§7.7.12 DATAWRITER_ActivityInfo
Spec: §7.7.12, p. 43 — “@extensibility(APPENDABLE) struct DATAWRITER_ActivityInfo { unsigned long long sample_seq_num; short stream_seq_num; };”
Repo: crates/xrce/src/object_info.rs (ActivityInfoVariant::DataWriter
l. 529, encode_into l. 574, decode_at l. 633);
crates/xrce-agent/src/daemon/session.rs (object_info l. 3002,
dds_write_and_report l. 3282)
Tests: crates/xrce/src/object_info.rs::tests::data_writer_activity_info_is_a_dheader_a_long_long_and_a_short,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_a_data_writer_reports_its_activity
Status: done — DHEADER, unsigned long long sample_seq_num (aligned to 4)
and short stream_seq_num. The agent counts the samples written per DataWriter
(sample_seq_num) and keeps the sequence number in the header of the last
WRITE_DATA message (stream_seq_num). The spec does not define either value;
not measured against another agent. Commit ca0cf7e08bf.
§7.7.12 ActivityInfoVariant as a union
Spec: §7.7.12, p. 43–44 — “union ActivityInfoVariant (ObjectKind) { case OBJK_DATAWRITER : DATAWRITER_ActivityInfo data_writer; case OBJK_DATAREADER : DATAREADER_ActivityInfo data_reader; };”
Repo: crates/xrce/src/object_info.rs (ActivityInfoVariant l. 512,
discriminator l. 540, encode_into l. 574, decode_at l. 633)
Tests: crates/xrce/src/object_info.rs::tests::agent_activity_info_has_a_dheader_and_a_locator_sequence,
crates/xrce/src/object_info.rs::tests::activity_info_decode_unknown_discriminator_rejected,
crates/xrce/src/object_info.rs::tests::activity_info_decode_truncated_rejected,
crates/xrce/src/object_info.rs::tests::appended_members_of_an_activity_are_skipped
Status: done — the discriminator is the octet of the ObjectKind
(OBJK_DATAWRITER 0x05, OBJK_DATAREADER 0x06); the members carry the DHEADER; an
unknown discriminator is an error. Annex A (p. 113) has the agent’s case in
addition and writes OBJECTID_AGENT, an ObjectId of two octets and no value of
ObjectKind; the code takes OBJK_AGENT (0x0D) as the discriminator of
AGENT_ActivityInfo. The IDL of the clause lacks the word switch. Commit
ca0cf7e08bf.
§7.7.13 ObjectInfo
§7.7.13 ObjectInfo with activity and config
Spec: §7.7.13, p. 44 — “@extensibility(FINAL) struct ObjectInfo { @optional ActivityInfoVariant activity; @optional ObjectVariant config; };”
Repo: crates/xrce/src/object_info.rs (ObjectInfo l. 760, encode_into
l. 794, decode_at l. 834, ObjectConfig l. 690);
crates/xrce-agent/src/daemon/session.rs (object_info l. 3002, answer_info
l. 2962)
Tests: crates/xrce/src/object_info.rs::tests::object_info_puts_the_activity_before_the_config,
crates/xrce/src/object_info.rs::tests::the_config_of_a_topic_is_the_object_variant_it_was_created_with,
crates/xrce/src/object_info.rs::tests::the_config_of_the_agent_is_its_agent_representation,
crates/xrce/src/object_info.rs::tests::an_empty_object_info_is_two_presence_octets,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_an_object_returns_the_object_variant_it_was_created_with
Status: done — activity before config, one presence octet for each of
the two @optional; config is an ObjectVariant with its ObjectKind (for
the agent the AGENT_Representation, for an object the representation it was
created with). Alignment is counted from the start of the payload, the byte
order follows the E flag. Commits ca0cf7e08bf, b9255734bfb.
§7.7.14 ReadSpecification
§7.7.14 DataDeliveryControl
Spec: §7.7.14, p. 44 — “@extensibility(APPENDABLE) struct DataDeliveryControl { unsigned short max_samples; unsigned short max_elapsed_time; unsigned short max_bytes_per_second; unsigned short min_pace_period; // milliseconds };”
Repo: crates/xrce/src/submessages/read_data.rs (DataDeliveryControl
l. 60, encode_into l. 79, decode l. 93, DeliveryControlForm l. 127);
crates/xrce-client/src/lib.rs (XrceClient::set_delivery_control_form l. 372)
Tests: crates/xrce/src/submessages/read_data.rs::tests::read_data_matches_the_captured_read_data_example,
crates/xrce/src/submessages/read_data.rs::tests::annex_b_4_2_read_data_with_filter_and_delivery_control
Status: done — four unsigned short in this order, with a DHEADER
(APPENDABLE). The form without a DHEADER that the eProsima capture shows is the
named setting DeliveryControlForm::Bare
(XrceClient::set_delivery_control_form); the reader takes both forms. Commit
b589558e671.
§7.7.14 DHEADER of DataDeliveryControl
Spec: §7.7.14, p. 44 — as above; Annex B.4.2, p. 151–152, shows the DHEADER.
Repo: crates/xrce/src/submessages/read_data.rs
(ReadSpecification::encode_into l. 151, decode l. 204)
Tests: crates/xrce/src/submessages/read_data.rs::tests::annex_b_4_2_read_data_with_filter_and_delivery_control,
crates/xrce/src/submessages/read_data.rs::tests::read_data_matches_the_captured_read_data_example
Status: done — a DHEADER with the length 8, aligned to 4, is written.
Annex B.4.2 also sets bit 31 in the DHEADER (0x80000008), which XCDR2 does not
have in a DHEADER; the reader does not take it as part of the length. Reading
works with and without a DHEADER. Commit b589558e671.
§7.7.14 ReadSpecification
Spec: §7.7.14, p. 44 — “@extensibility(FINAL) struct ReadSpecification { StreamId preferred_stream_id; DataFormat data_format; @optional string content_filter_expression; @optional DataDeliveryControl delivery_control; };”
Repo: crates/xrce/src/submessages/read_data.rs (ReadSpecification
l. 114, encode_into l. 151, decode l. 204, ReadDataPayload l. 312)
Tests: crates/xrce/src/submessages/read_data.rs::tests::read_data_matches_the_captured_read_data_example,
crates/xrce/src/submessages/read_data.rs::tests::read_data_full_spec_roundtrip,
crates/xrce/src/submessages/read_data.rs::tests::annex_b_4_2_read_data_with_filter_and_delivery_control
Status: done — order of the fields, presence octets of the two
@optional, values of data_format after Annex A and an XCDR2 string (see the
items on data_format, content_filter_expression and DataDeliveryControl). Commit
b589558e671.
§7.7.14 Values of data_format
Spec: §7.7.14, p. 44; Annex A, p. 113–114 — “const DataFormat FORMAT_DATA = 0x00; const DataFormat FORMAT_SAMPLE = 0x02; const DataFormat FORMAT_DATA_SEQ = 0x08; const DataFormat FORMAT_SAMPLE_SEQ = 0x0A; const DataFormat FORMAT_PACKED_SAMPLES = 0x0E;”
Repo: crates/xrce/src/submessages/write_data.rs (DataFormat l. 52, raw
l. 69, from_raw l. 78); crates/xrce/src/submessages/read_data.rs
(ReadSpecification::encode_into l. 151);
crates/xrce-agent/src/daemon/session.rs (data_submessages l. 3581)
Tests: crates/xrce/src/submessages/read_data.rs::tests::the_data_format_octet_has_the_values_of_annex_a,
crates/xrce/src/submessages/read_data.rs::tests::read_spec_rejects_reserved_data_format,
crates/xrce/src/submessages/write_data.rs::tests::data_format_raw_roundtrip,
crates/xrce-agent/src/daemon/session.rs::tests::a_read_for_data_seq_is_answered_with_one_data_seq,
crates/xrce-agent/src/daemon/session.rs::tests::a_read_for_sample_is_answered_with_a_sample_each,
crates/xrce-agent/src/daemon/session.rs::tests::a_read_for_sample_seq_is_answered_with_one_sample_seq,
crates/xrce-agent/src/daemon/session.rs::tests::a_read_for_packed_samples_is_answered_with_one_packed_samples
Status: done — DataFormat::raw gives 0x00, 0x02, 0x08, 0x0A and 0x0E;
from_raw reads the same values, bits outside FORMAT_MASK (0x0E) and reserved
combinations are ValueOutOfRange. The agent delivers DATA in the requested
format. Commits b589558e671, fd5253ca805.
§7.7.14 Encoding of content_filter_expression
Spec: §7.7.14, p. 44 — “@optional string content_filter_expression;” (XCDR2 by §7.7); Annex B.4.2, p. 151–152: padding byte 15, length 6 for “x>100”.
Repo: crates/xrce/src/submessages/read_data.rs
(ReadSpecification::encode_into l. 151, decode l. 204)
Tests: crates/xrce/src/submessages/read_data.rs::tests::the_content_filter_is_a_string_with_a_nul_and_an_aligned_length,
crates/xrce/src/submessages/read_data.rs::tests::annex_b_4_2_read_data_with_filter_and_delivery_control
Status: done — XCDR2 string: the length is an unsigned long, aligned to
4 (from the start of the payload), and counts the NUL; the NUL follows the
characters. Annex B.4.2 (padding octet 15, length 6 for “x>100”) is pinned by a
test with the bytes. Commit b589558e671.
§7.8.1 Use of the ClientKey
§7.8.1 The ClientKey identifies the client and carries permissions
Spec: §7.8.1, p. 44 — “The ClientKey is assigned to each client. The ClientKey uniquely identifies the client to a particular agent. The ClientKey is associated with a set of permissions for the client within the agent.”
Repo: crates/xrce-agent/src/lib.rs (XrceAgent::clients l. 102);
crates/xrce-agent/src/daemon/transport.rs (PeerTable::resolve l. 111);
crates/xrce-agent/src/daemon/access.rs (AccessController::permits l. 212,
Rule l. 125)
Tests: crates/xrce-agent/src/lib.rs::tests::multiple_clients_isolated,
crates/xrce-agent/src/daemon/transport.rs::tests::peer_table_resolves_header_client_key_directly,
crates/xrce-agent/src/daemon/access.rs::tests::a_controller_without_rules_restricts_nothing,
crates/xrce-agent/src/daemon/access.rs::tests::the_first_matching_rule_decides_and_no_match_denies,
crates/xrce-agent/src/daemon/session.rs::tests::create_without_permission_is_denied_and_stores_nothing,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_and_delete_without_permission_are_denied,
crates/xrce-agent/src/daemon/session.rs::tests::write_and_read_without_permission_are_denied
Status: done — the ClientKey identifies the client. The permissions are in
the AccessController (§7.4): rules per ClientKey for operation, ObjectKind, DDS
domain and topic (configuration key access_rules); the first matching rule
decides, without a match the operation is refused, without rules everything is
allowed. An operation without permission gets STATUS_ERR_DENIED. The rules are
read at start-up; a reload with SIGHUP does not change them. Commits
1c430db8a67, 5f7a8652d95.
§7.8.1 The ClientKey is secret and configured in client and agent
Spec: §7.8.1, p. 45 — “The ClientKey shall be considered secret. It must be configured both on the Client and in the Agent. The creation and configuration are outside the scope of this specification.”
Repo: crates/xrce-agent/src/daemon/access.rs
(AccessController::client_authorized l. 193, parse_client_key l. 227);
crates/xrce-agent/src/daemon/config.rs (authorized_client_keys);
crates/xrce-agent/src/daemon/session.rs (handle_create_client l. 1227)
Tests: crates/xrce-agent/src/daemon/access.rs::tests::only_configured_client_keys_are_authorized,
crates/xrce-agent/src/daemon/access.rs::tests::a_client_key_is_read_in_wire_order,
crates/xrce-agent/src/daemon/session.rs::tests::a_client_key_not_configured_in_the_agent_is_denied,
crates/xrce-agent/src/daemon/session.rs::tests::without_configured_client_keys_every_key_is_accepted
Status: done — configuration key authorized_client_keys (four octets in
the order of transmission); a ClientKey outside the list gets STATUS_ERR_DENIED
and no session, without a list the agent accepts every key. The client carries
its ClientKey (XrceClient::new). The protection of the ClientKey on the
transport after §8.3.2.4 is the listeners kind: dtls and kind: tls. Commits
1c430db8a67, 5f7a8652d95, eb44fbbf575.
§7.8.1 The ClientKey is not interpreted
Spec: §7.8.1, p. 45 — “The ClientKey shall not be interpreted.”
Repo: crates/xrce/src/header.rs (ClientKey l. 110)
Tests: crates/xrce/src/handshake.rs::tests::client_representation_decodes_the_captured_create_client_prefix
Status: done
§7.8.1 Operations only with an existing ProxyClient
Spec: §7.8.1, p. 45 — “With the exception of the operations create_client and get_info on the XRCE Root, all other operations expect that the ClientKey references an already exiting XRCE ProxyClient. If this is not the case, the operation shall fail.”
Repo: crates/xrce-agent/src/lib.rs (XrceAgent::create_object l. 240,
pull_sample l. 313: AgentError::UnknownClient);
crates/xrce-agent/src/daemon/session.rs (create_core l. 1583,
handle_delete l. 2733)
Tests: crates/xrce-agent/src/lib.rs::tests::create_object_for_unknown_client_rejected,
crates/xrce-agent/src/lib.rs::tests::pull_sample_unknown_client_rejected,
crates/xrce-agent/src/daemon/session.rs::tests::delete_client_needs_a_proxy_client
Status: done — an operation for a ClientKey without a ProxyClient is not
carried out; the session answers with STATUS_ERR_UNKNOWN_REFERENCE.
§7.8.1 STATUS_ERR_NOCLIENT or a silent drop
Spec: §7.8.1, p. 45 — “To avoid information leakage that could compromise security, the failure to locate a ClientKey may in some cases result in a returnValue having STATUS_ERR_NOCLIENT while in others it may silently drop the connection to the client.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_message, drops_for_unknown_client, SessionEvent::NoClient)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_message_to_an_unknown_client_key_is_dropped_and_counted
Status: done — §7.8.1 gives two ways: STATUS_ERR_NOCLIENT or a silent drop. StatusValue (Annex A) has no such value, the agent drops the message without an answer and reports SessionEvent::NoClient; create_client and get_info are exempt, delete_client gets its answer by §7.8.2.3. 458b32f4346.
### §7.8.1 Counter for STATUS_ERR_NOCLIENT and closing the connection
Spec: §7.8.1, p. 45 — “The Agent shall maintain a counter on the number of
times the STATUS_ERR_NOCLIENT was sent on an established connection, and once
a certain threshold is crossed it shall close the connection. The Agent may
subsequently refuse or throttle new connections originating from the same
client transport endpoint that was previously closed.”
Repo: crates/xrce-agent/src/daemon/transport.rs (PeerTable::strike, PeerTable::is_blocked, apply_events); crates/xrce-agent/src/daemon/config.rs (no_client_threshold)
Tests: crates/xrce-agent/src/daemon/transport.rs::tests::messages_to_an_unknown_client_key_close_the_connection_at_the_threshold, crates/xrce-agent/src/daemon/config.rs::tests::the_no_client_threshold_can_be_set
Status: done — the agent counts the messages per peer to an unknown ClientKey; at no_client_threshold (default 16, 0 never) the TCP connection is closed and a UDP peer is not read any more. 458b32f4346.
§7.8.2 XRCE Root
§7.8.2 The Root authenticates and creates ProxyClients
Spec: §7.8.2, p. 45 — “The XRCE Root object represents the Agent. An XRCE Agent is a singleton object that all agents shall instantiate. The XRCE Root is responsible for authenticating client applications and creating the XRCE ProxyClient object associated with each client.”
Repo: crates/xrce-agent/src/daemon/session.rs (SessionEngine,
handle_create_client l. 1168; checks l. 1227 and l. 1240);
crates/xrce-agent/src/daemon/access.rs (AccessController)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::create_client_happy_path_registers_and_replies_ok,
crates/xrce-agent/src/daemon/session.rs::tests::a_client_key_not_configured_in_the_agent_is_denied,
crates/xrce-agent/src/daemon/session.rs::tests::client_properties_are_checked_against_what_the_agent_requires
Status: done — the ProxyClient is created. Authentication is done by the
AccessController: configured ClientKeys (authorized_client_keys) and required
properties with name and value (required_client_properties), otherwise
STATUS_ERR_DENIED and no session. Commits 1c430db8a67, 5f7a8652d95.
§7.8.2 Table 3 Root operations
Spec: §7.8.2, Table 3, p. 45 — create_client, get_info,
delete_client.
Repo: —
Tests: —
Status: n/a (informative) — overview; the operations are listed one by
one in §7.8.2.1 to §7.8.2.3.
§7.8.2.1 create_client: inputs and outputs
Spec: §7.8.2.1, p. 45–46 — “client_representation (CLIENT_Representation): a representation of the Client. […] returnValue (ResultStatus) […] agent_info (AGENT_Representation): a representation of the Agent.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create_client
l. 1168, agent_status_reply l. 4331)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::create_client_happy_path_registers_and_replies_ok
Status: done — STATUS_AGENT carries ResultStatus and
AGENT_Representation (item on §8.3.5.5).
§7.8.2.1 CLIENT_Representation with client_timestamp
Spec: §7.8.2.1, p. 46 — “struct CLIENT_Representation { XrceCookie xrce_cookie; XrceVersion xrce_version; XrceVendorId xrce_vendor_id; Time_t client_timestamp; ClientKey client_key; SessionId session_id; @optional PropertySeq properties; };”
Repo: crates/xrce/src/handshake.rs (ClientRepresentation l. 328,
encode_form l. 407, decode_form l. 463); crates/xrce/src/encoding.rs
(RepresentationTimestamps l. 214); crates/xrce-agent/src/daemon/config.rs
(representation_timestamps); crates/xrce-client/src/lib.rs
(XrceClient::set_representation_timestamps l. 364)
Tests: crates/xrce/src/handshake.rs::tests::by_default_the_representations_have_no_timestamp,
crates/xrce/src/handshake.rs::tests::the_prose_form_has_a_time_t_after_the_vendor_id,
crates/xrce/src/handshake.rs::tests::client_representation_decodes_the_captured_create_client_prefix,
crates/xrce-client/src/lib.rs::tests::the_representation_timestamp_is_an_option_of_the_client,
crates/xrce-agent/src/daemon/config.rs::tests::the_form_of_the_representations_can_be_set
Status: done — the spec contradicts itself: the text (§7.8.2.1,
§8.3.5.1.2) names Time_t client_timestamp after xrce_vendor_id; the IDL of
Annex A (p. 105–106), the bytes of Annex B.1 and the eProsima capture (16
octets) do not have it. The bytes do not tell the forms apart. The default is
the form of the IDL; the form with a timestamp is the named setting
representation_timestamps: absent | present (agent key),
encoding::RepresentationTimestamps (Rust API),
XrceClient::set_representation_timestamps and the option representation timestamps in the XRCE client of every SDK. The Time_t follows
UnannotatedTypes (by default a DHEADER with the length 8). The tests check the
bytes of both forms. Commits f8bdf3cd878, 571ee6893d1.
§7.8.2.1 AGENT_Representation with agent_timestamp
Spec: §7.8.2.1, p. 46 — “struct AGENT_Representation { XrceCookie xrce_cookie; XrceVersion xrce_version; XrceVendorId xrce_vendor_id; Time_t agent_timestamp; @optional PropertySeq properties; };”
Repo: crates/xrce/src/handshake.rs (AgentRepresentation l. 356,
encode_form l. 554, decode_form l. 599); crates/xrce/src/encoding.rs
(RepresentationTimestamps l. 214)
Tests: crates/xrce/src/handshake.rs::tests::the_agent_representation_follows_the_setting_the_same_way,
crates/xrce/src/handshake.rs::tests::agent_representation_decodes_the_captured_status_agent_body,
crates/xrce-client/src/lib.rs::tests::the_representation_timestamp_is_an_option_of_the_client
Status: done — as for the item on client_timestamp: the default is the
form of Annex A (p. 106) without agent_timestamp; the form with the timestamp
is the setting representation_timestamps: present. The agent reads the setting
at start-up (server.rs, set_representation_timestamps). Commits f8bdf3cd878,
571ee6893d1.
§7.8.2.1 Check of xrce_cookie
Spec: §7.8.2.1, p. 46 — “Check the xrce_cookie to ensure it matches the predefined XRCE_COOKIE constant. If it does not match the creation shall fail and set the returnValue StatusValue to STATUS_ERR_INVALID_DATA.”
Repo: crates/xrce/src/handshake.rs (ClientRepresentation::decode_at
l. 455); crates/xrce-agent/src/daemon/session.rs (handle_create_client
l. 1175)
Tests: crates/xrce/src/submessages/create_client.rs::tests::refuses_a_payload_whose_cookie_is_not_xrce,
crates/xrce/src/handshake.rs::tests::client_representation_rejects_wrong_cookie,
crates/xrce-agent/src/daemon/session.rs::tests::a_wrong_cookie_is_answered_with_a_status_agent
Status: done — the cookie is checked; a wrong one gets a STATUS_AGENT with
STATUS_ERR_INVALID_DATA, no client is registered. Commit d7aec9c2d78.
§7.8.2.1 Answer to a wrong cookie as STATUS
Spec: §7.8.2.1, p. 46 — as above; §8.3.5.1, p. 63: “The XRCE Agent shall send a STATUS_AGENT message in response”.
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create_client
l. 1175–1192, agent_status_reply l. 4331)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_wrong_cookie_is_answered_with_a_status_agent,
crates/xrce-agent/src/daemon/session.rs::tests::an_unreadable_property_seq_is_refused_with_invalid_data
Status: done — the answer is a STATUS_AGENT (§8.3.5.1) with the ClientKey
of the header when the header has one, otherwise zeros. Commit d7aec9c2d78.
§7.8.2.1 Check of the major version
Spec: §7.8.2.1, p. 46 — “Check that the major version (xrce_version[0]) matches the XRCE_VERSION_MAJOR. If it does not match, the creation shall fail and set the returnValue StatusValue to STATUS_ERR_INCOMPATIBLE.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create_client
l. 1212)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::create_client_rejects_wrong_major_version
Status: done
§7.8.2.1 client_key authorized
Spec: §7.8.2.1, p. 46 — “Check that the Client identified by the client_key is authorized to connect to the XRCE Agent. If this check fails the operation shall fail and set the returnValue StatusValue to STATUS_ERR_DENIED.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create_client
l. 1227, deny_create_client l. 1337); crates/xrce-agent/src/daemon/access.rs
(AccessController::client_authorized l. 193)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_client_key_not_configured_in_the_agent_is_denied,
crates/xrce-agent/src/daemon/access.rs::tests::only_configured_client_keys_are_authorized
Status: done — a ClientKey outside authorized_client_keys gets
STATUS_ERR_DENIED; no session is created. Commits 1c430db8a67, 5f7a8652d95.
§7.8.2.1 Check of the properties
Spec: §7.8.2.1, p. 46 — “Check the Client properties, if present. These may contain vendor-specific information that may prevent the Agent from accepting the connection from the Client. […] If this check fails the operation shall fail and set the returnValue StatusValue to the appropriate value.”
Repo: crates/xrce-agent/src/daemon/access.rs
(AccessController::properties_accepted l. 201); crates/xrce/src/handshake.rs
(decode_properties l. 266); crates/xrce-agent/src/daemon/session.rs
(handle_create_client l. 1240)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::client_properties_are_checked_against_what_the_agent_requires,
crates/xrce-agent/src/daemon/session.rs::tests::an_unreadable_property_seq_is_refused_with_invalid_data,
crates/xrce-agent/src/daemon/session.rs::tests::a_big_endian_create_client_with_properties_is_read_right,
crates/xrce/src/handshake.rs::tests::a_malformed_property_seq_is_an_error_not_absent_properties
Status: done — if the agent requires properties
(required_client_properties, name and value), it answers a client without them
or with another value with STATUS_ERR_DENIED. A PropertySeq that cannot be read
is an error and is answered with STATUS_ERR_INVALID_DATA; it does not count as
“no properties”. Commits 5f7a8652d95, ca0cf7e08bf.
§7.8.2.1 Existing ProxyClient with the same session_id
Spec: §7.8.2.1, p. 47 — “If a ProxyClient exists and has the same session_id, then the operation shall not perform any action and shall set the returnValue StatusValue to STATUS_OK.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create_client
l. 1274 same_session, l. 1302–1332)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::create_client_same_session_id_reconnect_keeps_object_store,
crates/xrce-agent/src/daemon/session.rs::tests::a_create_client_for_the_same_session_leaves_the_streams_alone
Status: done — object store and streams stay, the answer is STATUS_OK. The
variant that resets the streams is the setting of the following item. Commit
d7aec9c2d78.
§7.8.2.1 Streams on the same session_id
Spec: §7.8.2.1, p. 47 — as above.
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create_client
l. 1290, SessionEngineConfig::restart_on_same_session);
crates/xrce-agent/src/daemon/config.rs (same_session_create_client)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_create_client_for_the_same_session_leaves_the_streams_alone,
crates/xrce-agent/src/daemon/session.rs::tests::a_create_client_for_the_same_session_can_restart_the_streams,
crates/xrce-agent/src/daemon/config.rs::tests::a_create_client_for_the_same_session_can_restart_the_streams,
crates/xrce-agent/tests/replay_foreign_session.rs::replay_matches_the_real_agents_create_client_create_and_delete_replies
Status: done — default keep (spec): a CREATE_CLIENT with the session_id
of the existing ProxyClient “shall not perform any action”, the streams go on.
Named setting same_session_create_client: restart: the agent discards the
states of the reliable streams, of the fragmentation, the backlog and the
counters of the best-effort streams. The eProsima processes need this; they
reuse ClientKey and session_id and start at sequence number 0 (capture; the
replay test sets restart). Commit d7aec9c2d78.
§7.8.2.1 Existing ProxyClient with another session_id
Spec: §7.8.2.1, p. 47 — “If a ProxyClient exists and has a different session_id then the operation shall delete the existing XRCE ProxyClient object and subsequently take the same actions as if there had not been a ProxyClient associated with the client_key.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create_client
l. 1275)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::create_client_different_session_id_resets_object_store
Status: done
§7.8.2.1 Sufficient resources
Spec: §7.8.2.1, p. 47 — “Check that there are sufficient internal resources to complete the create operation. If there are not, then the operation shall fail and set the returnValue StatusValue to STATUS_ERR_RESOURCES.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create_client)
Tests: crates/xrce-agent/tests/spec_items_session.rs::create_client_over_max_clients_is_a_resource_error
Status: done — handle_create_client checks max_clients and answers STATUS_ERR_RESOURCES; a repeated CREATE_CLIENT of a client that exists stays STATUS_OK (02c704651e4).
### §7.8.2.1 Deletion resets the communication state
Spec: §7.8.2.1, p. 47 — “deletion of an existing ProxyClient resets any prior communication state between the client and the agent. Any messages that were cached pending acknowledgments shall be discarded.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create_client
l. 1275–1301, handle_delete l. 2733)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::create_client_different_session_id_resets_object_store,
crates/xrce-agent/tests/replay_foreign_session.rs::replay_matches_the_real_agents_create_client_create_and_delete_replies
Status: done
§7.8.2.1 New ProxyClient: session_id, streams from 0, STATUS_OK
Spec: §7.8.2.1, p. 47 — “If the Agent creates a ProxyClient object it shall: Initialize its state to have the specified session_id. Initialize the built-in streams with sequence number 0. Set the returnValue StatusValue to STATUS_OK. Return a representation of the XRCE Agent in the agent_info.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create_client
l. 1302–1332); crates/xrce/src/reliable.rs (ReliableStreamState::new:
next_seq = 0)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::create_client_happy_path_registers_and_replies_ok,
crates/xrce-agent/src/daemon/session.rs::tests::reliable_outbound_messages_get_real_incrementing_sequence_numbers
Status: done
§7.8.2.1 Timestamps for synchronisation
Spec: §7.8.2.1, p. 47 — “The Agent and Client may use the client_timestamp and agent_timestamp to detect time-synchronization differences […]. The use of this information is left outside the scope of this specification.”
Repo: —
Tests: —
Status: n/a (informative) — outside the specification.
§7.8.2.1 XrceVersion and XrceVendorId for configuration
Spec: §7.8.2.1, p. 47 — “The Agent and Client may use the XrceVersion and XrceVendorId to further configure their protocol.”
Repo: —
Tests: —
Status: n/a (informative) — permission.
§7.8.2.2 Root get_info: inputs and outputs
Spec: §7.8.2.2, p. 47 — “info_mask (InfoMask): selects the kind of information to retrieve. client_info (ObjectInfo): a representation of the Client. […] returnValue (ResultStatus) […] agent_info (ObjectInfo): a representation of the Agent.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_get_info l. 2838,
agent_object_info l. 4242, client_info_status l. 242);
crates/xrce/src/object_info.rs (InfoMask l. 449);
crates/xrce-agent/src/daemon/discovery.rs (build_info_reply l. 107);
crates/xrce/src/submessages/get_info.rs (GetInfoPayload::with_client_info
l. 45)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_the_agent_in_a_session_returns_activity_and_representation,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_the_agent_checks_the_version_in_client_info,
crates/xrce-agent/src/daemon/discovery.rs::tests::discovery_responder_answers_get_info_on_agent,
crates/xrce-agent/src/daemon/discovery.rs::tests::the_info_mask_selects_activity_and_configuration,
crates/xrce/src/object_info.rs::tests::info_mask_bits_and_wire_form
Status: done — INFO with ResultStatus and the ObjectInfo of the agent.
info_mask is a 32-bit mask (InfoMask) that the agent reads from the
GET_INFO; it selects activity and config. client_info: GET_INFO_Payload
(§8.3.5.3.2, Annex A) has no member for it, §7.8.2.2 and Figure 10 (§8.4.4) name
it. The default is the payload of Annex A; GetInfoPayload::with_client_info
appends client_info behind the InfoMask, the agent reads it when it is there
(item on client_info). Commits ca0cf7e08bf, fd2e9a5bcfd.
§7.8.2.2 get_info before create_client and over another connection
Spec: §7.8.2.2, p. 47 — “The operation get_info returns information on the XRCE Agent and may be used prior to establishing a Session with the XRCE Agent […]. The operation get_info may be used over a different transport or connection”.
Repo: crates/xrce-agent/src/daemon/discovery.rs (run_discovery_responder
l. 43); crates/xrce-agent/src/daemon/session.rs (refusal l. 936,
handle_submessage l. 1141, handle_get_info l. 2838)
Tests: crates/xrce-agent/src/daemon/discovery.rs::tests::discovery_responder_answers_get_info_on_agent,
crates/xrce-agent/src/daemon/transport.rs::tests::the_udp_listener_answers_get_info_before_a_session,
crates/xrce-agent/src/daemon/transport.rs::tests::the_tcp_listener_answers_get_info_before_a_session,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_without_a_session_is_answered_for_the_agent_only
Status: done — the responder on the discovery port and the session engine
on the UDP and TCP listeners answer GET_INFO(OBJK_AGENT) without a session; a
transport other than that of the session that follows is possible too. There is
no test of its own for the serial line listener. Commits ca0cf7e08bf,
a8f300b7bcf.
§7.8.2.2 GET_INFO without a session on a listener
Spec: §7.8.2.2, p. 47 — as above.
Repo: crates/xrce-agent/src/daemon/session.rs (refusal l. 936,
handle_submessage l. 1141, handle_get_info l. 2838)
Tests: crates/xrce-agent/src/daemon/transport.rs::tests::the_udp_listener_answers_get_info_before_a_session,
crates/xrce-agent/src/daemon/transport.rs::tests::the_tcp_listener_answers_get_info_before_a_session,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_without_a_session_is_answered_for_the_agent_only
Status: done — handle_submessage passes a GET_INFO without a resolved
client or with a header without a session to handle_get_info(None, ...);
GET_INFO(OBJK_AGENT) before CREATE_CLIENT is answered on the UDP and TCP
listeners, any other kind with STATUS_ERR_UNKNOWN_REFERENCE. Commits
ca0cf7e08bf, a8f300b7bcf.
§7.8.2.2 client_info with CLIENT_Representation and CLIENTKEY_INVALID
Spec: §7.8.2.2, p. 47–48 — “The ObjectVariant member within client_info shall contain a CLIENT_Representation, which provides information on the XRCE Client that makes the request. […] The client_key field of CLIENT_Representation shall be set to the value CLIENTKEY_INVALID”.
Repo: crates/xrce/src/submessages/get_info.rs
(GetInfoPayload::with_client_info l. 45, client_info l. 62);
crates/xrce-agent/src/daemon/session.rs (client_info_status l. 242);
crates/xrce-client/src/discovery.rs (AgentDiscovery::with_client_info
l. 113); crates/xrce-client/src/lib.rs (XrceClient::request_agent_info
l. 622)
Tests: crates/xrce/src/submessages/get_info.rs::tests::client_info_follows_the_info_mask,
crates/xrce-client/src/discovery.rs::tests::client_info_names_the_version_and_hides_the_client_key,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_the_agent_checks_the_version_in_client_info,
crates/xrce-agent/src/daemon/discovery.rs::tests::a_client_of_another_major_version_is_answered_incompatible,
crates/xrce-client/src/lib.rs::tests::request_agent_info_works_before_the_session_and_sends_the_mask
Status: done — client_info is an ObjectInfo behind the InfoMask whose
config is a CLIENT_Representation with client_key CLIENTKEY_INVALID
(zeros). Annex A has no member for it in GET_INFO_Payload; a receiver that
does not read it answers the GET_INFO as without. The agent reads it: another
major version gets an INFO with STATUS_ERR_INCOMPATIBLE (Figure 10), an
unreadable one or one that is no CLIENT_Representation STATUS_ERR_INVALID_DATA.
The client sends it only on AgentDiscovery::with_client_info;
XrceClient::request_agent_info sends the GET_INFO of Annex A. Commits
ca0cf7e08bf, fd2e9a5bcfd.
§7.8.2.2 agent_info with AGENT_Representation and AGENT_ActivityInfo
Spec: §7.8.2.2, p. 48 — “The ObjectVariant member within agent_info shall contain an AGENT_ActivityInfo […]. The ActivityInfoVariant member within agent_info shall contain an AGENT_Representation”.
Repo: crates/xrce-agent/src/daemon/session.rs (agent_object_info
l. 4242); crates/xrce-agent/src/daemon/discovery.rs (build_info_reply
l. 107)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_the_agent_in_a_session_returns_activity_and_representation,
crates/xrce-agent/src/daemon/discovery.rs::tests::discovery_responder_answers_get_info_on_agent,
crates/xrce-agent/src/daemon/discovery.rs::tests::the_info_mask_selects_activity_and_configuration
Status: done — activity carries ActivityInfoVariant::Agent
(AGENT_ActivityInfo, layout see §7.7.12), config the AGENT_Representation.
The text swaps the two members: config is ObjectVariant, activity is
ActivityInfoVariant; the code follows Annex A. Commit ca0cf7e08bf.
§7.8.2.2 AGENT_Representation in agent_info
Spec: §7.8.2.2, p. 48 — as above.
Repo: crates/xrce-agent/src/daemon/session.rs (agent_object_info
l. 4242, handle_get_info l. 2838); crates/xrce-agent/src/daemon/discovery.rs
(build_info_reply l. 107)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_the_agent_in_a_session_returns_activity_and_representation,
crates/xrce-agent/src/daemon/discovery.rs::tests::discovery_responder_answers_get_info_on_agent,
crates/xrce-agent/src/daemon/discovery.rs::tests::the_info_mask_selects_activity_and_configuration
Status: done — config is ObjectConfig::Agent(AgentRepresentation) with
version and vendor of the agent, as far as the InfoMask asks for config; a
client picks an agent with it after §8.4.4. properties is empty. Commit
ca0cf7e08bf.
§7.8.2.2 address_seq reports the addresses
Spec: §7.8.2.2, p. 48 — “ActivityInfoVariant member address_seq shall be used to inform the XRCE Client of the transport addresses over which it can be reached and can receive calls to create_client.”
Repo: crates/xrce-agent/src/daemon/server.rs (listener_locators)
Tests: crates/xrce-agent/src/daemon/server.rs::tests::listener_locators_maps_udp_tcp_and_ipv6, crates/xrce-agent/src/daemon/server.rs::tests::listener_locators_names_the_secured_and_the_serial_listeners
Status: done — address_seq carries the addresses of the listeners: UDP and TCP with IPv4 as ADDRESS_FORMAT_MEDIUM, with IPv6 as ADDRESS_FORMAT_LARGE (§11.2.1, §11.3.1), as a TransportLocatorSeq in the AGENT_ActivityInfo with a DHEADER; DTLS, TLS and a serial line as ADDRESS_FORMAT_STRING (next item). 299b3a41398, ca0cf7e08bf, 0ac394aa5bf.
### §7.8.2.2 address_seq names the DTLS and TLS listeners
Spec: §7.8.2.2, p. 48 — as above.
Repo: crates/xrce-agent/src/daemon/server.rs (listener_locators)
Tests: crates/xrce-agent/src/daemon/server.rs::tests::listener_locators_names_the_secured_and_the_serial_listeners
Status: done — the listeners kind: dtls and kind: tls are reported as ADDRESS_FORMAT_STRING locators (dtls://host:port, tls://host:port), a serial line as serial://device?address=n: TransportLocatorFormat has no value of its own for them, and a plain locator of the same host would lead a client to connect without the protection of §8.3.2.4. 0ac394aa5bf.
### §7.8.2.2 properties for an authentication
Spec: §7.8.2.2, p. 48 — “The properties field of type PropertySeq […] may be used to implement an authentication protocol for the XRCE Agent. The specific mechanism is outside the scope of this specification.”
Repo: —
Tests: —
Status: n/a (informative) — outside the specification.
§7.8.2.3 delete_client deletes the ProxyClient
Spec: §7.8.2.3, p. 48 — “If the object is found it shall be delete and returnValue StatusValue shall be set to STATUS_OK.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_delete l. 2733)
Tests: crates/xrce-client/src/lib.rs::tests::disconnect_sends_delete_client_and_clears_state,
crates/xrce-agent/src/daemon/session.rs::tests::delete_client_needs_a_proxy_client,
crates/xrce-agent/tests/replay_foreign_session.rs::replay_matches_the_real_agents_create_client_create_and_delete_replies
Status: done
§7.8.2.3 delete_client without a ProxyClient
Spec: §7.8.2.3, p. 48 — “The XRCE Agent shall check the ClientKey to locate an existing XRCE: ProxyClient. If the object is not found the operation shall fail and returnValue StatusValue shall be set to STATUS_ERR_UNKNOWN_REFERENCE.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_delete l. 2733:
deletes_client, deleted_clients)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::delete_client_needs_a_proxy_client
Status: done — DELETE(OBJECTID_CLIENT) for a ClientKey without a
ProxyClient gets STATUS_ERR_UNKNOWN_REFERENCE. The same request again that
ended the session is a retransmission and gets STATUS_OK. Commits d7aec9c2d78,
09a995c86f4.
§7.8.3 XRCE ProxyClient
§7.8.3 ProxyClient by the ClientKey
Spec: §7.8.3, p. 48 — “The XRCE ProxyClient object represents a specific XRCE Client inside a concrete XRCE Agent. The ProxyClient object is identified by the ClientKey.”
Repo: crates/xrce-agent/src/lib.rs (XrceAgent::clients l. 102)
Tests: crates/xrce-agent/src/lib.rs::tests::register_client_idempotent
Status: done
§7.8.3 Table 4 ProxyClient operations
Spec: §7.8.3, Table 4, p. 48–49 — create, update, get_info,
delete.
Repo: —
Tests: —
Status: n/a (informative) — overview; the operations are listed one by
one in §7.8.3.1 to §7.8.3.4.
§7.8.3.1 create: inputs and outputs
Spec: §7.8.3.1, p. 49 — “creation_mode (CreationMode) […] objectid_prefix (ObjectIdPrefix) […] object_representation (ObjectVariant) […] The object_id in the returnValue shall be derived from the object_prefix input parameter.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create l. 1452,
create_core l. 1583, status_reply l. 4293)
Tests: crates/xrce-agent/tests/replay_foreign_session.rs::replay_matches_the_real_agents_create_client_create_and_delete_replies
Status: done
§7.8.3.1 input_objectkind and input_objectid
Spec: §7.8.3.1, p. 49 — “We will refer to this ObjectKind as the ‘input_objectkind’. […] The combination of the objectid_prefix and the ObjectKind contained in the object_representation discriminator shall be used to construct the ‘input’ ObjectId.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create l. 1531:
ObjectId::new(request.object_id.raw_id_12(), kind))
Tests: crates/xrce-agent/src/daemon/session.rs::tests::the_object_id_is_the_prefix_and_the_kind_of_the_representation,
crates/xrce-agent/tests/replay_foreign_session.rs::replay_matches_the_real_agents_create_client_create_and_delete_replies
Status: done — the ObjectId is the prefix of the request (12 bits) and
the kind of the representation’s discriminator; the STATUS names it. Commit
70963ac46ec.
§7.8.3.1 object_id with another nibble
Spec: §7.8.3.1, p. 49 — as above.
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create
l. 1531–1544)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::the_object_id_is_the_prefix_and_the_kind_of_the_representation
Status: done — the lower nibble of the request’s object_id is not read:
even with another kind in it handle_create creates the object of the
discriminator’s kind under the same prefix (in the test a participant under the
object_id of a publisher kind). Commit 70963ac46ec.
§7.8.3.1 Table 5: object does not exist
Spec: §7.8.3.1, Table 5, p. 50 — “Don’t care / Don’t care / NO — Create object according to Table 6.”
Repo: crates/xrce/src/object_store.rs (ObjectStore::create l. 152,
CreateOutcome::Created l. 175)
Tests: crates/xrce/src/object_store.rs::tests::create_inserts_new_object
Status: done
§7.8.3.1 Table 5: reuse=FALSE, replace=FALSE, exists
Spec: §7.8.3.1, Table 5, p. 50 — “FALSE / FALSE / YES — No action taken. Set the StatusValue within returnValue to: STATUS_ERR_ALREADY_EXISTS.”
Repo: crates/xrce/src/object_store.rs (CreateOutcome::Conflict l. 208);
crates/xrce-agent/src/daemon/session.rs (create_core l. 1692)
Tests: crates/xrce/src/object_store.rs::tests::create_strict_on_existing_returns_conflict
Status: done
§7.8.3.1 Table 5: reuse=FALSE, replace=TRUE, exists
Spec: §7.8.3.1, Table 5, p. 50 — “FALSE / TRUE / YES — Delete existing object as specified by the delete operation. Create object according to Table 6. Set the StatusValue within returnValue to: STATUS_OK.”
Repo: crates/xrce/src/object_store.rs (CreateOutcome::Replaced l. 206);
crates/xrce-agent/src/daemon/session.rs (create_core l. 1700)
Tests: crates/xrce/src/object_store.rs::tests::create_replace_increments_version,
crates/xrce-agent/src/daemon/session.rs::tests::a_replace_that_fails_returns_the_object_to_its_previous_configuration
Status: done — this includes that a replacement that fails returns the
object to its previous configuration (§7.8.3.2). Commit 70963ac46ec.
§7.8.3.1 Table 5: reuse=TRUE, replace=FALSE, exists
Spec: §7.8.3.1, Table 5, p. 50 — “TRUE / FALSE / YES — Check if object_representation matches the existing Object: If it matches no action is taken […] STATUS_OK_MATCHES. If it does not match no action is taken […] STATUS_ERR_MISMATCH.”
Repo: crates/xrce/src/object_store.rs (CreateOutcome::Reused l. 180);
crates/xrce-agent/src/daemon/session.rs (create_core l. 1688–1693)
Tests: crates/xrce/src/object_store.rs::tests::create_reuse_returns_equal_marker,
crates/xrce-agent/src/daemon/session.rs::tests::reuse_compares_the_container_of_the_representation
Status: done — equal: STATUS_OK_MATCHED, unequal: STATUS_ERR_MISMATCH,
no change in either case. Table 5 spells STATUS_OK_MATCHES; StatusValue in
Annex A and ResultStatusCode::OkMatched (0x01) are named STATUS_OK_MATCHED.
Representation, container and domain are compared (item below). Commit
70963ac46ec.
§7.8.3.1 Comparison with participant_id, publisher_id, domain_id
Spec: §7.8.3.1, Table 5, p. 50 — as above.
Repo: crates/xrce-agent/src/daemon/session.rs (create_core l. 1671:
same_extra, ObjectVariantExtra); crates/xrce/src/object_store.rs
(ObjectStore::create l. 152)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::reuse_compares_the_container_of_the_representation
Status: done — the comparison on reuse includes the container
(participant_id, publisher_id, subscriber_id) and the domain_id, which the
object store does not hold (ObjectVariantExtra per object in the session). The
same XML string under another container gets STATUS_ERR_MISMATCH. Commit
70963ac46ec.
§7.8.3.1 Table 5: reuse=TRUE, replace=TRUE, exists
Spec: §7.8.3.1, Table 5, p. 50 — “TRUE / TRUE / YES — Check if object_representation matches the existing Object: If it matches, no action is taken […] STATUS_OK_MATCHES. If it does not match, delete existing object as specified by the delete operation and then create a new object according to Table 6. Set the StatusValue within returnValue to: STATUS_OK.”
Repo: crates/xrce/src/object_store.rs (ObjectStore::create l. 177–192);
crates/xrce-agent/src/daemon/session.rs (create_core l. 1672–1681)
Tests: crates/xrce/src/object_store.rs::tests::create_reuse_and_replace_replaces_an_unequal_object,
crates/xrce-agent/src/daemon/session.rs::tests::a_create_with_reuse_and_replace_updates_the_object
Status: done — on equality STATUS_OK_MATCHED without a change, on
inequality the object is deleted and created anew (STATUS_OK), the DDS side
included. Commit 3b066516f69.
§7.8.3.1 reuse and replace replace an unequal object
Spec: §7.8.3.1, Table 5, p. 50 — as above.
Repo: crates/xrce/src/object_store.rs (ObjectStore::create l. 177–192);
crates/xrce-agent/src/daemon/session.rs (create_core l. 1672–1681)
Tests: crates/xrce/src/object_store.rs::tests::create_reuse_and_replace_replaces_an_unequal_object,
crates/xrce-agent/src/daemon/session.rs::tests::a_create_with_reuse_and_replace_updates_the_object,
crates/xrce-agent/src/daemon/session.rs::tests::the_update_of_a_missing_object_creates_it_or_is_refused,
crates/xrce-agent/src/daemon/session.rs::tests::an_update_needs_the_permission_to_update
Status: done — ObjectStore::create treats reuse with and without
replace differently: without replace an unequal object gets
STATUS_ERR_MISMATCH, with replace it replaces the object. That is also the
operation update (§7.8.3.2, Table 14, §8.4.13): XrceClient::update_object,
permission update in the AccessController, without an existing object it is
created (Table 5); update_of_missing_object: refuse gives
STATUS_ERR_UNKNOWN_REFERENCE (§7.8.3.2). The two readings contradict each
other in the spec; the default is Table 5, tested in
the_update_of_a_missing_object_creates_it_or_is_refused. Commit 3b066516f69.
§7.8.3.1 All representations with reference and XML
Spec: §7.8.3.1, p. 50 — “the representations for the different kinds of objects all derive from either OBJK_Representation2_Base or OBJK_Representation3_Base. Therefore, they all have at least the REPRESENTATION_BY_REFERENCE and the REPRESENTATION_AS_XML_STRING.”
Repo: crates/xrce-agent/src/daemon/session.rs (format_is_allowed l. 279,
handle_create l. 1508); crates/xrce-agent/src/daemon/config.rs
(representation_formats)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::the_formats_of_each_kind_are_enforced,
crates/xrce-agent/src/daemon/config.rs::tests::the_representation_formats_can_be_widened
Status: done — the spec contradicts itself: the text says all
representations have REPRESENTATION_BY_REFERENCE and
REPRESENTATION_AS_XML_STRING; §7.7.3.1 and Annex A give Type, QosProfile,
Application and Domain reference or XML (OBJK_RepresentationRefAndXML_Base),
Publisher, Subscriber, DataWriter and DataReader binary or XML
(OBJK_RepresentationBinAndXML_Base), DomainParticipant and Topic all three.
There is no OBJK_Representation2_Base. The default is Annex A
(representation_formats: spec): any other format gets STATUS_ERR_INVALID_DATA.
The named setting representation_formats: any takes every format, for clients
that create Publishers, Subscribers, DataWriters and DataReaders by reference;
not measured against such a client. Commits 0429eab4fb2, 23d8f50c712.
§7.8.3.1 Nested objects
Spec: §7.8.3.1, p. 50 — “Certain representations support the representation of nested objects. […] In this case, the creation of the XRCE object shall also create the nested objects and the failure to create any nested entity shall be considered a failure to create the contained entity as well.”
Repo: crates/xrce-agent/src/daemon/session.rs (create_nested l. 1833,
create_embedded l. 1785, create_core l. 1743–1759)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_participant_definition_creates_the_objects_inside_it,
crates/xrce-agent/src/daemon/session.rs::tests::a_participant_definition_with_a_broken_part_creates_nothing,
crates/xrce-agent/src/daemon/session.rs::tests::a_publisher_with_nested_data_writers_creates_them
Status: done — a DomainParticipant or an Application creates the objects
its definition holds (DDS-XML), and so does a Publisher or Subscriber with its
embedded DataWriters and DataReaders. If a child fails, the whole fails: what
was created is removed (remove_with_nested) and the previous object comes
back. Commits 9d5c64dc398, b97657ef4ec.
### §7.8.3.1 A proxy creates the DDS entity
Spec: §7.8.3.1, p. 50 — “Some of the XRCE objects may be defined by this specification as proxies for DDS entities. In this case the creation of the XRCE Object will automatically trigger the creation of the proxy DDS Entity.”
Repo: crates/xrce-agent/src/daemon/session.rs (plan_dds_create,
apply_dds_create); crates/xrce-agent/src/daemon/dds_port.rs
(DdsPort::create_participant_with, DdsPort::create_topic,
DdsPort::create_publisher, DdsPort::create_subscriber,
DdsPort::create_writer, DdsPort::create_reader);
crates/xrce-agent/src/daemon/dcps_bridge.rs (RealDdsPort)
Tests: crates/xrce-agent/tests/replay_foreign_session.rs::replay_creates_the_dds_entities_the_real_clients_describe,
crates/xrce-agent/tests/e2e_udp_loopback.rs::e2e_udp_loopback_keyed_dispose_reliable_besteffort_and_fragments,
crates/xrce-agent/src/daemon/session.rs::tests::a_publisher_and_a_subscriber_get_a_dds_entity_with_their_policies,
crates/xrce-agent/src/daemon/dcps_bridge.rs::tests::a_publisher_is_a_dds_entity_of_its_participants_domain
Status: done — Commits 505c2e56d24. Participant, Topic, Publisher, Subscriber,
DataWriter and DataReader have a DDS entity. Publisher and Subscriber are made
by DdsPort::create_publisher and create_subscriber (PRESENTATION,
ENTITY_FACTORY, PARTITION, GROUP_DATA are applied). QosProfile, Type and
Application have no DDS entity in Table 6.
§7.8.3.1 Failure of the DDS entity is failure of the object
Spec: §7.8.3.1, p. 50 — “Failure to create a DDS Entity shall be considered a failure to create the proxy XRCE object as well.”
Repo: crates/xrce-agent/src/daemon/session.rs (create_core,
apply_dds_create, remove_with_nested)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_dds_entity_is_enabled_when_the_creation_has_succeeded,
crates/xrce-agent/src/daemon/session.rs::tests::a_topic_of_an_unknown_type_is_refused_when_the_agent_is_told_to,
crates/xrce-agent/src/daemon/session.rs::tests::a_participant_definition_with_a_broken_part_creates_nothing
Status: done — Commits 70963ac46ec, 9d5c64dc398. If apply_dds_create or
DdsPort::enable fails, create_core deletes the DDS side and the store entry
and answers with the code of the error. If a nested object fails, the whole
object is removed (remove_with_nested).
§7.8.3.1 No discovery traffic on failure, entities disabled
Spec: §7.8.3.1, p. 50 — “If the creation of the XRCE object fails then there should be no associated DDS-RTPS discovery traffic generated by the Agent. This means that all DDS entities shall be created disabled […] and enabled (if so configured by their QoS) only after it has been determined that the creation has succeeded.”
Repo: crates/xrce-agent/src/daemon/dcps_bridge.rs (enable, create_participant_with); crates/xrce-agent/src/daemon/session.rs (create_core)
Tests: crates/xrce-agent/src/daemon/dcps_bridge.rs::tests::a_participant_qos_is_applied_to_the_participant, crates/xrce-agent/src/daemon/dcps_bridge.rs::tests::an_endpoint_is_announced_only_when_it_is_enabled
Status: done — DataWriters, DataReaders and the DomainParticipant are registered with the DcpsRuntime, and so discovered, only by DdsPort::enable; create_core calls enable when the object is stored and nothing can fail any more. An object that fails in creation or in enable is never announced. 70963ac46ec, 348ad4265e7.
### §7.8.3.1 DomainParticipant is created disabled
Spec: §7.8.3.1, p. 50 — “This means that all DDS entities shall be created
disabled […] and enabled (if so configured by their QoS) only after it has
been determined that the creation has succeeded.”
Repo: crates/xrce-agent/src/daemon/dcps_bridge.rs (create_participant_with, enable, runtime_for)
Tests: crates/xrce-agent/src/daemon/dcps_bridge.rs::tests::a_participant_qos_is_applied_to_the_participant
Status: done — create_participant_with no longer starts a runtime; it records the participant (for USER_DATA the slot of a runtime of its own), enable starts it when the CREATE succeeds. A domain id above 232 is refused at CREATE. 348ad4265e7.
### §7.8.3.1 Success yields STATUS_OK
Spec: §7.8.3.1, p. 50 — “If the creation succeeds the Agent shall set the StatusValue within returnStatus to STATUS_OK..”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create,
create_core)
Tests: crates/xrce-agent/tests/replay_foreign_session.rs::replay_matches_the_real_agents_create_client_create_and_delete_replies
Status: done — A successful creation is STATUS_OK; with reuse and an equal
representation STATUS_OK_MATCHED (Table 5 spells STATUS_OK_MATCHES; only the
name in the code differs).
§7.8.3.1 Table 6 OBJK_QOSPROFILE
Spec: §7.8.3.1, Table 6, p. 51 — “The agent shall use that definition to create an XRCE QosProfile in accordance to the representation defined in 7.7.3.2.”
Repo: crates/xrce-agent/src/daemon/session.rs (plan_dds_create,
definition_to_register, rebuild_profiles)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::type_and_qos_profile_xml_follow_their_clauses,
crates/xrce-agent/src/daemon/session.rs::tests::what_a_configuration_client_defines_is_referenced_by_another_client
Status: done — Commits 9d5c64dc398, b97657ef4ec. The object has no DDS entity.
A <qos_library> with one <qos_profile> is known to the agent as a definition
for as long as the object exists; other clients create it by
REPRESENTATION_BY_REFERENCE. A reference resolves against the profile files and
these definitions.
§7.8.3.1 Table 6 OBJK_TYPE
Spec: §7.8.3.1, Table 6, p. 51 — “The agent shall use that definition to create an XRCE Type in accordance to the representation defined in 7.7.3.3.”
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (types); crates/xrce-agent/src/daemon/session.rs (find_type_definition)
Tests: crates/xrce-agent/tests/spec_items_session.rs::a_type_by_reference_names_a_known_type_by_its_fully_qualified_name
Status: done — XML <types> (exactly one non-nested type) and a binary TypeObject create types; a reference resolves against the types known to the agent, and a type may refer to a type already known (item on §7.7.3.3.2).
### §7.8.3.1 Table 6 OBJK_APPLICATION
Spec: §7.8.3.1, Table 6, p. 51 — “The agent shall use that definition to create an XRCE Application with all the contained entities found within the definition in accordance to the representation defined in 7.7.3.5.”
Repo: crates/xrce-agent/src/daemon/session.rs (plan_dds_create,
create_nested, ensure_predefined);
crates/xrce-agent/src/daemon/definitions.rs (plan_participant)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::what_a_configuration_client_defines_is_referenced_by_another_client,
crates/xrce-agent/src/daemon/session.rs::tests::a_create_client_makes_the_objects_configured_for_the_client
Status: done — Commits b97657ef4ec, 2ba972cd270. create_nested makes the
DomainParticipants of the Application with the objects inside them under the
ObjectIds of their names (Table 16); a second creation reuses the objects that
exist.
§7.8.3.1 Table 6 OBJK_PARTICIPANT
Spec: §7.8.3.1, Table 6, p. 51 — “The agent shall use that definition to create an XRCE DomainParticipant and an associated DDS DomainParticipant with all the contained entities found within the definition in accordance to the representation defined in 7.7.3.6.”
Repo: crates/xrce-agent/src/daemon/session.rs (plan_dds_create,
create_core, create_nested); crates/xrce-agent/src/daemon/dcps_bridge.rs
(RealDdsPort::create_participant_with);
crates/xrce-agent/src/daemon/entity_repr.rs (participant);
crates/xrce-agent/src/daemon/binary_forms.rs (participant)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_participant_definition_creates_the_objects_inside_it,
crates/xrce-agent/src/daemon/session.rs::tests::a_participant_definition_with_a_broken_part_creates_nothing,
crates/xrce-agent/src/daemon/dcps_bridge.rs::tests::full_chain_against_a_real_leased_domain,
crates/xrce-agent/src/daemon/dcps_bridge.rs::tests::a_participant_qos_is_applied_to_the_participant,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_participant_domain_comes_from_the_wire_unless_the_xml_names_one,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_domain_reference_is_resolved_against_the_domain_libraries,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_participant_qos_profile_reference_is_applied
Status: done — Commits 9d5c64dc398, 0b67c04800c. The participant binds the
DcpsRuntime of its domain. The entities in the definition are made with it; if
one fails, the whole participant is removed. domain_reference and
qos_profile_reference of the binary form are resolved.
§7.8.3.1 Table 6 OBJK_TOPIC
Spec: §7.8.3.1, Table 6, p. 51 — “The agent shall locate the XRCE DomainParticipant identified by the participant_id. If this object is not found the operation shall fail and return STATUS_ERR_UNKNOWN_REFERENCE. The agent shall use the definition to create an XRCE Topic […] and an associated DDS Topic. The DDS Topic shall be created using the DomainParticipant identified by the participant_id.”
Repo: crates/xrce-agent/src/daemon/session.rs (plan_dds_create,
participant_of_create); crates/xrce-agent/src/daemon/dcps_bridge.rs
(RealDdsPort::create_topic)
Tests: crates/xrce-agent/src/daemon/dds_port.rs::tests::null_port_rejects_topic_before_participant,
crates/xrce-agent/tests/replay_foreign_session.rs::replay_creates_the_dds_entities_the_real_clients_describe,
crates/xrce-agent/src/daemon/session.rs::tests::a_topic_is_created_by_name_or_by_register_type_ref,
crates/xrce-agent/src/daemon/session.rs::tests::a_topic_of_an_unknown_type_is_refused_when_the_agent_is_told_to
Status: done — Commits 969c784c93b. In the DcpsRuntime the topic is the name
and type of its endpoints. A type the agent does not know follows the agent key
unknown_topic_types: refuse (default) answers STATUS_ERR_UNKNOWN_REFERENCE
and creates nothing, forward creates the topic and forwards the samples
undecoded.
§7.8.3.1 Table 6 OBJK_PUBLISHER
Spec: §7.8.3.1, Table 6, p. 51–52 — “The agent shall locate the XRCE DomainParticipant identified by the participant_id. If this object is not found the operation shall fail and return STATUS_ERR_UNKNOWN_REFERENCE. […] an associated DDS Publisher. The DDS Publisher shall be created using the DomainParticipant identified by the participant_id.”
Repo: crates/xrce-agent/src/daemon/session.rs (plan_dds_create,
participant_of_create, DdsCreate::Container);
crates/xrce-agent/src/daemon/dcps_bridge.rs (RealDdsPort::create_publisher)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_publisher_or_subscriber_needs_an_existing_participant,
crates/xrce-agent/src/daemon/session.rs::tests::a_publisher_and_a_subscriber_get_a_dds_entity_with_their_policies,
crates/xrce-agent/src/daemon/dcps_bridge.rs::tests::a_publisher_is_a_dds_entity_of_its_participants_domain,
crates/xrce-agent/src/daemon/dds_port.rs::tests::publisher_and_subscriber_need_their_participant_and_endpoints_need_them
Status: done — Commits 505c2e56d24. A participant the client does not hold gives
STATUS_ERR_UNKNOWN_REFERENCE; a participant_id of another kind
STATUS_ERR_INVALID_DATA; nothing is stored. The DDS Publisher is made under the
participant with PRESENTATION, ENTITY_FACTORY, PARTITION and GROUP_DATA.
§7.8.3.1 Table 6 OBJK_SUBSCRIBER
Spec: §7.8.3.1, Table 6, p. 51–52 — as for the publisher, for the subscriber.
Repo: crates/xrce-agent/src/daemon/session.rs (plan_dds_create,
participant_of_create, DdsCreate::Container);
crates/xrce-agent/src/daemon/dcps_bridge.rs (RealDdsPort::create_subscriber)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_publisher_or_subscriber_needs_an_existing_participant,
crates/xrce-agent/src/daemon/session.rs::tests::a_publisher_and_a_subscriber_get_a_dds_entity_with_their_policies,
crates/xrce-agent/src/daemon/dds_port.rs::tests::publisher_and_subscriber_need_their_participant_and_endpoints_need_them
Status: done — Commits 505c2e56d24. As for the Publisher, for the Subscriber.
§7.8.3.1 Table 6 OBJK_DATAWRITER
Spec: §7.8.3.1, Table 6, p. 52 — “The agent shall locate the XRCE Publisher identified by the publisher_id. If this object is not found the operation shall fail and return STATUS_ERR_UNKNOWN_REFERENCE. […] an associated DDS DataWriter. The DDS DataWriter shall be created using the Publisher identified by the publisher_id.”
Repo: crates/xrce-agent/src/daemon/session.rs (plan_dds_create,
DdsCreate::Endpoint); crates/xrce-agent/src/daemon/dcps_bridge.rs
(RealDdsPort::create_writer)
Tests: crates/xrce-agent/src/daemon/dcps_bridge.rs::tests::create_writer_before_topic_rejected,
crates/xrce-agent/tests/replay_foreign_session.rs::replay_creates_the_dds_entities_the_real_clients_describe,
crates/xrce-agent/src/daemon/session.rs::tests::annex_b_2_3_create_of_a_binary_data_writer,
crates/xrce-agent/src/daemon/session.rs::tests::an_endpoint_and_its_topic_belong_to_one_participant,
crates/xrce-agent/src/daemon/session.rs::tests::a_data_writer_states_its_qos_over_a_profile,
crates/xrce-agent/src/daemon/dds_port.rs::tests::publisher_and_subscriber_need_their_participant_and_endpoints_need_them
Status: done — The writer inherits PARTITION and GROUP_DATA of the Publisher. A Publisher the client does not hold gives STATUS_ERR_UNKNOWN_REFERENCE; Publisher and topic must belong to the same participant.
§7.8.3.1 Table 6 OBJK_DATAREADER
Spec: §7.8.3.1, Table 6, p. 52 — “OBJK_DATEREADER The ObjectVariant is a DATAWRITER_Representation […]. The agent shall locate the XRCE Subscriber identified by the subscriber_id. If this object is not found the operation shall fail and return STATUS_ERR_UNKNOWN_REFERENCE.”
Repo: crates/xrce-agent/src/daemon/session.rs (plan_dds_create,
DdsCreate::Endpoint); crates/xrce-agent/src/daemon/dcps_bridge.rs
(RealDdsPort::create_reader)
Tests: crates/xrce-agent/tests/replay_foreign_session.rs::replay_creates_the_dds_entities_the_real_clients_describe,
crates/xrce-agent/tests/e2e_udp_loopback.rs::e2e_udp_loopback_keyed_dispose_reliable_besteffort_and_fragments,
crates/xrce-agent/src/daemon/session.rs::tests::an_endpoint_and_its_topic_belong_to_one_participant,
crates/xrce-agent/src/daemon/dds_port.rs::tests::publisher_and_subscriber_need_their_participant_and_endpoints_need_them
Status: done — The row of the spec writes OBJK_DATEREADER and
DATAWRITER_Representation; OBJK_DATAREADER and DATAREADER_Representation
are meant. The reader inherits PARTITION and GROUP_DATA of the Subscriber; a
missing Subscriber gives STATUS_ERR_UNKNOWN_REFERENCE.
§7.8.3.2 update of an existing object
Spec: §7.8.3.2, p. 52 — “This operation shall attempt to update an existing object in the XRCE Agent. If the object exists and the update is successful STATUS_OK shall be returned”.
Repo: crates/xrce-agent/src/daemon/session.rs (create_core);
crates/xrce/src/object_store.rs (ObjectStore::create);
crates/xrce-client/src/lib.rs (XrceClient::update_object)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_create_with_reuse_and_replace_updates_the_object,
crates/xrce-client/src/lib.rs::tests::update_object_sends_a_create_with_reuse_and_replace
Status: done — Commits 3b066516f69. Table 14 and §8.4.13 map update to CREATE
with reuse and replace. An equal representation (container and domain_id
included) gives STATUS_OK_MATCHED and changes nothing; a different one replaces
the object with its DDS side (STATUS_OK).
§7.8.3.2 update without an object
Spec: §7.8.3.2, p. 52 — “If the object does not already exist STATUS_ERR_UNKNOWN_REFERENCE shall be returned.”
Repo: crates/xrce-agent/src/daemon/session.rs (create_core);
crates/xrce-agent/src/daemon/config.rs (update_of_missing_object)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::the_update_of_a_missing_object_creates_it_or_is_refused
Status: done — Commits 3b066516f69. The spec contradicts itself: §7.8.3.2
requires STATUS_ERR_UNKNOWN_REFERENCE, Table 5 and §8.4.13 let the same CREATE
make the object. The default is Table 5 (create); the agent key
update_of_missing_object: refuse gives STATUS_ERR_UNKNOWN_REFERENCE.
§7.8.3.2 update with invalid parameters, return to the old configuration
Spec: §7.8.3.2, p. 52 — “If the update was unsuccessful due to invalid parameters, STATUS_ERR_INVALID_DATA shall be returned. If an update is unsuccessful the referenced object shall return to its previous configuration.”
Repo: crates/xrce-agent/src/daemon/session.rs (create_core,
refuse_create, restore_previous)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_replace_that_fails_returns_the_object_to_its_previous_configuration
Status: done — Commits 70963ac46ec. A representation no object can be made from
is refused with its STATUS before anything changes (STATUS_ERR_INVALID_DATA for
a malformed representation, STATUS_ERR_UNKNOWN_REFERENCE for a reference that
does not resolve). If the new DDS side fails, restore_previous restores the
store entry and the DDS side from the stored plan.
§7.8.3.2 update without permission
Spec: §7.8.3.2, p. 52 — “If the object cannot be updated due to permission restrictions, STATUS_ERR_DENIED shall be returned.”
Repo: crates/xrce-agent/src/daemon/session.rs (create_core, permits);
crates/xrce-agent/src/daemon/access.rs (Operation::Update,
AccessController::permits)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::an_update_needs_the_permission_to_update,
crates/xrce-agent/src/daemon/session.rs::tests::replacing_an_object_needs_the_permission_to_delete_it
Status: done — Commits 5f7a8652d95, 3b066516f69. An update (CREATE with reuse
and replace) needs the permission Operation::Update, a replace without
reuse the permission Operation::Delete; otherwise STATUS_ERR_DENIED.
§7.8.3.3 get_info of an object
Spec: §7.8.3.3, p. 52 — “object_info (ObjectInfo): contains the current activity and configuration of the specified object. This operation returns the configuration and activity data for an existing object.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_get_info,
object_info, answer_info); crates/xrce/src/object_info.rs (ObjectInfo);
crates/xrce/src/submessages/info.rs (InfoPayload)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_an_object_returns_the_object_variant_it_was_created_with,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_a_data_writer_reports_its_activity,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_a_data_reader_reports_its_activity,
crates/xrce-agent/src/daemon/session.rs::tests::any_object_id_of_kind_agent_is_the_root_in_a_session
Status: done — Commits ca0cf7e08bf. The answer is an INFO with activity
(DataWriter, DataReader) and config (the ObjectVariant the object was created
with); the InfoMask selects. sample_seq_num, stream_seq_num and
highest_acked_num are counted by the agent itself; the spec does not define
the values, and a comparison with another agent was not measured.
§7.8.3.3 get_info without an object
Spec: §7.8.3.3, p. 53 — “If the object does not already exist STATUS_ERR_UNKNOWN_REFERENCE shall be returned.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_get_info,
answer_info)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_a_missing_object_is_an_info_with_unknown_reference,
crates/xrce-agent/src/daemon/transport.rs::tests::the_udp_listener_answers_get_info_before_a_session
Status: done — Commits ca0cf7e08bf. The agent answers with an INFO whose
ResultStatus is STATUS_ERR_UNKNOWN_REFERENCE and that carries the request_id
and object_id of the request (§8.3.5.7.2: the answer to GET_INFO is INFO).
§7.8.3.3 get_info without permission
Spec: §7.8.3.3, p. 53 — “If the object cannot be accessed due to permission restrictions STATUS_ERR_DENIED shall be returned.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_get_info);
crates/xrce-agent/src/daemon/access.rs (Operation::GetInfo)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::get_info_and_delete_without_permission_are_denied
Status: done — Commits 5f7a8652d95. Without the permission Operation::GetInfo
the agent answers with an INFO with STATUS_ERR_DENIED; the object stays.
§7.8.3.4 delete of an object
Spec: §7.8.3.4, p. 53 — “This operation deletes an existing object. If the object is successfully deleted STATUS_OK shall be returned.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_delete)
Tests: crates/xrce-agent/tests/endpoint_client_fixtures.rs::delete_fixture_decodes_and_removes_the_object_create_added,
crates/xrce-agent/tests/replay_foreign_session.rs::replay_matches_the_real_agents_create_client_create_and_delete_replies,
crates/xrce-agent/src/daemon/session.rs::tests::delete_client_needs_a_proxy_client
Status: done — The spec gives the input object_id the type
ObjectIdPrefix. DELETE(OBJECTID_CLIENT) ends the session and deletes the
ProxyClient (d7aec9c2d78).
§7.8.3.4 delete without an object
Spec: §7.8.3.4, p. 53 — “If the object does not exist STATUS_ERR_UNKNOWN_REFERENCE shall be returned.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_delete)
Tests: crates/xrce-agent/tests/spec_items_session.rs::delete_of_an_object_that_does_not_exist_is_an_unknown_reference, crates/xrce-agent/src/daemon/session.rs::tests::delete_client_needs_a_proxy_client
Status: done — handle_delete answers STATUS_ERR_UNKNOWN_REFERENCE when no object was removed; for DELETE(OBJECTID_CLIENT) without a ProxyClient (d7aec9c2d78) and for an ordinary object (02c704651e4).
### §7.8.3.4 delete without permission
Spec: §7.8.3.4, p. 53 — “If the object cannot be deleted due to permission restrictions, STATUS_ERR_DENIED shall be returned.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_delete);
crates/xrce-agent/src/daemon/access.rs (Operation::Delete)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::get_info_and_delete_without_permission_are_denied,
crates/xrce-agent/src/daemon/session.rs::tests::replacing_an_object_needs_the_permission_to_delete_it
Status: done — Commits 5f7a8652d95. Without the permission Operation::Delete
the agent answers STATUS_ERR_DENIED; the object stays.
§7.8.4 XRCE DataWriter
§7.8.4 Table 7 write operation
Spec: §7.8.4, Table 7, p. 53 — write with object_id and data.
Repo: —
Tests: —
Status: n/a (informative) — overview.
§7.8.4.1 write writes one or more samples
Spec: §7.8.4.1, p. 53 — “This operation writes one or more samples using the XRCE DataWriter identified by the object_id. […] The DataRepresentation type (see 7.7.2) supports multiple DataFormats. This allows sending single data items (FORMAT_DATA) as well as sequences (batches) of data items (FORMAT_SAMPLE_SEQ).”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_write_data,
split_write_items, dds_write_and_report);
crates/xrce-agent/src/daemon/dcps_bridge.rs (RealDdsPort::write,
RealDdsPort::sample_length)
Tests: crates/xrce-agent/tests/e2e_udp_loopback.rs::e2e_udp_loopback_keyed_dispose_reliable_besteffort_and_fragments,
crates/xrce-agent/tests/endpoint_client_fixtures.rs::write_data_fixture_decodes_into_the_sample_bytes_the_client_sent,
crates/xrce-agent/src/daemon/session.rs::tests::a_data_seq_is_split_by_the_type_and_written_sample_by_sample,
crates/xrce-agent/src/daemon/session.rs::tests::a_sample_seq_carries_state_and_time_per_sample,
crates/xrce-agent/src/daemon/session.rs::tests::packed_samples_resolve_their_deltas_against_the_base
Status: done — Commits f40bd568ad1. FORMAT_DATA, FORMAT_SAMPLE, FORMAT_DATA_SEQ,
FORMAT_SAMPLE_SEQ and FORMAT_PACKED_SAMPLES are written. The elements of a
sequence lie back to back without a length (Annex A sequence<SampleData>); the
type of the topic (DdsPort::sample_length) tells them apart. Assumption, not
measured against another agent: there is no padding between the elements, each
is read from alignment origin 0 (Annex B.5.2 shows 4-byte elements only).
§7.8.4.1 Sequence formats when writing
Spec: §7.8.4.1, p. 53 — as above.
Repo: crates/xrce-agent/src/daemon/session.rs (split_write_items,
handle_write_data); crates/xrce-agent/src/daemon/dcps_bridge.rs
(RealDdsPort::sample_length)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_data_seq_is_split_by_the_type_and_written_sample_by_sample,
crates/xrce-agent/src/daemon/session.rs::tests::a_sequence_that_does_not_split_writes_nothing,
crates/xrce-agent/src/daemon/session.rs::tests::a_sequence_of_a_topic_of_unknown_type_is_refused
Status: done — Commits f40bd568ad1. The three sequence formats are written sample
by sample. A sequence that does not split (count larger than the bytes, bytes
behind the last sample, truncated sample) writes nothing and gives
STATUS_ERR_INVALID_DATA. The same holds for a topic of unknown type (possible
only with unknown_topic_types: forward) whose samples cannot be told apart.
§7.8.4.1 Success yields STATUS_OK
Spec: §7.8.4.1, p. 53 — “If the data is successfully written STATUS_OK shall be returned.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_write_data)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_successful_write_is_answered_with_status_ok
Status: done — Commits 869304e6b63. A successful WRITE_DATA is answered with a
STATUS that names the request_id and DataWriter of the request; several
samples in one request give one STATUS. The capture of the eProsima agent holds
no answer to WRITE_DATA; the text of the spec (§8.3.5.8, Table 14) is followed.
§7.8.4.1 Unknown DataWriter
Spec: §7.8.4.1, p. 53 — “If the XRCE DataWriter object identified by the object_id does not exist, the ResultStatus STATUS_ERR_UNKNOWN_REFERENCE shall be returned.”
Repo: crates/xrce-agent/src/daemon/dcps_bridge.rs (RealDdsPort::write);
crates/xrce-agent/src/daemon/session.rs (dds_write_and_report,
dds_port_error_status)
Tests: crates/xrce-agent/src/daemon/dcps_bridge.rs::tests::full_chain_against_a_real_leased_domain
Status: done — RealDdsPort::write returns DdsPortError::UnknownReference
for a writer that does not exist; the session answers
STATUS_ERR_UNKNOWN_REFERENCE.
§7.8.4.1 write without permission
Spec: §7.8.4.1, p. 53 — “If the client is not allowed to write data using the referenced object_id due to permission restrictions, the ResultStatus STATUS_ERR_DENIED shall be returned.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_write_data,
permit); crates/xrce-agent/src/daemon/access.rs (Operation::WriteData)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::write_and_read_without_permission_are_denied
Status: done — Commits 5f7a8652d95. Without the permission Operation::WriteData
the agent answers STATUS_ERR_DENIED; nothing reaches the DDS side.
§7.8.4.1 Invalid data
Spec: §7.8.4.1, p. 53 — “If the data could not be written successfully due, for example invalid data format, the ResultStatus STATUS_ERR_INVALID_DATA shall be returned.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_write_data,
refuse_unreadable, dds_port_error_status);
crates/xrce-agent/src/daemon/dcps_bridge.rs (RealDdsPort::write)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_request_that_cannot_be_read_is_answered_invalid_data,
crates/xrce-agent/src/daemon/session.rs::tests::a_sequence_that_does_not_split_writes_nothing,
crates/xrce-agent/src/daemon/session.rs::tests::a_dispose_the_agent_cannot_identify_is_answered_with_a_status
Status: done — Commits 97de94f63e4, f40bd568ad1. A WRITE_DATA whose body cannot
be read, a sequence that does not split, and a dispose with no identifiable
instance give STATUS_ERR_INVALID_DATA. If the known type of the topic does not
read a payload, RealDdsPort::write returns DdsPortError::InvalidType (also
STATUS_ERR_INVALID_DATA); this branch has no test of its own.
§7.8.4.1 Timestamp in SampleInfo
Spec: §7.8.4.1, p. 53 — “The DataRepresentation type also supports sending sample information in addition to the data. This is encoded in the SampleInfo type (see 7.7.1) allowing sending timestamps and also notifications of dispose and unregister.”
Repo: crates/xrce-agent/src/daemon/session.rs (split_write_items,
source_time_of); crates/xrce-agent/src/daemon/dcps_bridge.rs
(RealDdsPort::write, he_timestamp)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_sample_is_stamped_with_the_session_time_plus_its_offset,
crates/xrce-agent/src/daemon/session.rs::tests::a_sample_seq_carries_state_and_time_per_sample,
crates/xrce-agent/src/daemon/dcps_bridge.rs::tests::known_keyed_type_gets_a_real_keyhash_and_honors_dispose
Status: done — Commits f40bd568ad1. The flags for dispose and unregister and
session_time_offset are read from SampleInfo (FORMAT_SAMPLE,
FORMAT_SAMPLE_SEQ) and SampleInfoDelta (FORMAT_PACKED_SAMPLES); the timestamp
reaches the DDS writer as the source time.
§7.8.4.1 session_time_offset as the source time
Spec: §7.8.4.1, p. 53 — as above.
Repo: crates/xrce-agent/src/daemon/session.rs (source_time_of,
handle_create_client); crates/xrce-agent/src/daemon/dcps_bridge.rs
(RealDdsPort::write)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_sample_is_stamped_with_the_session_time_plus_its_offset,
crates/xrce-agent/src/daemon/session.rs::tests::a_sample_seq_carries_state_and_time_per_sample
Status: done — Commits f40bd568ad1. The source time is the session time plus
session_time_offset. The session time is the agent’s clock when the session
was created: Annex A CLIENT_Representation has no client_timestamp. With
representation_timestamps: present the agent reads a client_timestamp but
does not use it as the session time. FORMAT_DATA carries no SampleInfo and is
not stamped.
§7.8.4.1 dispose
Spec: §7.8.4.1, p. 54 — “If the DataRepresentation contains a Sample where the SampleInfo has the ‘dispose’ flag set, the XRCE Agent shall call the dispose operation on the corresponding DDS DataWriter for the instance identified in the associated data.”
Repo: crates/xrce-agent/src/daemon/dcps_bridge.rs (RealDdsPort::write); crates/xrce-agent/src/daemon/session.rs (handle_write_data)
Tests: crates/xrce-agent/src/daemon/dcps_bridge.rs::tests::dispose_on_a_topic_of_unknown_type_is_refused, crates/xrce-agent/src/daemon/session.rs::tests::a_dispose_the_agent_cannot_identify_is_answered_with_a_status, crates/xrce-agent/tests/e2e_udp_loopback.rs::e2e_udp_loopback_keyed_dispose_reliable_besteffort_and_fragments
Status: done — for a known keyed type the agent calls write_user_lifecycle with the flag DISPOSED and the real KeyHash (f40bd568ad1). The specification asks for the dispose “for the instance identified in the associated data”; a type without a key or an unknown type identifies no instance, the data cannot be interpreted by the agent: STATUS_ERR_INVALID_DATA (next item).
### §7.8.4.1 dispose without a known type
Spec: §7.8.4.1, p. 54 — as above.
Repo: crates/xrce-agent/src/daemon/dcps_bridge.rs (RealDdsPort::write); crates/xrce-agent/src/daemon/session.rs (handle_write_data)
Tests: crates/xrce-agent/src/daemon/dcps_bridge.rs::tests::dispose_on_a_topic_of_unknown_type_is_refused, crates/xrce-agent/src/daemon/session.rs::tests::a_dispose_the_agent_cannot_identify_is_answered_with_a_status, crates/xrce-agent/tests/e2e_udp_loopback.rs::e2e_udp_loopback_keyed_dispose_reliable_besteffort_and_fragments
Status: done — for a topic of unknown type or of a type without @key the agent cannot determine the instance from the data (SerializedTypeSupport::key_material is None); an instance the specification wants identified does not exist. RealDdsPort::write writes nothing and returns DdsPortError::InvalidType; the session answers STATUS_ERR_INVALID_DATA, the specification’s status for data the agent cannot interpret, and reports SessionEvent::DdsPortFailed (f40bd568ad1).
### §7.8.4.1 unregister
Spec: §7.8.4.1, p. 54 — “Similarly there is a Sample where the SampleInfo
has the ‘unregister’ flag set, the XRCE Agent shall call the unregister
operation on the corresponding DDS DataWriter for the instance identified in
the associated data.”
Repo: crates/xrce-agent/src/daemon/dcps_bridge.rs (RealDdsPort::write); crates/xrce-agent/src/daemon/session.rs (handle_write_data)
Tests: crates/xrce-agent/src/daemon/dcps_bridge.rs::tests::dispose_on_a_topic_of_unknown_type_is_refused, crates/xrce-agent/src/daemon/session.rs::tests::a_dispose_the_agent_cannot_identify_is_answered_with_a_status, crates/xrce-agent/tests/e2e_udp_loopback.rs::e2e_udp_loopback_keyed_dispose_reliable_besteffort_and_fragments
Status: done — for a known keyed type the agent calls write_user_lifecycle with the flag UNREGISTERED; the native reader of the e2e test sees the unregistration (f40bd568ad1). For a type without a key or without a known type STATUS_ERR_INVALID_DATA applies as for dispose.
§7.8.5 XRCE DataReader
§7.8.5 Table 8 read operation
Spec: §7.8.5, Table 8, p. 54 — read with object_id,
read_specification and the output read_data.
Repo: —
Tests: —
Status: n/a (informative) — overview.
§7.8.5.1 read reads samples
Spec: §7.8.5.1, p. 54 — “This operation reads one or more samples from the XRCE DataReader identified by the object_id. If the data is successfully read STATUS_OK shall be returned.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_read_data,
pump_read, data_submessages)
Tests: crates/xrce-agent/tests/e2e_udp_loopback.rs::e2e_udp_loopback_keyed_dispose_reliable_besteffort_and_fragments,
crates/xrce-agent/src/daemon/session.rs::tests::read_data_elapsed_time_is_measured_from_the_real_request_time,
crates/xrce-agent/src/daemon/session.rs::tests::a_read_for_data_seq_is_answered_with_one_data_seq
Status: done — Commits 8bcb1d00161, fd5253ca805. Success is DATA (§8.3.5.10) in
the requested data_format.
§7.8.5.1 read without an object
Spec: §7.8.5.1, p. 54 — “If the object does not exist STATUS_ERR_UNKNOWN_REFERENCE shall be returned.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_read_data);
crates/xrce-agent/src/daemon/dds_port.rs (NullDdsPort::set_read_filter);
crates/xrce-agent/src/daemon/dcps_bridge.rs (RealDdsPort::set_read_filter)
Tests: crates/xrce-agent/src/daemon/dds_port.rs::tests::null_port_rejects_content_filter_but_accepts_clearing_it
Status: done — A reader that does not exist makes DdsPort::set_read_filter
return DdsPortError::UnknownReference; handle_read_data answers
STATUS_ERR_UNKNOWN_REFERENCE and starts no read.
§7.8.5.1 read without permission
Spec: §7.8.5.1, p. 54 — “If the client is not allowed to read data using the referenced object_id due to permission restrictions, STATUS_ERR_DENIED shall be returned.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_read_data,
permit); crates/xrce-agent/src/daemon/access.rs (Operation::ReadData)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::write_and_read_without_permission_are_denied,
crates/xrce-agent/src/daemon/session.rs::tests::read_with_permission_is_not_denied
Status: done — Commits 5f7a8652d95. Without the permission Operation::ReadData
the agent answers STATUS_ERR_DENIED and starts no read.
§7.8.5.1 Table 9 preferred_stream_id
Spec: §7.8.5.1, Table 9, p. 54 — “Specifies the StreamId the Agent should use to send the Samples to the Client. The special value STREAMID_NONE indicates that Agent can choose the StreamId unconstrained. The Agent is allowed to use an StreamId different from the preferred_stream_id if it determines that using the preferred_stream_id could cause problems with its resource-management.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_read_data,
pump_read, ActiveRead)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_sample_above_the_clients_mtu_on_a_reliable_stream_splits_into_fragments,
crates/xrce-agent/src/daemon/session.rs::tests::streamid_none_lets_the_agent_choose_the_stream
Status: done — Commits 8bcb1d00161. DATA goes on the requested stream; for
STREAMID_NONE the agent chooses STREAMID_BUILTIN_BEST_EFFORTS.
§7.8.5.1 STREAMID_NONE as the requested stream
Spec: §7.8.5.1, Table 9, p. 54 — as above.
Repo: crates/xrce-agent/src/daemon/session.rs (handle_read_data)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::streamid_none_lets_the_agent_choose_the_stream
Status: done — Commits 8bcb1d00161. The agent chooses the built-in best-effort
stream 0x01; DATA does not go on STREAMID_NONE.
§7.8.5.1 Table 9 data_format
Spec: §7.8.5.1, Table 9, p. 55 — “data_format DataFormat Selects one the data formats. See 7.7.1”; p. 55: “The setting of the data_format controls whether the read operation returns a single sample per message or a collection of samples. It also determines whether the data or it includes the additional information that appears in the SampleInfo”.
Repo: crates/xrce-agent/src/daemon/session.rs (data_submessages,
pump_read, ActiveRead)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_read_for_data_seq_is_answered_with_one_data_seq,
crates/xrce-agent/src/daemon/session.rs::tests::a_read_for_sample_is_answered_with_a_sample_each,
crates/xrce-agent/src/daemon/session.rs::tests::a_read_for_sample_seq_is_answered_with_one_sample_seq,
crates/xrce-agent/src/daemon/session.rs::tests::a_read_for_packed_samples_is_answered_with_one_packed_samples,
crates/xrce-agent/src/daemon/session.rs::tests::the_sequence_formats_split_at_the_size_of_a_submessage,
crates/xrce-client/src/lib.rs::tests::poll_hands_over_the_data_of_every_format
Status: done — Commits fd5253ca805. DATA comes in FORMAT_DATA, FORMAT_SAMPLE,
FORMAT_DATA_SEQ, FORMAT_SAMPLE_SEQ or FORMAT_PACKED_SAMPLES as requested; the
sequence formats split at the size of a submessage (PACKED_SAMPLES at most 256
samples). The SampleInfo values are only what the agent knows: sequence_number
counts the delivered samples, session_time_offset is the time of delivery,
state is 0 because DdsPort::poll_samples hands over payload bytes only (no
source timestamp, no instance, view or sample state).
§7.8.5.1 Table 9 content_filter_expression
Spec: §7.8.5.1, Table 9, p. 55 — “A content filter expression selecting which data to read. The syntax shall be as specified in Annex B (Syntax for Queries and Filters) of the DDS specification [DDS].” p. 55: “Only samples for which the filter evaluates to TRUE shall be returned to the XRCE Client.”
Repo: crates/xrce-agent/src/daemon/dcps_bridge.rs
(RealDdsPort::set_read_filter, CompiledReadFilter, drain_buffer);
crates/xrce-agent/src/daemon/session.rs (handle_read_data);
crates/xrce/src/submessages/read_data.rs (ReadSpecification)
Tests: crates/xrce-agent/src/daemon/dcps_bridge.rs::tests::a_content_filter_admits_an_xcdr2_sample,
crates/xrce-agent/src/daemon/session.rs::tests::read_data_with_an_unhonorable_content_filter_is_rejected_not_silently_unfiltered,
crates/xrce/src/submessages/read_data.rs::tests::annex_b_4_2_read_data_with_filter_and_delivery_control,
crates/xrce/src/submessages/read_data.rs::tests::the_content_filter_is_a_string_with_a_nul_and_an_aligned_length
Status: done — Commits b589558e671. The encoding on the wire is an XCDR2 string
with a NUL. A filter the agent cannot apply gives a STATUS and delivers no
unfiltered data.
§7.8.5.1 Table 9 max_samples
Spec: §7.8.5.1, Table 9, p. 55 — “Maximum number of samples to return as a result of the read. The special value MAX_SAMPLES_ZERO =0 is used to cancel any prior read operation that may still be active. The special value MAX_SAMPLES_UNLIMITED =0xffff is used to indicate that there is limit on the number of samples returned.”
Repo: crates/xrce/src/continuous_read.rs
(ReadStream::pull_pending_samples, ReadStream::capacity);
crates/xrce-agent/src/daemon/session.rs (pump_read)
Tests: crates/xrce/src/continuous_read.rs::tests::max_samples_cap_enforced,
crates/xrce/src/continuous_read.rs::tests::the_capacity_is_what_the_stream_still_delivers,
crates/xrce-agent/src/daemon/session.rs::tests::a_read_takes_only_the_samples_it_delivers
Status: done — The limit is counted; the agent takes from the DataReader
only the samples the read still delivers. The text on MAX_SAMPLES_UNLIMITED
says “there is limit”; §8.3.5.9.2 (p. 71) says “no limit”, which the code
follows.
§7.8.5.1 MAX_SAMPLES_ZERO and MAX_SAMPLES_UNLIMITED
Spec: §7.8.5.1, Table 9, p. 55; §8.3.5.9.2, p. 71 — as above.
Repo: crates/xrce/src/continuous_read.rs (MAX_SAMPLES_ZERO,
MAX_SAMPLES_UNLIMITED); crates/xrce-agent/src/daemon/session.rs
(handle_read_data)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::max_samples_zero_cancels_the_active_read,
crates/xrce/src/continuous_read.rs::tests::max_samples_zero_ends_the_read_and_unlimited_has_no_limit
Status: done — Commits 8bcb1d00161. 0 ends the running read of the DataReader
without further DATA; 0xFFFF reads without a limit.
§7.8.5.1 Table 9 max_elapsed_time
Spec: §7.8.5.1, Table 9, p. 55 — “Maximum amount of time in seconds that may be spent delivering the samples from the read operation. […] The special value MAX_ELAPSED_TIME_UNLIMITED = 0 indicates there is no maximum”.
Repo: crates/xrce-agent/src/daemon/session.rs (elapsed_time_limit, handle_read_data)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::max_elapsed_time_is_in_seconds_or_in_the_milliseconds_of_the_example
Status: done — the agent reads max_elapsed_time as seconds (Table 9, the definition; 0 is MAX_ELAPSED_TIME_UNLIMITED) and measures from the time of the request. Annex B.4.2 (an example) writes 30000 for 30 seconds; that reading is the setting max_elapsed_time_unit: milliseconds. 0db56a58a0e.
### §7.8.5.1 max_elapsed_time in milliseconds after Annex B.4.2
Spec: Annex B.4.2, p. 152 — “over a time window not to exceed 30 seconds”
with max_elapsed_time = 30000 = 0x7530; against it Table 9, p. 55: “Maximum
amount of time in seconds”.
Repo: crates/xrce-agent/src/daemon/config.rs (max_elapsed_time_unit); crates/xrce-agent/src/daemon/session.rs (SessionEngineConfig::max_elapsed_time_in_milliseconds)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::max_elapsed_time_is_in_seconds_or_in_the_milliseconds_of_the_example, crates/xrce-agent/src/daemon/config.rs::tests::the_unit_of_max_elapsed_time_can_be_set
Status: done — the reading of the Annex B example (milliseconds) is the setting max_elapsed_time_unit: milliseconds. 0db56a58a0e.
### §7.8.5.1 Table 9 max_bytes_per_sec
Spec: §7.8.5.1, Table 9, p. 55 — “Maximum rate in bytes per second at which the data may be returned to the read operation.”
Repo: crates/xrce/src/continuous_read.rs (ReadStream,
ReadStream::pull_pending_samples)
Tests: crates/xrce/src/continuous_read.rs::tests::rate_limit_partitions_samples_over_time
Status: done — The field is named max_bytes_per_second in the IDL.
§7.8.5.1 Table 9 min_pace_period
Spec: §7.8.5.1, Table 9, p. 55 — “Minimum separation between data messages returned from the read operation in milliseconds.” p. 55: “This period makes it possible for the client to go into a sleep cycle between messages.”
Repo: crates/xrce/src/continuous_read.rs
(ReadStream::pull_pending_samples)
Tests: crates/xrce/src/continuous_read.rs::tests::pacing_throttles_per_period
Status: done
§8.1 General
§8.1 Properties of the protocol
Spec: §8.1, p. 57 — bandwidth 40–100 Kbit/s, sleep cycles, language independence, minimal discovery, full access to DDS, updates of several topics, reliable and best-effort delivery, security at the transport level, access to all data, “Provide a full implementation requiring less than 100KB of code.”
Repo: —
Tests: —
Status: n/a (informative) — design goals; the code size is not
measured.
§8.1 XRCE clients without a standard API and without peer-to-peer
Spec: §8.1, p. 57 — “In contrast to applications that use the DDS API directly, XRCE Clients: Do not have a standard API […]. Cannot operate without infrastructure support. […] Do not communicate directly peer-to-peer.”
Repo: —
Tests: —
Status: n/a (informative) — description.
§8.2 Definitions
§8.2 Terms client, agent, session, message
Spec: §8.2, p. 57 — “At a high level, a client communicates with an agent using the DDS-XRCE protocol, exchanging messages on a stream belonging to a session.”
Repo: —
Tests: —
Status: n/a (informative) — terms.
§8.2.1 One transport message carries one XRCE message
Spec: §8.2.1, p. 57 — “The underlying XRCE Transport shall transfer each message as a unit. A single XRCE Transport ‘message’ shall transport a single XRCE message.”
Repo: crates/xrce/src/transport_udp.rs (send_message, recv_message);
crates/xrce/src/transport_tcp.rs (XrceTcpClient::send_message,
recv_message)
Tests: crates/xrce/src/transport_udp.rs::tests::rfc768_udp_delivers_one_datagram_per_message_with_boundaries_intact,
crates/xrce/src/transport_tcp.rs::tests::rfc793_byte_stream_is_delimited_by_the_length_prefix_not_by_writes
Status: done
§8.2.1 Alignment from the first byte of the message
Spec: §8.2.1, p. 57 — “XRCE messages shall be encoded assuming the first byte has a 16-byte alignment. Therefore, the encoding is independent of any transport heading or prefix that may precede it.”
Repo: crates/xrce/src/submessages/mod.rs (Message::encode,
Message::decode); crates/xrce-agent/src/daemon/binary_forms.rs
(participant, topic, container, endpoint);
crates/xrce-agent/src/daemon/entity_repr.rs (Cdr)
Tests: crates/xrce/src/submessages/mod.rs::tests::message_two_submessages_padded_correctly
Status: done — The codecs of the payloads align relative to the start of
their structure; these starts lie on multiples of 4. binary_forms.rs reads the
binary forms of §7.7.3 as XCDR2 (alignment up to 4) relative to the start of the
sequence<octet>; entity_repr.rs::Cdr reads the structures of eProsima as
classic CDR (alignment up to 8) from the same start.
§8.2.2 Session with a handshake
Spec: §8.2.2, p. 58 — “A session defines a bi-directional connection between a client and an agent that has been established with a handshake.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create_client);
crates/xrce-client/src/lib.rs (XrceClient::connect, handle_status_agent)
Tests: crates/xrce-agent/src/daemon/transport.rs::tests::udp_listener_answers_create_client_over_loopback,
crates/xrce-client/src/lib.rs::tests::connect_sends_a_real_create_client_and_moves_to_connecting,
crates/xrce-agent/src/daemon/session.rs::tests::a_wrong_cookie_is_answered_with_a_status_agent
Status: done — The agent answers CREATE_CLIENT with STATUS_AGENT; a wrong
cookie gives STATUS_AGENT with STATUS_ERR_INVALID_DATA (d7aec9c2d78).
§8.2.2 Up to 256 streams per session
Spec: §8.2.2, p. 58 — “A session can contain independent, reliable, and best-effort message streams. Each session may have up to 256 streams.”
Repo: crates/xrce/src/header.rs (StreamId);
crates/xrce-agent/src/daemon/session.rs (SessionEngine::reliable)
Tests: crates/xrce/src/header.rs::tests::stream_id_classification,
crates/xrce-agent/src/daemon/session.rs::tests::reset_clears_reads_backlog_best_effort_counters_and_every_reliable_stream
Status: done — Commits d4aad7c50b6. StreamId has 256 values; the agent keeps
the state per (client, stream), stream 255 included (RESET clears all).
§8.2.2 At most one active session
Spec: §8.2.2, p. 58 — “There can be at most one active session between an XRCE client and an XRCE agent. Creation of a new session closes any previous sessions.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create_client,
refusal, session_ids)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::create_client_different_session_id_resets_object_store,
crates/xrce-agent/src/daemon/session.rs::tests::a_message_of_a_replaced_session_is_not_processed
Status: done — Commits d4aad7c50b6. A new session_id replaces the old session;
messages with the old session_id are not processed (see the next item).
§8.2.2 Messages of an ended session
Spec: §8.2.2, p. 58 — as above.
Repo: crates/xrce-agent/src/daemon/session.rs (SessionEngine::refusal,
handle_message, SessionEvent::MessageRefused)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_message_of_a_replaced_session_is_not_processed,
crates/xrce-agent/src/daemon/session.rs::tests::a_message_without_a_session_is_not_processed_unless_it_is_a_create_client,
crates/xrce-agent/src/daemon/session.rs::tests::a_create_client_for_a_session_id_of_no_session_is_refused
Status: done — Commits d4aad7c50b6. A message whose session_id is not the
active session of the client is not processed and not answered; the agent
reports SessionEvent::MessageRefused. The values 0x00 and 0x80 (no session)
are accepted only for CREATE_CLIENT and for GET_INFO (§7.8.2.2).
§8.2.3 Streams with sequence numbers of their own
Spec: §8.2.3, p. 58 — “A stream represents an independent ordered flow of messages within a session. Messages are ordered within a stream by means of a sequence number. The sequence numbers used by different streams are independent of each other.”
Repo: crates/xrce-agent/src/daemon/session.rs (reliable,
best_effort_seq per (client, stream))
Tests: crates/xrce-agent/src/daemon/session.rs::tests::best_effort_messages_get_increasing_sequence_numbers
Status: done
§8.2.3 Constant byte order per stream
Spec: §8.2.3, p. 58 — “Streams can be reliable or best efforts. Each stream uses a constant endianness to encode the data in the message/submessage headers and payload.”
Repo: crates/xrce/src/submessages/ (into_submessage of all payloads with
FLAG_E_LITTLE_ENDIAN)
Tests: crates/xrce/src/submessages/write_data.rs::tests::write_data_flags_are_e_le_and_format_data
Status: done — ZeroDDS sends little-endian; on reception every payload follows the
E flag of its submessage (b9255734bfb, 299b3a41398). The code does not
check that the byte order is equal within a stream.
§8.2.4 The client starts the session
Spec: §8.2.4, p. 58 — “An XRCE client is the entity that initiates the establishment of a session with an XRCE agent.”
Repo: crates/xrce-client/src/lib.rs (XrceClient::connect)
Tests: crates/xrce-client/src/lib.rs::tests::connect_sends_a_real_create_client_and_moves_to_connecting
Status: done
§8.2.5 The agent accepts sessions
Spec: §8.2.5, p. 58 — “An XRCE agent is the entity that listens to and accepts requests to establish sessions from XRCE clients.”
Repo: crates/xrce-agent/src/daemon/transport.rs (run_udp_listener)
Tests: crates/xrce-agent/src/daemon/transport.rs::tests::udp_listener_answers_create_client_over_loopback
Status: done
§8.3 Message Structure
§8.3.1 Header and one or more submessages
Spec: §8.3.1, p. 58 — “An XRCE message is composed of a message Header followed by one or more Submessages and shall be transferred as a unit by the underlying XRCE Transport.”
Repo: crates/xrce/src/submessages/mod.rs (Message, Message::new, encode,
decode)
Tests: crates/xrce/src/submessages/mod.rs::tests::message_encode_decode_roundtrip_with_key,
crates/xrce/tests/foreign_frames.rs::every_client_datagram_decodes_and_writes_back,
crates/xrce/tests/wire_roundtrips.rs::a_message_without_a_submessage_is_refused
Status: done — header and submessages. Message::new, encode and decode refuse
a message without a submessage (d4aad7c50b6, see the item below).
§8.3.1 Message without a submessage
Spec: §8.3.1, p. 58 — as above.
Repo: crates/xrce/src/submessages/mod.rs (Message::new, Message::encode,
Message::decode; error ValueOutOfRange)
Tests: crates/xrce/tests/wire_roundtrips.rs::a_message_without_a_submessage_is_refused
Status: done — Message::new and encode with an empty list, and decode of a bare
header, return an error (d4aad7c50b6). The two tests that fixed the earlier
behaviour now assert the refusal.
§8.3.2 Layout of the header
Spec: §8.3.2, p. 59 — sessionId (8 bits), streamId (8 bits),
sequenceNr (16 bits), clientKey (32 bits, “if sessionId <= 127”).
Repo: crates/xrce/src/header.rs (MessageHeader, write_to, read_from)
Tests: crates/xrce/src/header.rs::tests::header_layout_bytes_no_key,
crates/xrce/src/header.rs::tests::header_layout_bytes_with_key,
crates/xrce/src/header.rs::tests::header_decode_truncated_with_key
Status: done
§8.3.2.1 sessionId with 8 bits, unique per client
Spec: §8.3.2.1, p. 59 — “A session is identified by an 8-bit sessionId. The sessionId is unique to an XRCE Agent for a given XRCE Client. The sessionId also determines whether the Header includes a clientKey or not.”
Repo: crates/xrce/src/header.rs (SessionId);
crates/xrce-agent/src/daemon/session.rs (session_ids)
Tests: crates/xrce/src/header.rs::tests::session_id_127_carries_client_key
Status: done
§8.3.2.1 sessionId 0 to 127 with clientKey
Spec: §8.3.2.1, p. 59 — “If the sessionId is between 0 and 127 (0x00 to 0x7f), both included, then the Header shall include the clientKey and the sessionId is scoped by the clientKey.”
Repo: crates/xrce/src/header.rs (SessionId::carries_client_key,
MessageHeader::with_client_key)
Tests: crates/xrce/src/header.rs::tests::header_with_client_key_wire_size_8,
crates/xrce/src/header.rs::tests::header_constructor_rejects_inconsistent_with_key
Status: done
§8.3.2.1 sessionId 128 to 255 without clientKey
Spec: §8.3.2.1, p. 59 — “If the sessionId is between 128 and 255 (0x80 to 0xff), both included, then the Header shall not include the clientKey and the sessionId is scoped by the source address of the message.”
Repo: crates/xrce/src/header.rs (MessageHeader::without_client_key);
crates/xrce-agent/src/daemon/transport.rs (PeerTable)
Tests: crates/xrce/src/header.rs::tests::header_no_client_key_wire_size_4,
crates/xrce-agent/src/daemon/transport.rs::tests::peer_table_resolves_bound_address
Status: done
§8.3.2.1 clientKey from the source address
Spec: §8.3.2.1, p. 59 — “If the clientKey does not appear explicitly in the message header, the XRCE Agent must be able to locate it from the source address of the message (see clause 8.3.2.4).”
Repo: crates/xrce-agent/src/daemon/transport.rs (PeerTable::resolve, bind)
Tests: crates/xrce-agent/src/daemon/transport.rs::tests::peer_table_bootstraps_from_create_client_payload,
crates/xrce-agent/src/daemon/transport.rs::tests::a_client_registering_again_is_answered_at_its_new_address
Status: done
§8.3.2.1 SESSION_ID_NONE_WITH_CLIENT_KEY = 0x00
Spec: §8.3.2.1, p. 59 — “The value 0 (0x00) shall be used to indicate the lack of a session within a Header containing a clientKey. This value is referred to as SESSION_ID_NONE_WITH_CLIENT_KEY.”
Repo: crates/xrce/src/header.rs (SESSION_ID_NONE_WITH_CLIENT_KEY,
SessionId::is_none, SessionId::none_like);
crates/xrce-agent/src/daemon/session.rs (refusal, handle_create_client);
crates/xrce-client/src/lib.rs (XrceClient::connect)
Tests: crates/xrce/src/header.rs::tests::only_0x00_and_0x80_are_the_no_session_values,
crates/xrce-agent/src/daemon/session.rs::tests::a_message_without_a_session_is_not_processed_unless_it_is_a_create_client,
crates/xrce-agent/src/daemon/session.rs::tests::a_create_client_for_a_session_id_of_no_session_is_refused,
crates/xrce-client/src/lib.rs::tests::create_client_travels_in_a_header_without_a_session
Status: done — the client sends CREATE_CLIENT in a header with 0x00 (session 0 to
127) or 0x80; in such a header the agent processes only CREATE_CLIENT (and
GET_INFO, §7.8.2.2) and refuses a CREATE_CLIENT that asks for 0x00 or 0x80 as
its session_id (d4aad7c50b6).
§8.3.2.1 SESSION_ID_NONE_WITHOUT_CLIENT_KEY = 0x80
Spec: §8.3.2.1, p. 59 — “The value 128 (0x80) shall be used to indicate the lack of a session within a Header that does not contain a clientKey. This value is referred to as SESSION_ID_NONE_WITHOUT_CLIENT_KEY.”
Repo: crates/xrce/src/header.rs (SESSION_ID_NONE_WITHOUT_CLIENT_KEY,
SessionId::is_none, SessionId::none_like);
crates/xrce-agent/src/daemon/session.rs (refusal);
crates/xrce-agent/src/daemon/discovery.rs (build_info_reply)
Tests: crates/xrce/src/header.rs::tests::only_0x00_and_0x80_are_the_no_session_values,
crates/xrce/src/header.rs::tests::header_roundtrip_no_key,
crates/xrce-agent/src/daemon/session.rs::tests::a_message_without_a_session_is_not_processed_unless_it_is_a_create_client,
crates/xrce-client/src/lib.rs::tests::create_client_travels_in_a_header_without_a_session
Status: done — the CREATE_CLIENT of a client with a session_id of 128 to 255 goes
in a header with 0x80 and no clientKey; the INFO of the discovery uses 0x80
(d4aad7c50b6).
§8.3.2.1 Values for “no session” in the header
Spec: §8.3.2.1, p. 59 — as above.
Repo: crates/xrce/src/header.rs (SessionId::is_none, SessionId::none_like);
crates/xrce-agent/src/daemon/session.rs (refusal, handle_create_client,
SessionEvent::MessageRefused);
crates/xrce-client/src/lib.rs (XrceClient::connect, send_control)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_message_without_a_session_is_not_processed_unless_it_is_a_create_client,
crates/xrce-agent/src/daemon/session.rs::tests::a_message_of_a_replaced_session_is_not_processed,
crates/xrce-agent/src/daemon/session.rs::tests::a_create_client_for_a_session_id_of_no_session_is_refused,
crates/xrce-client/src/lib.rs::tests::create_client_travels_in_a_header_without_a_session
Status: done — XrceClient::connect sends CREATE_CLIENT with SESSION_ID_NONE_* in
the header (0x00 with clientKey, 0x80 without); in a header without a
session the agent processes only CREATE_CLIENT and GET_INFO, refuses 0x00 and
0x80 as a requested session_id, and drops messages of a replaced session
(d4aad7c50b6).
§8.3.2.2 Streams within the session
Spec: §8.3.2.2, p. 59–60 — “Each XRCE message belongs to a single stream. […] Streams are scoped by the session they belong to.”
Repo: crates/xrce-agent/src/daemon/session.rs (reliable,
best_effort_seq keyed by (client, stream))
Tests: crates/xrce-agent/src/daemon/session.rs::tests::best_effort_messages_get_increasing_sequence_numbers
Status: done
§8.3.2.2 STREAMID_NONE
Spec: §8.3.2.2, p. 60 — “The streamId with value 0 (0x00) is referred as STREAMID_NONE. This stream is used for messages exclusively containing submessages that do not belong to any stream.”
Repo: crates/xrce/src/header.rs (StreamId::NONE)
Tests: crates/xrce/src/header.rs::tests::stream_id_classification
Status: done — the rules per submessage are at §8.3.5.11, §8.3.5.12, §8.3.5.15 and §8.3.5.16.
§8.3.2.2 streamId 1 to 127 best-effort
Spec: §8.3.2.2, p. 60 — “The streams with streamId between 1 (0x01) and 127 (0x7F), both included, shall be best-effort streams.”
Repo: crates/xrce/src/header.rs (StreamId::is_best_effort)
Tests: crates/xrce/src/header.rs::tests::stream_id_classification
Status: done
§8.3.2.2 streamId 128 to 255 reliable, the leading bit as a flag
Spec: §8.3.2.2, p. 60 — “The streams with streamId between 128 (0x80) and 255 (0xFF), both included, shall be reliable streams. Based on the rules above if the streamId is not STREAMID_NONE, then the leading bit of the streamId can be interpreted as a flag that indicates the reliability of the stream.”
Repo: crates/xrce/src/header.rs (StreamId::is_reliable)
Tests: crates/xrce/src/header.rs::tests::stream_id_classification
Status: done
§8.3.2.2 Built-in streams 0x01 and 0x80
Spec: §8.3.2.2, p. 60 — “There are two built-in streams that are created whenever a session is created: A built-in best-effort stream identified by a streamId with value 1 (0x01). […] A built-in reliable stream identified by a streamId with value 128 (0x80).”
Repo: crates/xrce/src/header.rs (StreamId::BUILTIN_BEST_EFFORT,
BUILTIN_RELIABLE); crates/xrce-client/src/lib.rs
(send_maybe_fragmented: stream 0x80 or 0x01)
Tests: crates/xrce/src/header.rs::tests::stream_id_classification,
crates/xrce-agent/src/daemon/session.rs::tests::reliable_outbound_messages_get_real_incrementing_sequence_numbers
Status: done — a stream’s state comes into being on first use.
§8.3.2.3 STREAMID_NONE without order
Spec: §8.3.2.3, p. 60 — “For the stream with streamId STREAMID_NONE, the sequenceNr does not impose any order; however, it still may be used to discard duplicate messages.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_message: the order check
only for best-effort and reliable streams)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::best_effort_streams_drop_duplicates_and_older_messages
Status: done — on STREAMID_NONE the agent checks neither order nor duplicates; the
spec permits discarding duplicates there and does not require it
(d4aad7c50b6).
§8.3.2.3 Order and duplicates on the other streams
Spec: §8.3.2.3, p. 60 — “For the stream with streamId different from STREAMID_NONE, the sequenceNr imposes an order. Messages within a stream shall not be delivered out of order. In addition, duplicate messages shall be discarded.”
Repo: crates/xrce/src/reliable.rs (recv_data, drain_in_order);
crates/xrce-agent/src/daemon/session.rs (handle_message,
take_best_effort); crates/xrce-client/src/lib.rs (ingest_message)
Tests: crates/xrce/src/reliable.rs::tests::recv_data_reorders_out_of_order,
crates/xrce/src/reliable.rs::tests::recv_data_drops_duplicates,
crates/xrce-agent/src/daemon/session.rs::tests::out_of_order_reliable_messages_wait_for_the_gap_and_report_a_truthful_acknack,
crates/xrce-agent/src/daemon/session.rs::tests::best_effort_streams_drop_duplicates_and_older_messages,
crates/xrce-client/src/lib.rs::tests::a_best_effort_stream_discards_duplicate_and_older_messages
Status: done — reliable streams reorder and discard duplicates through recv_data
and drain_in_order; best-effort streams discard duplicates and older
messages in the agent and in the client (d4aad7c50b6, see the item below).
§8.3.2.3 Order and duplicates on best-effort streams
Spec: §8.3.2.3, p. 60 — as above.
Repo: crates/xrce-agent/src/daemon/session.rs (take_best_effort,
best_effort_in, SessionEvent::BestEffortMessageDiscarded);
crates/xrce-client/src/lib.rs (ingest_message, best_effort_in,
ClientEvent::BestEffortMessageDiscarded)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::best_effort_streams_drop_duplicates_and_older_messages,
crates/xrce-client/src/lib.rs::tests::a_best_effort_stream_discards_duplicate_and_older_messages
Status: done — a message that is not newer than the last one of its stream (RFC 1982,
16 bit, also across the wrap of the counter) is discarded and reported as an
event; each stream counts for itself (d4aad7c50b6).
§8.3.2.3 Serial number arithmetic with 16 bits
Spec: §8.3.2.3, p. 60 — “Addition and comparison of sequence numbers shall use Serial Number Arithmetic as defined by [IETF RFC-1982] with SERIAL_BITS set to 16. This implies that the maximum number of outstanding (unacknowledged) messages for a specific client session stream is limited to 2 15 —that is, 32768.”
Repo: crates/xrce/src/serial_number.rs (SerialNumber16,
wrapping_lt, wrapping_cmp)
Tests: crates/xrce/src/serial_number.rs::tests::lt_across_wrap_boundary,
crates/xrce/src/serial_number.rs::tests::undefined_pair_at_exactly_half_window,
crates/xrce/src/serial_number.rs::tests::wrap_around_does_not_break_lt_for_consecutive_numbers
Status: done — the sender keeps at most 16 messages open
(SENDER_WINDOW_CAP).
§8.3.2.3 sequenceNr little-endian
Spec: §8.3.2.3, p. 60 — “The sequenceNr shall be encoded using little endian format.”
Repo: crates/xrce/src/header.rs (write_to)
Tests: crates/xrce/src/header.rs::tests::header_layout_bytes_no_key
Status: done
§8.3.2.4 clientKey for sessionId 0 to 127
Spec: §8.3.2.4, p. 60 — “The clientKey shall be present on the Header if the sessionId is between 0 and 127. […] If the clientKey is present, it shall contain the ClientKey associated with the XRCE Client.”
Repo: crates/xrce-client/src/lib.rs (header_client_key)
Tests: crates/xrce-agent/tests/endpoint_client_fixtures.rs::every_fixture_shares_the_same_client_key_and_session_id
Status: done
§8.3.2.4 Deriving the ClientKey from the source address
Spec: §8.3.2.4, p. 60 — “If the clientKey is not present, the XRCE Agent shall be able to derive the ClientKey associated with the XRCE Client from the source address of the message. This means that the ClientKey has either been pre-configured on the XRCE Agent for that particular source address, or it has been exchanged as part of the session establishment.”
Repo: crates/xrce-agent/src/daemon/transport.rs (PeerTable::bind)
Tests: crates/xrce-agent/src/daemon/transport.rs::tests::peer_table_bootstraps_from_create_client_payload
Status: done — through the exchange in CREATE_CLIENT; a pre-configuration per source address does not exist.
§8.3.2.4 Protection of the ClientKey by the transport
Spec: §8.3.2.4, p. 60 — “Any exchange of the clientKey is protected by the security mechanisms provided by the XRCE transport.”
Repo: crates/xrce-agent/src/daemon/config.rs (ListenerConfig::Dtls,
ListenerConfig::Tls); crates/xrce-agent/src/daemon/transport/secure.rs;
crates/xrce/src/transport_dtls.rs, crates/xrce/src/transport_tls.rs
Tests: crates/xrce-agent/tests/secure_listeners.rs::tls::a_client_that_trusts_the_agents_certificate_opens_a_session,
crates/xrce-agent/tests/secure_listeners.rs::tls::a_plain_text_create_client_on_the_tls_port_is_not_answered,
crates/xrce-agent/tests/secure_listeners.rs::dtls::a_client_that_trusts_the_agents_certificate_opens_a_session,
crates/xrce-agent/tests/secure_listeners.rs::dtls::a_plain_text_create_client_on_the_dtls_port_is_not_answered
Status: done — listeners kind: dtls and kind: tls with certificate and key from
PEM files (eb44fbbf575); plain text on that port is not answered. The
features dtls and tls are not part of daemon; a binary needs
--features dtls,tls. Secured listeners are not announced in GET_INFO(AGENT)
and the multicast discovery. The DTLS handshake of one peer runs in the
listener’s accept task, one at a time.
§8.3.3 Submessage with header and payload up to 64 KB
Spec: §8.3.3, p. 60 — “Following the message header there shall be one or more submessages. A Submessage shall be composed of a SubmessageHeader and a payload.” Payload “up to to 64 KB”.
Repo: crates/xrce/src/submessages/mod.rs (Submessage,
Submessage::new)
Tests: crates/xrce/src/submessages/mod.rs::tests::message_decode_rejects_truncated_body,
crates/xrce/src/submessages/mod.rs::tests::message_encode_decode_roundtrip_no_key_single_sm
Status: done
§8.3.3 Submessages on multiples of 4
Spec: §8.3.3, p. 60 — “Submessages shall start at an offset that is a multiple of 4 relative to the beginning of the Message. This means that additional padding may be added between the end of a submessage and the beginning of the next submessage.”
Repo: crates/xrce/src/submessages/mod.rs (Message::encode,
Message::decode: UnalignedSubmessage)
Tests: crates/xrce/src/submessages/mod.rs::tests::message_two_submessages_padded_correctly,
crates/xrce/tests/foreign_frames.rs::every_client_datagram_decodes_and_writes_back
Status: done — after the last submessage the code writes no padding, eProsima writes it; the decoder accepts both.
§8.3.4 Layout of the SubmessageHeader
Spec: §8.3.4, p. 61 — submessageId (8 bits), flags (8 bits),
submessageLength (16 bits).
Repo: crates/xrce/src/submessages/mod.rs (SubmessageHeader,
to_bytes, from_bytes)
Tests: crates/xrce/src/submessages/mod.rs::tests::submessage_header_roundtrip
Status: done
§8.3.4.1 submessageId
Spec: §8.3.4.1, p. 61 — “The submessageId identifies the kind of submessage. The kinds of submessages are defined in 8.3.5.”
Repo: crates/xrce/src/submessages/mod.rs (SubmessageId::from_u8)
Tests: crates/xrce/src/submessages/mod.rs::tests::submessage_id_rejects_unknown_byte
Status: done — an unknown submessageId discards the whole message.
§8.3.4.2 Endianness bit in the flags
Spec: §8.3.4.2, p. 61 — “Bit 0, the ‘Endianness’ bit, shall indicate the endianness used to encode the submessage header and payload. If the Endianness bit is set to 0, the encoding shall be big endian and otherwise little endian. The flags field for all submessage kinds shall have the Endianness bit. Specific submessage kinds may define additional flag bits.”
Repo: crates/xrce/src/submessages/mod.rs (FLAG_E_LITTLE_ENDIAN,
SubmessageHeader::body_endianness); crates/xrce/src/handshake.rs,
crates/xrce/src/object_info.rs, crates/xrce/src/transport_locator.rs
(encode_with/decode_with); crates/xrce-agent/src/daemon/session.rs,
crates/xrce-client/src/lib.rs (reading with body_endianness)
Tests: crates/xrce/src/submessages/acknack.rs::tests::acknack_be_roundtrip,
crates/xrce/src/submessages/heartbeat.rs::tests::heartbeat_be_roundtrip,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_big_endian_binary_topic_reads_back,
crates/xrce/src/submessages/create_client.rs::tests::create_client_follows_the_e_flag
Status: done — all payloads follow the bit (b9255734bfb, 299b3a41398, see the
item below). The agent writes its own replies little-endian with E=1; each
submessage states its own byte order.
§8.3.4.2 Payloads and the endianness bit
Spec: §8.3.4.2, p. 61 — as above.
Repo: crates/xrce/src/handshake.rs (ClientRepresentation,
AgentRepresentation, PropertySeq: encode_with/decode_with);
crates/xrce/src/object_info.rs (ObjectInfo, ActivityInfoVariant);
crates/xrce/src/transport_locator.rs (ports in the byte order of the flag);
crates/xrce/src/submessages/create_client.rs
(CreateClientPayload::into_submessage_with)
Tests: crates/xrce/src/handshake.rs::tests::a_big_endian_client_representation_with_properties_reads_back,
crates/xrce/src/handshake.rs::tests::a_big_endian_agent_representation_with_properties_reads_back,
crates/xrce/src/submessages/create_client.rs::tests::create_client_follows_the_e_flag,
crates/xrce/src/transport_locator.rs::tests::medium_has_a_padding_octet_and_a_port_in_the_byte_order_of_the_flag,
crates/xrce-agent/src/daemon/session.rs::tests::a_big_endian_create_client_with_properties_is_read_right,
crates/xrce-client/src/lib.rs::tests::a_big_endian_status_agent_is_read_with_its_properties
Status: done — ClientRepresentation, AgentRepresentation, PropertySeq,
ObjectInfo, ActivityInfoVariant and the ports of the TransportLocator
are read and written in the byte order of the E flag (b9255734bfb,
299b3a41398). The agent still writes the INFO it builds little-endian with
E=1.
§8.3.4.3 submessageLength without the header, little-endian
Spec: §8.3.4.3, p. 61 — “The submessageLength indicates the length of the Submessage (excluding the Submessage header). The submessageLength shall be encoded using little endian format, independent of the value of the flags.”
Repo: crates/xrce/src/submessages/mod.rs (SubmessageHeader::to_bytes)
Tests: crates/xrce/src/submessages/mod.rs::tests::submessage_header_length_is_always_le_even_with_be_body
Status: done
§8.3.4.4 payload with the types of §7.7
Spec: §8.3.4.4, p. 61 — “The definition of the payload shall use the data types defined in clause 7.7.”
Repo: —
Tests: —
Status: n/a (informative) — structure of the specification; the types
are in the items on §7.7.
§8.3.5 Submessage Types
§8.3.5 Table 10 values of the SubmessageId
Spec: §8.3.5, Table 10, p. 62–63 — CREATE_CLIENT 0, CREATE 1, GET_INFO 2, DELETE 3, STATUS_AGENT 4, STATUS 5, INFO 6, WRITE_DATA 7, READ_DATA 8, DATA 9, ACKNACK 10, HEARTBEAT 11, RESET 12, FRAGMENT 13, TIMESTAMP 14, TIMESTAMP_REPLY 15.
Repo: crates/xrce/src/submessages/mod.rs (SubmessageId)
Tests: crates/xrce/tests/profile_conformance.rs::spec_1_2_submessage_ids_match_spec_assignment,
crates/xrce/src/submessages/mod.rs::tests::submessage_id_roundtrip_all_16_values
Status: done — the text before it says 13 kinds; Table 10 and Figure 7 show 16.
§8.3.5.1 CREATE_CLIENT from the client
Spec: §8.3.5.1, p. 63 — “The CREATE_CLIENT submessage shall be sent by the XRCE Client to create an XRCE ProxyClient.”
Repo: crates/xrce-client/src/lib.rs (XrceClient::connect)
Tests: crates/xrce-client/src/lib.rs::tests::connect_sends_a_real_create_client_and_moves_to_connecting
Status: done
§8.3.5.1 Reception calls create_client
Spec: §8.3.5.1, p. 63 — “Reception of this submessage shall result in the XRCE Agent calling the create_client operation on the XRCE Root object, see 7.8.2.1. The parameters to this operation are obtained from the payload.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create_client)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::create_client_happy_path_registers_and_replies_ok
Status: done
§8.3.5.1 STATUS_AGENT in response
Spec: §8.3.5.1, p. 63 — “The XRCE Agent shall send a STATUS_AGENT message in response, see 8.3.5.5.”
Repo: crates/xrce-agent/src/daemon/session.rs (agent_status_reply,
handle_create_client)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::create_client_happy_path_registers_and_replies_ok,
crates/xrce-agent/src/daemon/session.rs::tests::create_client_rejects_wrong_major_version,
crates/xrce-agent/src/daemon/session.rs::tests::a_wrong_cookie_is_answered_with_a_status_agent
Status: done — every outcome is answered with STATUS_AGENT; a wrong cookie or an
unreadable payload gives STATUS_AGENT with STATUS_ERR_INVALID_DATA
(d7aec9c2d78).
§8.3.5.1 Flags of CREATE_CLIENT
Spec: §8.3.5.1.1, p. 63 — “The CREATE_CLIENT submessage does not define any additional flag bits beyond the common ones specified in 8.3.4.2.”
Repo: crates/xrce/src/submessages/create_client.rs
(CreateClientPayload::into_submessage)
Tests: crates/xrce/src/submessages/create_client.rs::tests::create_client_roundtrip_via_submessage,
crates/xrce/src/submessages/create_client.rs::tests::annex_b_1_create_client_example_bytes
Status: done — the code sets the E flag only. Annex B.1 names 0x07 (“reuse,
replace”), which CREATE_CLIENT does not have; the test for Annex B.1
(be97b3247a6) checks the bytes of the CLIENT_Representation, not that flag.
§8.3.5.1 Payload CREATE_CLIENT_Payload
Spec: §8.3.5.1.2, p. 64 — “struct CLIENT_Representation { XrceCookie xrce_cookie; XrceVersion xrce_version; XrceVendorId xrce_vendor_id; ClientKey client_key; SessionId session_id; @optional PropertySeq properties; }; struct CREATE_CLIENT_Payload { CLIENT_Representation client_representation; };”
Repo: crates/xrce/src/handshake.rs (ClientRepresentation, encode_form,
decode_form); crates/xrce/src/encoding.rs
(RepresentationTimestamps); crates/xrce/src/submessages/create_client.rs;
agent key representation_timestamps in
crates/xrce-agent/src/daemon/config.rs; XrceClient::set_representation_timestamps
Tests: crates/xrce/src/submessages/create_client.rs::tests::decodes_the_committed_fixture_member_by_member,
crates/xrce/src/submessages/create_client.rs::tests::annex_b_1_create_client_example_bytes,
crates/xrce/src/handshake.rs::tests::client_representation_decodes_the_captured_create_client_prefix,
crates/xrce/src/handshake.rs::tests::by_default_the_representations_have_no_timestamp,
crates/xrce/src/handshake.rs::tests::the_prose_form_has_a_time_t_after_the_vendor_id,
crates/xrce-client/src/lib.rs::tests::the_representation_timestamp_is_an_option_of_the_client,
crates/xrce-agent/src/daemon/config.rs::tests::the_form_of_the_representations_can_be_set
Status: done — Annex A and the bytes of Annex B.1 have no client_timestamp; that is
the default. The prose of §7.8.2.1 and §8.3.5.1.2 lists a Time_t after
xrce_vendor_id; that form is the setting representation_timestamps: present (Rust: encoding::RepresentationTimestamps::Present; SDKs: option
representation timestamps) (f8bdf3cd878, 571ee6893d1). Both forms are
tested with bytes in zerodds-xrce and in the client. The code reads and
writes two octets after properties as requested_mtu, as eProsima sends
them; the spec does not know the field. PropertySeq is aligned after Annex A
(ca0cf7e08bf).
§8.3.5.2 CREATE from the client
Spec: §8.3.5.2, p. 64 — “The CREATE submessage shall be sent by the XRCE Client to create an XRCE Object.”
Repo: crates/xrce-client/src/lib.rs (XrceClient::create_object)
Tests: crates/xrce-client/src/lib.rs::tests::create_object_builds_the_real_two_level_object_variant
Status: done
§8.3.5.2 Reception calls create with flags and payload
Spec: §8.3.5.2, p. 64 — “Reception of this submessage shall result in the XRCE Agent calling the create operation on the XRCE ProxyClient object […]. The parameters to this operation shall be obtained from the SubmessageHeader flags and payload.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create)
Tests: crates/xrce-agent/tests/replay_foreign_session.rs::replay_matches_the_real_agents_create_client_create_and_delete_replies
Status: done
§8.3.5.2 STATUS in response to CREATE
Spec: §8.3.5.2, p. 64 — “The XRCE Agent shall send a STATUS submessage in response, see 8.3.5.6.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create, status_reply,
refuse_unreadable)
Tests: crates/xrce-agent/tests/replay_foreign_session.rs::replay_matches_the_real_agents_create_client_create_and_delete_replies,
crates/xrce-agent/src/daemon/session.rs::tests::a_create_without_a_base_object_request_is_answered
Status: done — every request gets a STATUS: a payload without a BaseObjectRequest
and an unreadable representation give STATUS_ERR_INVALID_DATA
(70963ac46ec, 97de94f63e4).
§8.3.5.2 CREATE without BaseObjectRequest
Spec: §8.3.5.2, p. 64 — as above.
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create,
SessionEvent::CreateRefused)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_create_without_a_base_object_request_is_answered
Status: done — a CREATE of fewer than 4 octets gives a STATUS with
STATUS_ERR_INVALID_DATA for OBJECTID_INVALID (with the request_id when
its two octets are there) and a CreateRefused event (70963ac46ec).
§8.3.5.2 Flags reuse and replace
Spec: §8.3.5.2.1, p. 64 — “Bit 1, the ‘Reuse’ bit, encodes the value of the CreationMode reuse field. Bit 2, the ‘Replace’ bit, encodes the value of the CreationMode replace field.”
Repo: crates/xrce/src/submessages/create.rs (CREATE_FLAG_REUSE,
CREATE_FLAG_REPLACE)
Tests: crates/xrce/src/submessages/create.rs::tests::create_roundtrip_carries_reuse_replace_flags,
crates/xrce/src/submessages/create.rs::tests::create_default_flags_have_no_reuse_no_replace
Status: done
§8.3.5.2 Payload CREATE_Payload
Spec: §8.3.5.2.2, p. 64–65 — “struct CREATE_Payload : BaseObjectRequest { ObjectVariant object_representation; };”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create:
BaseObjectRequest::decode, ObjectVariant::decode_for_kind)
Tests: crates/xrce-agent/tests/endpoint_client_fixtures.rs::create_fixture_decodes_into_an_object_the_agent_accepts,
crates/xrce/src/object_repr.rs::tests::participant_representation_matches_the_captured_create_bytes
Status: done
§8.3.5.3 GET_INFO from the client
Spec: §8.3.5.3, p. 65 — “The GET_INFO submessage shall be sent by the XRCE Client to get information about a resource identified by its object_id.”
Repo: crates/xrce-client/src/lib.rs (XrceClient::request_get_info,
XrceClient::request_agent_info, ClientEvent::Info,
ClientEvent::InfoUnreadable)
Tests: crates/xrce-client/src/lib.rs::tests::request_agent_info_works_before_the_session_and_sends_the_mask,
crates/xrce-client/src/lib.rs::tests::request_get_info_needs_a_session_and_names_the_object,
crates/xrce-client/src/lib.rs::tests::an_info_is_read_into_an_event
Status: done — request_get_info asks about an object of the session,
request_agent_info about the agent, also without a session; an INFO is
evaluated as ClientEvent::Info (ca0cf7e08bf).
§8.3.5.3 Target by the ObjectKind of the object_id
Spec: §8.3.5.3, p. 65 — “The targeted XRCE Object shall depend on the ObjectKind encoded in the last 4 bits of the object_id. If the ObjectKind is set to OBJK_AGENT, then it shall result in the XRCE Agent calling the get_info operation on the XRCE Root object […]. If the ObjectKind is set to one of OBJK_PARTICIPANT, […] That is to a value between 0x01 and 0x0c (both included), then it shall result in the XRCE Agent calling the get_info operation on the XRCE ProxyClient object”.
Repo: crates/xrce-agent/src/daemon/session.rs (handle_get_info: kind
OBJK_AGENT is the Root, 0x01 to 0x0C the ProxyClient, OBJK_CLIENT the
session); crates/xrce-agent/src/daemon/discovery.rs
(run_discovery_responder)
Tests: crates/xrce-agent/src/daemon/discovery.rs::tests::discovery_responder_answers_get_info_on_agent,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_the_agent_in_a_session_returns_activity_and_representation,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_without_a_session_is_answered_for_the_agent_only,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_an_object_returns_the_object_variant_it_was_created_with
Status: done — the Root answers every object_id of kind OBJK_AGENT, also without
a session; the kinds 0x01 to 0x0C go to the ProxyClient (ca0cf7e08bf). For
the Root the spec refers to §7.8.3.3 instead of §7.8.2.2, and the list says
“OBJK” instead of OBJK_TOPIC.
§8.3.5.3 Distinction by the nibble of the kind
Spec: §8.3.5.3, p. 65 — as above.
Repo: crates/xrce-agent/src/daemon/session.rs (handle_get_info);
crates/xrce-agent/src/daemon/discovery.rs (run_discovery_responder)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::any_object_id_of_kind_agent_is_the_root_in_a_session,
crates/xrce-agent/src/daemon/transport.rs::tests::the_udp_listener_answers_get_info_before_a_session,
crates/xrce-agent/src/daemon/transport.rs::tests::the_tcp_listener_answers_get_info_before_a_session
Status: done — handle_get_info and the responder check the kind of the object_id,
not the value 0xFFFD; an ObjectId 0x010 of kind OBJK_AGENT is answered
by the Root (ca0cf7e08bf, a8f300b7bcf).
§8.3.5.3 INFO in response to GET_INFO
Spec: §8.3.5.3, p. 65 — “The XRCE Agent shall send an INFO submessage in response to this message, see 8.3.5.6.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_get_info, answer_info,
InfoPayload)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_the_agent_in_a_session_returns_activity_and_representation,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_a_missing_object_is_an_info_with_unknown_reference,
crates/xrce-agent/src/daemon/discovery.rs::tests::discovery_responder_answers_get_info_on_agent
Status: done — every answer to GET_INFO is an INFO; for an unknown object it carries
STATUS_ERR_UNKNOWN_REFERENCE, without permission STATUS_ERR_DENIED
(ca0cf7e08bf). The reference says §8.3.5.6 instead of §8.3.5.7.
§8.3.5.3 Flags of GET_INFO
Spec: §8.3.5.3.1, p. 65 — “The GET_INFO submessage does not define any additional flag bits beyond the common ones specified in 8.3.4.2.”
Repo: crates/xrce/src/submessages/get_info.rs
(GetInfoPayload::into_submessage)
Tests: crates/xrce/src/submessages/get_info.rs::tests::get_info_roundtrip
Status: done
§8.3.5.3 Payload GET_INFO_Payload
Spec: §8.3.5.3.2, p. 65 — “struct GET_INFO_Payload : BaseObjectRequest { InfoMask info_mask; };”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_get_info:
BaseObjectRequest::decode, GetInfoPayload::parse);
crates/xrce/src/object_info.rs (InfoMask)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::get_info_without_an_info_mask_is_invalid_data,
crates/xrce/src/object_info.rs::tests::info_mask_bits_and_wire_form,
crates/xrce/src/submessages/get_info.rs::tests::get_info_roundtrip,
crates/xrce-agent/src/daemon/discovery.rs::tests::discovery_responder_answers_get_info_on_agent
Status: done — the agent reads the BaseObjectRequest and the info_mask; without
the mask it answers with an INFO and STATUS_ERR_INVALID_DATA
(ca0cf7e08bf). The client_info of Figure 10 (§8.4.4) follows the
InfoMask (GetInfoPayload::with_client_info), because Annex A has no member
for it.
§8.3.5.4 DELETE from the client
Spec: §8.3.5.4, p. 65 — “The DELETE submessage shall be sent by the XRCE Client to delete the XRCE:ProxyClient or any other XRCE Object”.
Repo: crates/xrce-client/src/lib.rs (XrceClient::delete_object,
disconnect)
Tests: crates/xrce-client/src/lib.rs::tests::disconnect_sends_delete_client_and_clears_state
Status: done
§8.3.5.4 delete_client for OBJK_CLIENT, delete otherwise
Spec: §8.3.5.4, p. 65–66 — “The related XRCE Object is identified by the object_id field in the payload. If the ObjectVariant contained within the payload has ObjectKind set to OBJK_CLIENT, then the XRCE Agent shall call the delete_client operation. Otherwise it shall call the delete operation.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_delete)
Tests: crates/xrce-agent/tests/replay_foreign_session.rs::replay_matches_the_real_agents_create_client_create_and_delete_replies,
crates/xrce-agent/src/daemon/session.rs::tests::delete_client_needs_a_proxy_client
Status: done — the code takes the kind from the object_id; DELETE_Payload has no
ObjectVariant. delete_client without a ProxyClient gives
STATUS_ERR_UNKNOWN_REFERENCE (d7aec9c2d78).
§8.3.5.4 STATUS in response to DELETE
Spec: §8.3.5.4, p. 66 — “The XRCE Agent shall send a STATUS submessage in response, see 8.3.5.6.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_delete, status_reply)
Tests: crates/xrce-agent/tests/replay_foreign_session.rs::replay_matches_the_real_agents_create_client_create_and_delete_replies
Status: done — the code answers every DELETE with a STATUS, delete_client
included, as the text of the clause says. Table 14 (p. 86) names STATUS_AGENT
for delete_client; there is no setting for it.
§8.3.5.4 Flags and payload DELETE_Payload
Spec: §8.3.5.4.1–§8.3.5.4.2, p. 66 — no additional flags; “struct DELETE_Payload : BaseObjectRequest { };”
Repo: crates/xrce/src/submessages/delete.rs (DeletePayload)
Tests: crates/xrce-agent/tests/endpoint_client_fixtures.rs::delete_fixture_decodes_and_removes_the_object_create_added
Status: done
§8.3.5.5 STATUS_AGENT on CREATE_CLIENT
Spec: §8.3.5.5, p. 66 — “The STATUS_AGENT submessage shall be sent by the XRCE Agent in response to a CREATE_CLIENT submessage. The submessage shall contain the returnStatus to the create_client operation invocation”.
Repo: crates/xrce-agent/src/daemon/session.rs (agent_status_reply; SessionEngine::handle_create_client)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::create_client_happy_path_registers_and_replies_ok,
crates/xrce-agent/src/daemon/session.rs::tests::a_wrong_cookie_is_answered_with_a_status_agent,
crates/xrce-agent/src/daemon/session.rs::tests::create_client_rejects_wrong_major_version
Status: done — Commits d7aec9c2d78. every failure of CREATE_CLIENT (wrong cookie,
a session_id that is no session, wrong major version, ClientKey not
authorized, no resources) is answered with a STATUS_AGENT, not a STATUS.
§8.3.5.5 Flags of STATUS_AGENT
Spec: §8.3.5.5.1, p. 66 — no additional flags.
Repo: crates/xrce/src/submessages/status_agent.rs
(StatusAgentPayload::into_submessage)
Tests: crates/xrce/src/submessages/status_agent.rs::tests::status_agent_roundtrip,
crates/xrce-client/src/lib.rs::tests::a_big_endian_status_agent_is_read_with_its_properties
Status: done — the agent writes the submessage with the E flag set and no
other flag; the client also reads E=0 (§8.3.4.2, b9255734bfb).
§8.3.5.5 Payload STATUS_AGENT_Payload
Spec: §8.3.5.5.2, p. 66–67 — “struct STATUS_AGENT_Payload { AGENT_Representation agent_info; }; If the operation fails, the STATUS_AGENT_Payload shall have the ResultStatus within the BaseObjectReply set to with the StatusValue that corresponds to the type of error encountered.”
Repo: crates/xrce-agent/src/daemon/session.rs (agent_status_reply); crates/xrce/src/submessages/status_agent.rs (StatusAgentPayload::result_and_position); crates/xrce-client/src/lib.rs (handle_status_agent)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::the_status_agent_payload_is_annex_a_unless_the_result_status_is_named, crates/xrce-agent/src/daemon/config.rs::tests::the_payload_of_status_agent_can_be_set
Status: done — the IDL of Annex A is STATUS_AGENT_Payload { AGENT_Representation agent_info; }: a successful CREATE_CLIENT is answered with the AGENT_Representation alone (agent_timestamp only with representation_timestamps: present). The form of the text and of the eProsima capture with a ResultStatus in front is the setting status_agent: with_result_status; a failure carries the ResultStatus the text gives it in both forms because the IDL has no room for it. The client reads both (told apart by the cookie); the replay sets the setting. ceff32b54a4.
### §8.3.5.5 request_id and object_id in STATUS_AGENT
Spec: §8.3.5.5.2, p. 67 — “The request_id and object_id within the
BaseObjectReply shall match the namesake fields in the BaseObjectRequest of the
corresponding CREATE_CLIENT message.”
Repo: —
Tests: —
Status: n/a (informative) — The text asks that request_id and object_id in the BaseObjectReply of the STATUS_AGENT equal those of the BaseObjectRequest of the CREATE_CLIENT. CREATE_CLIENT_Payload has no BaseObjectRequest in Annex A (only the CLIENT_Representation), so there is nothing to equal, and STATUS_AGENT_Payload has no BaseObjectReply (see the payload item). There is no requirement that can be fulfilled.
### §8.3.5.5 xrce_cookie XRCE
Spec: §8.3.5.5.2, p. 67 — “The xrce_cookie shall be set to the four bytes {‘X’, ‘R’, ‘C’, ‘E’}.”
Repo: crates/xrce/src/handshake.rs (XRCE_COOKIE,
AgentRepresentation::encode_into)
Tests: crates/xrce/src/handshake.rs::tests::agent_representation_roundtrip_no_properties,
crates/xrce/src/handshake.rs::tests::agent_representation_decodes_the_captured_status_agent_body
Status: done
§8.3.5.5 xrce_version of the agent
Spec: §8.3.5.5.2, p. 67 — “The xrce_version shall be set to the version of the XRCE protocol that the Agent will implement in its connection to the Client.”
Repo: crates/xrce/src/handshake.rs (XRCE_VERSION);
crates/xrce-agent/src/daemon/session.rs (agent_status_reply)
Tests: crates/xrce/src/handshake.rs::tests::agent_representation_decodes_the_captured_status_agent_body
Status: done
§8.3.5.6 STATUS on CREATE and DELETE
Spec: §8.3.5.6, p. 67 — “The STATUS submessage shall be sent by the XRCE Agent in response to a CREATE or DELETE.”
Repo: crates/xrce-agent/src/daemon/session.rs (status_reply; handle_create, handle_delete)
Tests: crates/xrce-agent/tests/replay_foreign_session.rs::replay_matches_the_real_agents_create_client_create_and_delete_replies,
crates/xrce-agent/src/daemon/session.rs::tests::delete_client_needs_a_proxy_client,
crates/xrce-agent/src/daemon/session.rs::tests::a_create_without_a_base_object_request_is_answered
Status: done
§8.3.5.6 STATUS on READ_DATA on failure
Spec: §8.3.5.6, p. 67 — “The STATUS submessage shall also be sent by the XRCE Agent in response to a READ_DATA submessage when the returnStatus to the read_data operation is anything other than STATUS_OK.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_read_data; refuse_unreadable)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::read_data_with_an_unhonorable_content_filter_is_rejected_not_silently_unfiltered,
crates/xrce-agent/src/daemon/session.rs::tests::a_request_that_cannot_be_read_is_answered_invalid_data,
crates/xrce-agent/src/daemon/session.rs::tests::a_sample_too_large_for_data_is_reported
Status: done — a failure to set the filter, an unreadable request
(97de94f63e4) and a sample that fits no submessage are answered with a STATUS.
§8.3.5.6 STATUS carries the operation’s return value
Spec: §8.3.5.6, p. 67 — “The STATUS submessage shall contain the returnStatus to the operation that was triggered by the corresponding request message.”
Repo: crates/xrce-agent/src/daemon/session.rs (status_reply)
Tests: crates/xrce-agent/tests/replay_foreign_session.rs::replay_matches_the_real_agents_create_client_create_and_delete_replies
Status: done
§8.3.5.6 Flags and payload STATUS_Payload
Spec: §8.3.5.6.1–§8.3.5.6.2, p. 67 — no additional flags; “struct STATUS_Payload : BaseObjectReply { }; […] The request_id and object_id within the BaseObjectReply shall match the namesake fields in the corresponding request message.”
Repo: crates/xrce/src/object_info.rs (BaseObjectReply, ResultStatus);
crates/xrce/src/submessages/status.rs (StatusPayload)
Tests: crates/xrce/src/object_info.rs::tests::base_object_reply_roundtrip,
crates/xrce/tests/unannotated_types.rs::the_final_setting_writes_the_reference_implementations_octets,
crates/xrce-agent/tests/replay_foreign_session.rs::replay_matches_the_real_agents_create_client_create_and_delete_replies
Status: done — ResultStatus has no @extensibility in Annex A and is
APPENDABLE: by default it carries a DHEADER (BaseObjectReply 10 octets), with
unannotated_types: final it is 6 octets as in the capture; both forms are read
(7f85e76debd, 220857a1e90).
§8.3.5.7 INFO on GET_INFO
Spec: §8.3.5.7, p. 67 — “The INFO submessage shall be sent by the XRCE Agent to the XRCE Client in response to a GET_INFO message.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_get_info, answer_info);
crates/xrce-agent/src/daemon/discovery.rs (build_info_reply)
Tests: crates/xrce-agent/src/daemon/discovery.rs::tests::discovery_responder_answers_get_info_on_agent,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_the_agent_in_a_session_returns_activity_and_representation,
crates/xrce-agent/src/daemon/transport.rs::tests::the_udp_listener_answers_get_info_before_a_session,
crates/xrce-agent/src/daemon/transport.rs::tests::the_tcp_listener_answers_get_info_before_a_session
Status: done — Commits ca0cf7e08bf, a8f300b7bcf. inside a session, before a
session at the UDP and TCP listeners, and over the discovery group.
§8.3.5.7 Flags of INFO
Spec: §8.3.5.7.1, p. 67 — no additional flags.
Repo: crates/xrce/src/submessages/info.rs (InfoPayload::into_submessage_with)
Tests: crates/xrce/src/submessages/info.rs::tests::info_roundtrip,
crates/xrce/src/submessages/info.rs::tests::info_payload_is_the_reply_and_the_object_info
Status: done — the E flag states the byte order of the payload; the agent
writes E=1 (ca0cf7e08bf).
§8.3.5.7 Payload INFO_Payload
Spec: §8.3.5.7.2, p. 67–68 — “struct INFO_Payload : BaseObjectReply { ObjectInfo object_info; }; […] The activity and config within members within the INFO_Payload shall contain the value of the identically named output parameters of the get_info operation.”
Repo: crates/xrce/src/submessages/info.rs (InfoPayload::new, InfoPayload::parse);
crates/xrce/src/object_info.rs (BaseObjectReply, ObjectInfo, ActivityInfoVariant);
crates/xrce-agent/src/daemon/session.rs (handle_get_info, object_info, agent_object_info)
Tests: crates/xrce/src/submessages/info.rs::tests::info_payload_is_the_reply_and_the_object_info,
crates/xrce/src/object_info.rs::tests::object_info_puts_the_activity_before_the_config,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_an_object_returns_the_object_variant_it_was_created_with,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_a_data_writer_reports_its_activity,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_a_data_reader_reports_its_activity,
crates/xrce-agent/src/daemon/discovery.rs::tests::the_info_mask_selects_activity_and_configuration
Status: done — Commits ca0cf7e08bf. BaseObjectReply and ObjectInfo (activity
before config, @optional as a presence octet) per Annex A; activity and
config follow the InfoMask. The agent counts the values highest_acked_num
(DataReader) and stream_seq_num and sample_seq_num (DataWriter) itself; the
specification does not define them, not measured against another agent.
§8.3.5.7 Failure in INFO
Spec: §8.3.5.7.2, p. 68 — “If the operation fails the ResultStatus within the BaseObjectReply shall be set to the StatusValue that corresponds to the type of error encountered.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_get_info, answer_info);
crates/xrce-agent/src/daemon/discovery.rs (build_info_reply)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_a_missing_object_is_an_info_with_unknown_reference,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_without_an_info_mask_is_invalid_data,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_and_delete_without_permission_are_denied,
crates/xrce-agent/src/daemon/discovery.rs::tests::a_get_info_without_a_mask_is_answered_with_an_error_info
Status: done — Commits ca0cf7e08bf. a failure of GET_INFO (UNKNOWN_REFERENCE,
INVALID_DATA, DENIED) is sent as an INFO carrying the status, not as a STATUS.
§8.3.5.7 request_id and object_id of the GET_INFO
Spec: §8.3.5.7.2, p. 68 — “The request_id and object_id within the BaseObjectReply shall match the identically named fields in the BaseObjectRequest of the corresponding GET_INFO message.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_get_info: InfoRequest::base, answer_info);
crates/xrce-agent/src/daemon/discovery.rs (build_info_reply)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_the_agent_in_a_session_returns_activity_and_representation,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_a_missing_object_is_an_info_with_unknown_reference,
crates/xrce-agent/src/daemon/session.rs::tests::any_object_id_of_kind_agent_is_the_root_in_a_session,
crates/xrce-agent/src/daemon/discovery.rs::tests::any_object_id_of_kind_agent_is_the_root
Status: done — Commits ca0cf7e08bf. the tests check request_id and object_id
in the INFO, also for an object_id of kind OBJK_AGENT other than 0xFFFD.
§8.3.5.8 WRITE_DATA from the client
Spec: §8.3.5.8, p. 68 — “The WRITE_DATA submessage is used by the XRCE Client to write data using an XRCE DataWriter object within the XRCE Agent.”
Repo: crates/xrce-client/src/lib.rs (XrceClient::request_write,
XrceClient::request_write_sample); crates/xrce/src/submessages/write_data.rs
Tests: crates/xrce/src/submessages/write_data.rs::tests::write_data_matches_the_annex_b_example,
crates/endpoint-e2e/tests/xrce_write_framing.rs::rust_endpoint_frames_conformant_write_data
Status: done — xrce_write_framing.rs checks the frames of the endpoint
SDKs of further languages against the same decoder.
§8.3.5.8 Reception calls write, STATUS in response
Spec: §8.3.5.8, p. 68 — “Reception of this submessage shall result in the XRCE Agent calling the write operation on an XRCE DataWriter object (see 7.8.4.1). The XRCE Agent shall respond with a STATUS submessage.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_write_data)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_successful_write_is_answered_with_status_ok,
crates/xrce-agent/tests/e2e_udp_loopback.rs::e2e_udp_loopback_keyed_dispose_reliable_besteffort_and_fragments
Status: done — Commits 869304e6b63. write is called; a write without error is
answered with STATUS_OK, a failure with its status. The reply follows the text
of §8.3.5.8; the capture of the eProsima agent shows no reply to WRITE_DATA,
there is no setting for it.
§8.3.5.8 DataWriter from object_id, data from the payload
Spec: §8.3.5.8, p. 68 — “The data parameter to the write operation shall be obtained from the payload. The related XRCE DataWriter is identified by the object_id field in the payload. Upon reception of this message the XRCE Agent shall located the XRCE DataWriter identified by the object_id and use it to write the data to the DDS domain.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_write_data, dds_write_and_report)
Tests: crates/xrce-agent/tests/e2e_udp_loopback.rs::e2e_udp_loopback_keyed_dispose_reliable_besteffort_and_fragments,
crates/xrce-agent/src/daemon/session.rs::tests::a_client_writes_through_a_preconfigured_data_writer_without_a_create
Status: done
§8.3.5.8 Flags: endianness and DataFormat in bits 1 to 3
Spec: §8.3.5.8.1, p. 68 — “The WRITE_DATA sub-message uses the lowest order 4 bits of the flags: Bit 0 indicates the ‘Endianness’ […]. Bits 1, 2, and 3 shall be set to indicate the DataFormat used for the payload.”
Repo: crates/xrce/src/submessages/write_data.rs
(DataFormat::to_flag_bits, DataFormat::from_flag_bits, DataFormat::FORMAT_MASK)
Tests: crates/xrce/src/submessages/write_data.rs::tests::write_data_sample_flags_carry_format_sample,
crates/xrce/src/submessages/write_data.rs::tests::write_data_rejects_reserved_format
Status: done
§8.3.5.8 Table 11 flag values
Spec: §8.3.5.8.1, Table 11, p. 68–69 — FORMAT_DATA 0x0/0x1, FORMAT_SAMPLE 0x2/0x3, FORMAT_DATA_SEQ 0x8/0x9, FORMAT_SAMPLE_SEQ 0xA/0xB, FORMAT_PACKED_SAMPLES 0xE/0xF; example 0x09 for FORMAT_DATA_SEQ little-endian.
Repo: crates/xrce/src/submessages/write_data.rs (DataFormat)
Tests: crates/xrce/src/submessages/write_data.rs::tests::write_data_flags_are_e_le_and_format_data,
crates/xrce/src/submessages/write_data.rs::tests::data_format_raw_roundtrip,
crates/xrce/src/submessages/write_data.rs::tests::any_write_data_dispatches_every_format
Status: done
§8.3.5.8 Table 12 payload per DataFormat
Spec: §8.3.5.8.2, Table 12, p. 69–70 — WRITE_DATA_Payload_Data,
_Sample, _DataSeq, _SampleSeq, _PackedSamples; “All the WRITE_DATA
payload representations extend BaseObjectRequest”.
Repo: crates/xrce/src/submessages/write_data.rs (WriteDataPayload,
WriteDataPayloadSample, WriteDataPayloadDataSeq, WriteDataPayloadSampleSeq,
WriteDataPayloadPackedSamples);
crates/xrce-agent/src/daemon/session.rs (split_write_items)
Tests: crates/xrce/src/submessages/write_data.rs::tests::write_data_base_object_request_precedes_the_sample,
crates/xrce/src/submessages/write_data.rs::tests::write_data_sample_seq_matches_annex_b_5_4_layout,
crates/xrce/src/submessages/write_data.rs::tests::write_data_packed_samples_matches_annex_b_5_5_layout,
crates/xrce-agent/src/daemon/session.rs::tests::a_data_seq_is_split_by_the_type_and_written_sample_by_sample,
crates/xrce-agent/src/daemon/session.rs::tests::a_sample_seq_carries_state_and_time_per_sample,
crates/xrce-agent/src/daemon/session.rs::tests::packed_samples_resolve_their_deltas_against_the_base,
crates/xrce-agent/src/daemon/session.rs::tests::a_sequence_that_does_not_split_writes_nothing,
crates/xrce-agent/src/daemon/session.rs::tests::a_sequence_of_a_topic_of_unknown_type_is_refused
Status: done — Commits f40bd568ad1. codec and processing in the agent: the
samples of the three sequence formats are told apart by the topic’s type and
written one by one, with a SampleInfo each. For a topic of unknown type a
sequence cannot be split and is answered with STATUS_ERR_INVALID_DATA, nothing
is written. Assumption, not measured against another agent: the samples sit back
to back with no padding, each from alignment origin 0 (Annex B.5.2 shows 4-octet
elements only).
§8.3.5.9 READ_DATA from the client
Spec: §8.3.5.9, p. 70 — “The READ_DATA submessage is used by the XRCE Client to initiate a reception (read) of data from an XRCE DataReader object within the XRCE Agent.”
Repo: crates/xrce-client/src/lib.rs (XrceClient::request_read)
Tests: crates/xrce-agent/tests/endpoint_client_fixtures.rs::read_data_fixture_decodes_into_a_real_read_specification
Status: done
§8.3.5.9 Reception calls read, DATA or STATUS
Spec: §8.3.5.9, p. 70 — “Reception of this submessage shall result in the XRCE Agent calling the read operation on an XRCE DataReader object (see 7.8.5.1) one or more times. Depending on the returnStatus, the XRCE Agent may respond with a DATA submessages or a STATUS submessage. The read_specification parameters to the read operation shall be obtained from the payload.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_read_data, pump_read)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::read_data_elapsed_time_is_measured_from_the_real_request_time,
crates/xrce-agent/src/daemon/session.rs::tests::read_data_with_an_unhonorable_content_filter_is_rejected_not_silently_unfiltered
Status: done
§8.3.5.9 One or more DATA, DataReader from object_id
Spec: §8.3.5.9, p. 70 — “The XRCE Agent shall send one or more DATA submessages in response to this message, see 8.3.5.10. The related XRCE DataReader is identified by the object_id field in the payload.”
Repo: crates/xrce-agent/src/daemon/session.rs (pump_read)
Tests: crates/xrce-agent/tests/e2e_udp_loopback.rs::e2e_udp_loopback_keyed_dispose_reliable_besteffort_and_fragments
Status: done
§8.3.5.9 DATA until the end criterion
Spec: §8.3.5.9, p. 70 — “After reception of this message, the XRCE Agent shall continue to send DATA submessages to the client until either the ‘end criteria’ specified in the payload read_specification and continuous_read_options attained”.
Repo: crates/xrce/src/continuous_read.rs (ReadStream);
crates/xrce-agent/src/daemon/session.rs (tick, pump_read)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::read_data_elapsed_time_is_measured_from_the_real_request_time,
crates/xrce/src/continuous_read.rs::tests::max_samples_cap_enforced
Status: done — Commits 8bcb1d00161. continuous_read_options does not exist in
the IDL; its counterpart is delivery_control (item “Reading without and with
continuous_read_options” below).
§8.3.5.9 A new READ_DATA for the same object_id
Spec: §8.3.5.9, p. 70 — “[…] or else a new READ_DATA message for the same object_id is received from the XRCE Client.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_read_data: self.reads.insert)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_new_read_data_replaces_the_active_read
Status: done — the new read replaces the active one; DATA then carries only the
request_id of the new one.
§8.3.5.9 Control of the delivery time
Spec: §8.3.5.9, p. 71 — “The read operation also allows an XRCE Client to control when data may be sent by the XRCE Agent so that the Agent does not unnecessarily wake up the Client during its sleep cycle.”
Repo: —
Tests: —
Status: n/a (informative) — purpose; the fields are in the items on
Table 9.
§8.3.5.9 Flags of READ_DATA
Spec: §8.3.5.9.1, p. 71 — no additional flags.
Repo: crates/xrce/src/submessages/read_data.rs
(ReadDataPayload::into_submessage, ReadDataPayload::into_submessage_with)
Tests: crates/xrce/src/submessages/read_data.rs::tests::read_data_minimal_roundtrip
Status: done
§8.3.5.9 Payload READ_DATA_Payload
Spec: §8.3.5.9.2, p. 71 — “struct READ_DATA_Payload : BaseObjectRequest { ReadSpecification read_specification; };”
Repo: crates/xrce/src/submessages/read_data.rs (ReadDataPayload,
ReadSpecification, DataDeliveryControl, DeliveryControlForm);
crates/xrce-client/src/lib.rs (XrceClient::set_delivery_control_form)
Tests: crates/xrce/src/submessages/read_data.rs::tests::read_data_base_object_request_precedes_the_spec,
crates/xrce/src/submessages/read_data.rs::tests::read_data_matches_the_captured_read_data_example,
crates/xrce/src/submessages/read_data.rs::tests::annex_b_4_2_read_data_with_filter_and_delivery_control,
crates/xrce/src/submessages/read_data.rs::tests::the_content_filter_is_a_string_with_a_nul_and_an_aligned_length,
crates/xrce/src/submessages/read_data.rs::tests::the_data_format_octet_has_the_values_of_annex_a
Status: done — Commits b589558e671. BaseObjectRequest and ReadSpecification
per Annex A (data_format 0x00/0x02/0x08/0x0A/0x0E, content_filter_expression
as an XCDR2 string, DataDeliveryControl with a DHEADER). The contradiction
between Annex B.4.2 (DHEADER) and the eProsima capture (no DHEADER) is a named
setting: XrceClient::set_delivery_control_form(DeliveryControlForm::Bare)
writes the form without a DHEADER; the agent reads both.
§8.3.5.9 Reading without and with continuous_read_options
Spec: §8.3.5.9.2, p. 71–72 — “If the continuous_read_options member is not present, then the Agent shall call the read operation just once. As a result the only data returned will be the one already in the DDS DataReader cache. If the continuous_read_options member is present, then the Agent shall call the read operation multiple times. The period of calling shall be no faster than the pace_period. […] The Agent shall stop calling the read operation once either max_total_samples have been returned, or else max_total_elapsed_time has elapsed.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_read_data);
crates/xrce/src/continuous_read.rs (ReadStream::once, ReadStream::new, ReadStream::pull_pending_samples)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_read_without_delivery_control_returns_the_cache_once,
crates/xrce/src/continuous_read.rs::tests::a_read_without_delivery_control_returns_the_cache_once,
crates/xrce-agent/src/daemon/session.rs::tests::next_sample_waits_for_one_sample,
crates/xrce/src/continuous_read.rs::tests::pacing_throttles_per_period,
crates/xrce/src/continuous_read.rs::tests::max_elapsed_time_finalizes,
crates/xrce/src/continuous_read.rs::tests::max_samples_cap_enforced
Status: done — Commits 8bcb1d00161. the IDL does not know
continuous_read_options, pace_period, max_total_samples and
max_total_elapsed_time; the code takes the presence of delivery_control as
the marker (max_samples, max_elapsed_time, min_pace_period). With
delivery_control it reads continuously; without, it reads once and returns
what is in the cache. The difference to Micro-XRCE-DDS 3.0.1
(DataReader::read, read from the source: the next sample without a time limit)
is the named setting read_without_delivery_control: once | next-sample
(default once).
§8.3.5.9 Reading without delivery_control reads the cache once
Spec: §8.3.5.9.2, p. 71–72 — as above.
Repo: crates/xrce/src/continuous_read.rs (ReadStream::pull_pending_samples);
crates/xrce-agent/src/daemon/session.rs (pump_read)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_read_without_delivery_control_returns_the_cache_once,
crates/xrce-agent/src/daemon/session.rs::tests::next_sample_waits_for_one_sample
Status: done — Commits 8bcb1d00161. without delivery_control the agent delivers
all samples in the cache and ends the read; it does not deliver a sample that
arrives later (default once). With read_without_delivery_control: next-sample it delivers the next sample that arrives.
§8.3.5.9 MIN_PACE_PERIOD_NONE
Spec: §8.3.5.9.2, p. 72 — “The member min_pace_period may take the special value MIN_PACE_PERIOD_NONE. This value shall indicate that there is no minimum time interval between samples.”
Repo: crates/xrce/src/continuous_read.rs (ReadStream::capacity,
ReadStream::pull_pending_samples: 0 without a minimum interval)
Tests: crates/xrce/src/continuous_read.rs::tests::max_samples_cap_enforced,
crates/xrce/src/continuous_read.rs::tests::rate_limit_partitions_samples_over_time,
crates/xrce/src/continuous_read.rs::tests::pacing_throttles_per_period
Status: done — the specification gives MIN_PACE_PERIOD_NONE no value;
the code takes 0.
§8.3.5.10 DATA on STATUS_OK, STATUS otherwise
Spec: §8.3.5.10, p. 72 — “The DATA submessage shall be sent by the XRCE Agent to the XRCE Client in response to a READ_DATA message when the read operation performed by the XRCE Agent returns STATUS_OK. If the read operation returns any other status the XRCE Agent shall send a STATUS message, not a DATA message.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_read_data,
pump_read)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::read_data_with_an_unhonorable_content_filter_is_rejected_not_silently_unfiltered,
crates/xrce-agent/tests/e2e_udp_loopback.rs::e2e_udp_loopback_keyed_dispose_reliable_besteffort_and_fragments,
crates/xrce-agent/src/daemon/session.rs::tests::a_sample_too_large_for_data_is_reported
Status: done
§8.3.5.10 Sequence of DATA until the end or cancellation
Spec: §8.3.5.10, p. 72 — “A single READ_DATA message may result on multiple, possible an open-ended sequence, of DATA submessages sent as a response by the XRCE Agent. The DATA messages will continue to be sent until the one of the terminating conditions on the READ_DATA operation is reached, or until it is explicitly cancelled.”
Repo: crates/xrce-agent/src/daemon/session.rs (tick, pump_read, handle_read_data)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::read_data_elapsed_time_is_measured_from_the_real_request_time,
crates/xrce-agent/src/daemon/session.rs::tests::max_samples_zero_cancels_the_active_read
Status: done — until the end condition or the cancellation with MAX_SAMPLES_ZERO.
§8.3.5.10 request_id and object_id of the READ_DATA
Spec: §8.3.5.10, p. 72 — “The request_id and object_id within the DATA payload shall match the namesake fields in the corresponding READ_DATA message.”
Repo: crates/xrce-agent/src/daemon/session.rs (pump_read: ActiveRead::request_id;
data_submessages: BaseObjectRequest)
Tests: crates/xrce-agent/tests/e2e_udp_loopback.rs::e2e_udp_loopback_keyed_dispose_reliable_besteffort_and_fragments,
crates/xrce/src/submessages/data.rs::tests::data_base_object_request_precedes_the_sample
Status: done
§8.3.5.10 Flags of DATA
Spec: §8.3.5.10.1, p. 72 — “The flags shall be interpreted the same way as the flags of the WRITE_DATA submessage.”
Repo: crates/xrce/src/submessages/data.rs (DataPayload::flags,
DataPayloadSample::flags, DataPayloadDataSeq::flags, DataPayloadSampleSeq::flags,
DataPayloadPackedSamples::flags)
Tests: crates/xrce/src/submessages/data.rs::tests::data_uses_id_9,
crates/xrce/src/submessages/data.rs::tests::data_sample_rejects_non_sample_format
Status: done
§8.3.5.10 DATA format as requested in READ_DATA
Spec: §8.3.5.10.2, p. 72 — “The format the payload shall match the one requested in the READ_DATA message having the matching request_id. It shall also match the DataFormat encoded in the flags”.
Repo: crates/xrce-agent/src/daemon/session.rs (handle_read_data: ActiveRead::format;
data_submessages)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_read_for_data_seq_is_answered_with_one_data_seq,
crates/xrce-agent/src/daemon/session.rs::tests::a_read_for_sample_is_answered_with_a_sample_each,
crates/xrce-agent/src/daemon/session.rs::tests::a_read_for_sample_seq_is_answered_with_one_sample_seq,
crates/xrce-agent/src/daemon/session.rs::tests::a_read_for_packed_samples_is_answered_with_one_packed_samples,
crates/xrce-agent/src/daemon/session.rs::tests::the_sequence_formats_split_at_the_size_of_a_submessage
Status: done — Commits fd5253ca805. the agent sends DATA in the data_format the
READ_DATA asks for (FORMAT_DATA, _SAMPLE, _DATA_SEQ, _SAMPLE_SEQ,
_PACKED_SAMPLES); the sequence formats split at the size of a submessage.
§8.3.5.10 Table 13 payload per DataFormat
Spec: §8.3.5.10.2, Table 13, p. 72–73 — DATA_Payload_Data, _Sample,
_DataSeq, _SampleSeq, _PackedSamples; “All the DATA payload
representations extend RelatedObjectRequest.”
Repo: crates/xrce/src/submessages/data.rs (DataPayload,
DataPayloadSample, DataPayloadDataSeq, DataPayloadSampleSeq,
DataPayloadPackedSamples, AnyData);
crates/xrce-agent/src/daemon/session.rs (data_submessages)
Tests: crates/xrce/src/submessages/data.rs::tests::any_data_dispatches_every_format,
crates/xrce/src/submessages/data.rs::tests::data_sample_seq_matches_annex_b_5_4_layout,
crates/xrce-agent/src/daemon/session.rs::tests::a_read_for_sample_seq_is_answered_with_one_sample_seq
Status: done — Commits fd5253ca805. codec and agent. In the list the closing
brace after DATA_Payload_Sample is missing (p. 73). The agent fills the
SampleInfo with what it knows: sequence_number counts the samples delivered,
session_time_offset is the time of delivery, state is 0 because
DdsPort::poll_samples hands over the payload bytes only (source time and
instance, view and sample state are not carried).
§8.3.5.11 ACKNACK for a protocol independent of the transport
Spec: §8.3.5.11, p. 74 — “The ACKNACK submessage is used to enable a transport independent reliability protocol to be implemented. If the transport used for a session is able to reliably send messages […] then these messages may not be required.”
Repo: —
Tests: —
Status: n/a (informative) — purpose; the code uses ACKNACK over TCP as
well.
§8.3.5.11 The agent sends ACKNACK only on HEARTBEAT
Spec: §8.3.5.11, p. 74 — “in general it is expected that it is the XRCE Client that initiates any synchronization, and therefore, the XRCE Agent will only send ACKNACK messages in response to HEARTBEAT messages.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_heartbeat;
no other place in the agent produces ACKNACK)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::out_of_order_reliable_messages_wait_for_the_gap_and_report_a_truthful_acknack
Status: done
§8.3.5.11 ACKNACK on STREAMID_NONE
Spec: §8.3.5.11, p. 74 — “The ACKNACK submessage does not belong to any stream, for this reason the MessageHeader shall have the streamId set to STREAM_ID_NONE”.
Repo: crates/xrce-agent/src/daemon/session.rs (handle_heartbeat); crates/xrce-client/src/lib.rs (handle_heartbeat)
Tests: crates/xrce-agent/tests/spec_items_session.rs::the_acknack_of_the_agent_is_on_streamid_none
Status: done — handle_heartbeat of the agent and XrceClient::handle_heartbeat set StreamId::NONE in the ACKNACK header, the payload names the stream (02c704651e4).
### §8.3.5.11 Flags of ACKNACK
Spec: §8.3.5.11.1, p. 74 — no additional flags.
Repo: crates/xrce/src/submessages/acknack.rs
(AckNackPayload::into_submessage)
Tests: crates/xrce/src/submessages/acknack.rs::tests::acknack_roundtrip_via_submessage
Status: done
§8.3.5.11 Payload ACKNACK_Payload
Spec: §8.3.5.11.2, p. 74 — “struct ACKNACK_Payload { short first_unacked_seq_num; octet[2] nack_bitmap; octet stream_id; };”
Repo: crates/xrce/src/submessages/acknack.rs (AckNackPayload,
ACKNACK_BODY_SIZE = 5 octets of the members; encode_body, decode_body)
Tests: crates/xrce/src/submessages/acknack.rs::tests::acknack_le_roundtrip,
crates/xrce/src/submessages/acknack.rs::tests::acknack_be_roundtrip,
crates/xrce/tests/unannotated_types.rs::the_default_is_appendable_with_a_dheader,
crates/xrce/tests/unannotated_types.rs::the_final_setting_writes_the_reference_implementations_octets,
crates/xrce/tests/unannotated_types.rs::both_forms_are_read_in_either_setting
Status: done — Commits 7f85e76debd. ACKNACK_Payload has no @extensibility in
Annex A and is APPENDABLE (DDS-XTypes 1.3 §7.3.1.2.1.8): by default a DHEADER (4
octets) and 5 octets of members; with unannotated_types: final it is 5 octets
as in the eProsima capture; both forms are read, in every SDK (6bb66e420b7,
82fa0a977e2). The text says short, Annex A unsigned short for
first_unacked_seq_num; both have 2 octets.
§8.3.5.11 first_unacked_seq_num
Spec: §8.3.5.11.2, p. 74 — “The first_unacked_seq_num shall indicate that all sequence numbers up to but not including it have been received.”
Repo: crates/xrce/src/reliable.rs (ReliableStreamState::pending_acknack:
expected_seq; ReliableStreamState::recv_acknack)
Tests: crates/xrce/src/reliable.rs::tests::pending_acknack_marks_missing_slots,
crates/xrce/src/reliable.rs::tests::recv_acknack_clears_acked_seqnrs
Status: done — the example below it says “up to and including 99” for the value 100.
§8.3.5.11 nack_bitmap
Spec: §8.3.5.11.2, p. 74 — “The nack_bitmap shall indicate missing sequence numbers, starting from first_unacked_seq_num. […] first_unacked_seq_num set to 100 and nack_bitmap set to 0x4009 […] would indicate that sequence numbers 100, 103, and 114 are missing.”
Repo: crates/xrce/src/reliable.rs (ReliableStreamState::pending_acknack,
ReliableStreamState::recv_acknack: u16::from_le_bytes(nack_bitmap));
crates/xrce-agent/src/daemon/session.rs (handle_acknack);
crates/xrce-client/src/lib.rs (XrceClient::handle_acknack)
Tests: crates/xrce/src/reliable.rs::tests::end_to_end_sender_receiver_with_loss_recovery,
crates/xrce-agent/src/daemon/session.rs::tests::acknack_nack_triggers_retransmission_of_the_exact_buffered_bytes
Status: done — bit i stands for first_unacked_seq_num + i,
nack_bitmap[0] for bits 0 to 7. The specification does not fix which octet
of octet[2] carries the low bits; every ACKNACK in the eProsima capture has
nack_bitmap = 0x0000 (counted with a script over the file), so the order
cannot be checked against it.
§8.3.5.11 stream_id of the ACKNACK
Spec: §8.3.5.11.2, p. 74 — “The stream_id indicates the stream to which the ACKNACK is directed.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_acknack:
self.reliable.get_mut(&(client, ack.stream_id)))
Tests: crates/xrce-agent/src/daemon/session.rs::tests::acknack_nack_triggers_retransmission_of_the_exact_buffered_bytes
Status: done
§8.3.5.12 HEARTBEAT for a protocol independent of the transport
Spec: §8.3.5.12, p. 74 — “The HEARTBEAT submessage is used to enable a transport independent reliability protocol to be implemented. […] If a session transport is able to reliably send messages […] then these messages may not be required.”
Repo: —
Tests: —
Status: n/a (informative) — purpose.
§8.3.5.12 HEARTBEAT only for an active client
Spec: §8.3.5.12, p. 74 — “This specification does not dictate the timing of HEARTBEAT messages. However, in general it is expected that it is the XRCE Agent will only send HEARTBEAT messages when it has some indication that the XRCE Client is active and not in a sleep cycle.”
Repo: —
Tests: —
Status: open — an expectation the product can fulfil. crates/xrce/src/reliable.rs sends HEARTBEAT in tick every DEFAULT_HEARTBEAT_PERIOD (500 ms) while unacknowledged messages exist and the session has not expired, without regard to a sleep phase of the client.
§8.3.5.12 HEARTBEAT on STREAMID_NONE
Spec: §8.3.5.12, p. 74 — “The HEARTBEAT submessage does not belong to any stream, for this reason the MessageHeader shall have the stream_id set to STREAM_ID_NONE”.
Repo: crates/xrce-agent/src/daemon/session.rs (tick);
crates/xrce-client/src/lib.rs (XrceClient::tick)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_heartbeat_of_the_agent_is_on_streamid_none,
crates/xrce-client/src/lib.rs::tests::a_heartbeat_of_the_client_is_on_streamid_none
Status: done — the header of HEARTBEAT carries STREAMID_NONE, the payload the stream it reports.
§8.3.5.12 Flags of HEARTBEAT
Spec: §8.3.5.12.1, p. 74 — no additional flags.
Repo: crates/xrce/src/submessages/heartbeat.rs
(HeartbeatPayload::into_submessage)
Tests: crates/xrce/src/submessages/heartbeat.rs::tests::heartbeat_roundtrip_via_submessage
Status: done
§8.3.5.12 Payload HEARTBEAT_Payload
Spec: §8.3.5.12.2, p. 75 — “struct HEARTBEAT_Payload { short first_unacked_seq_nr; short last_unacked_seq_nr; octet stream_id; };”
Repo: crates/xrce/src/submessages/heartbeat.rs (HeartbeatPayload,
HEARTBEAT_BODY_SIZE = 5)
Tests: crates/xrce/src/submessages/heartbeat.rs::tests::heartbeat_le_roundtrip,
crates/xrce/src/submessages/heartbeat.rs::tests::heartbeat_be_roundtrip
Status: done — Annex A has @extensibility(FINAL): 5 octets without a
DHEADER. Annex A names the members first_unacked_seq_num and
last_unacked_seq_num (unsigned short), the text first_unacked_seq_nr and
last_unacked_seq_nr (short); the code uses _nr and i16, both have 2
octets.
§8.3.5.12 first_unacked_seq_nr and last_unacked_seq_nr
Spec: §8.3.5.12.2, p. 75 — “The first_unacked_seq_nr indicates the first available message sequence number on the sending side. The last_unacked_seq_nr indicates the first available message sequence number on the sending side.”
Repo: crates/xrce/src/reliable.rs (ReliableStreamState::pending_heartbeat:
window_base and the highest open seq)
Tests: crates/xrce/src/reliable.rs::tests::pending_heartbeat_fires_first_time,
crates/xrce/src/reliable.rs::tests::heartbeat_window_end_with_hole_is_serial_max_not_count
Status: done — the sentence on last_unacked_seq_nr repeats the one on
first_unacked_seq_nr; the code sets the last open number.
§8.3.5.12 stream_id of the HEARTBEAT
Spec: §8.3.5.12.2, p. 75 — “The stream_id indicates the stream to which the HEARTBEAT is directed.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_heartbeat:
state per hb.stream_id)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::out_of_order_reliable_messages_wait_for_the_gap_and_report_a_truthful_acknack
Status: done
§8.3.5.13 RESET resets the session state
Spec: §8.3.5.13, p. 75 — “The RESET submessage shall be used to reset and re-establish a session. It contains no payload. It shall cause the XRCE Agent to reset all state associated with the session_id indicated in the submessage header.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_reset);
crates/xrce/src/reliable.rs (ReliableStreamState::reset)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::reset_clears_reads_backlog_best_effort_counters_and_every_reliable_stream,
crates/xrce/src/reliable.rs::tests::reset_clears_state_completely
Status: done — Commits d4aad7c50b6. RESET resets all reliable streams (stream 255
included), the reassembly of FRAGMENT, the running reads, the backlog waiting
for room in a sender window and the sequence counters of the best-effort
streams, in and out. The objects of the ProxyClient and its session_id stay;
the specification does not say whether “all state” includes them.
§8.3.5.13 Running reads and counters after RESET
Spec: §8.3.5.13, p. 75 — as above.
Repo: crates/xrce-agent/src/daemon/session.rs (handle_reset)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::reset_clears_reads_backlog_best_effort_counters_and_every_reliable_stream
Status: done — Commits d4aad7c50b6. handle_reset ends running READ_DATA,
empties the backlog and resets the counters of the best-effort streams; the test
sends RESET through the session.
§8.3.5.13 Flags and empty payload of RESET
Spec: §8.3.5.13.1–§8.3.5.13.2, p. 75 — no additional flags; “The RESET submessage shall have an empty payload.”
Repo: crates/xrce/src/submessages/reset.rs (ResetPayload)
Tests: crates/xrce/src/submessages/reset.rs::tests::reset_roundtrip_empty_body,
crates/xrce/src/submessages/reset.rs::tests::reset_rejects_nonempty_body
Status: done
§8.3.5.14 FRAGMENT for submessages above the MTU
Spec: §8.3.5.14, p. 75 — “The FRAGMENT submessage is used to enable sending of other submessages whose length exceeds the transport MTU.”
Repo: crates/xrce-agent/src/daemon/session.rs (emit_possibly_fragmented);
crates/xrce-client/src/lib.rs (XrceClient::send_maybe_fragmented)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_sample_above_the_clients_mtu_on_a_reliable_stream_splits_into_fragments,
crates/xrce-client/src/lib.rs::tests::write_above_mtu_splits_into_fragments,
crates/xrce-agent/src/daemon/session.rs::tests::a_fragment_run_without_a_submessage_is_answered_invalid_data
Status: done — the MTU comes from the field requested_mtu that eProsima
appends; if it is missing, 508 octets apply. FRAGMENT only on reliable streams
(§8.3.5.14): on a best-effort stream the agent sends a too large submessage
whole and reports SessionEvent::ReliableSendOverflowed. A run without a
submessage is refused (622d2496da0).
§8.3.5.14 FRAGMENT only on reliable streams
Spec: §8.3.5.14, p. 75 — “The FRAGMENT message shall only be sent within reliable streams.”
Repo: crates/xrce-agent/src/daemon/session.rs (emit_possibly_fragmented:
sent whole on best-effort streams); crates/xrce-client/src/lib.rs
(send_maybe_fragmented)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_sample_above_the_clients_mtu_on_a_reliable_stream_splits_into_fragments,
crates/xrce-client/src/lib.rs::tests::write_above_mtu_splits_into_fragments,
crates/xrce-agent/tests/e2e_udp_loopback.rs::e2e_udp_loopback_keyed_dispose_reliable_besteffort_and_fragments
Status: done — agent and client split only on reliable streams; a submessage
above the MTU goes out whole on a best-effort stream (event
ReliableSendOverflowed). On reception the code reassembles FRAGMENT on any
stream. The best-effort branch has no test of its own.
§8.3.5.14 Last Fragment bit
Spec: §8.3.5.14, p. 75 — “all FRAGMENT submessage except for the last shall have the ‘Last Fragment’ bit in the flags set to 0. The last FRAGMENT submessage shall have the ‘Last Fragment’ flag set 1.”
Repo: crates/xrce/src/submessages/fragment.rs (FRAGMENT_FLAG_LAST)
Tests: crates/xrce/src/submessages/fragment.rs::tests::fragment_roundtrip_carries_last_flag,
crates/xrce/src/submessages/fragment.rs::tests::fragment_intermediate_has_no_last_flag
Status: done
§8.3.5.14 Reassembly and interpretation as submessages
Spec: §8.3.5.14, p. 75 — “Upon reception of the last fragment submessage the Agent shall concatenate the payload bytes of all FRAGMENT messages for that Stream in the order of the stream sequence number without sequence number gaps. The concatenated payloads shall be interpreted as XRCE submessages as if they had been received following the HEADER that came with the last fragment.”
Repo: crates/xrce-agent/src/daemon/session.rs
(process_message_submessages); crates/xrce/src/fragment.rs
(FragmentAssembler::add_fragment); crates/xrce/src/submessages/mod.rs
(decode_submessages)
Tests:
crates/xrce-agent/src/daemon/session.rs::tests::multi_fragment_create_reassembles_correctly,
crates/xrce-agent/src/daemon/session.rs::tests::a_second_fragmented_message_reassembles_like_the_first,
crates/xrce-agent/src/daemon/session.rs::tests::a_fragmented_run_of_two_submessages_runs_both
Status: done — the bytes are concatenated in the order of the stream and processed under the header of the message with the last fragment, every submessage of the run (8e0bfe868aa).
§8.3.5.14 Every submessage of the reassembled run
Spec: §8.3.5.14, p. 75 — as above.
Repo: crates/xrce/src/submessages/mod.rs (decode_submessages);
crates/xrce-agent/src/daemon/session.rs (process_message_submessages);
crates/xrce-client/src/lib.rs (XrceClient, ClientEvent::FragmentDiscarded)
Tests: crates/xrce/src/submessages/mod.rs::tests::a_submessage_run_decodes_every_submessage_past_the_padding,
crates/xrce-agent/src/daemon/session.rs::tests::a_fragmented_run_of_two_submessages_runs_both,
crates/xrce-agent/src/daemon/session.rs::tests::a_fragment_run_without_a_submessage_is_answered_invalid_data,
crates/xrce-client/src/lib.rs::tests::a_fragment_run_without_a_submessage_is_reported
Status: done — agent and client take every submessage of the reassembled
run, at multiples of 4 (§8.3.3) (8e0bfe868aa). A run without a submessage, or
one that is no sequence of submessages, gives STATUS STATUS_ERR_INVALID_DATA
at the agent and ClientEvent::FragmentDiscarded at the client (622d2496da0).
§8.3.5.14 Flags of FRAGMENT
Spec: §8.3.5.14.1, p. 75 — “Bit 0 indicates the ‘Endianness’ […]. Bit 1, the ‘Last Fragment’ bit, indicates the last fragment in the sequence.”
Repo: crates/xrce/src/submessages/fragment.rs (FragmentPayload::flags)
Tests: crates/xrce/src/submessages/fragment.rs::tests::fragment_roundtrip_carries_last_flag
Status: done
§8.3.5.14 FRAGMENT payload in the buffer
Spec: §8.3.5.14.2, p. 75 — “The payload of the FRAGMENT submessage is opaque. The Agent shall cache the payload bytes of all FRAGMENT submessages for a Stream in the order of the stream sequence number until the last FRAGMENT submessage is received.”
Repo: crates/xrce/src/fragment.rs (FragmentAssembler);
crates/xrce-agent/src/daemon/session.rs (FragmentRun)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_tick_between_fragments_keeps_the_reassembly,
crates/xrce/src/fragment.rs::tests::out_of_order_reassembly
Status: done — an incomplete run is discarded after 10 s
(DEFAULT_GC_TTL) and reported as an event.
§8.3.5.15 Sending TIMESTAMP
Spec: §8.3.5.15, p. 76 — “The TIMESTAMP submessage is used to send timestamp information. […] The TIMESTAMP submessage does not belong to any stream, for this reason the MessageHeader shall have the streamId set to STREAM_ID_NONE”. §8.3.5.15.2: “The transmit_timestamp shall contain the timestamp of the sender of the message at the time the message is sent.”
Repo: crates/xrce-agent/src/daemon/session.rs
(SessionEngine::request_timestamp, tick with timestamp_interval,
handle_timestamp_reply); crates/xrce-client/src/lib.rs
(XrceClient::send_timestamp, send_timestamp_reply)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::the_agent_sends_a_timestamp_and_reads_the_reply,
crates/xrce-agent/src/daemon/session.rs::tests::tick_sends_a_timestamp_every_interval,
crates/xrce-client/src/lib.rs::tests::the_client_sends_and_reads_timestamps
Status: done — agent and client send TIMESTAMP on STREAMID_NONE with the
sender’s clock (b224ed97138). The agent sends unprompted at the interval of the
agent key timestamp_interval_secs; default 0 (none), since the eProsima
clients do not expect a TIMESTAMP. The client’s TIMESTAMP_REPLY gives the event
ClockSynchronised.
§8.3.5.15 Flags and payload TIMESTAMP_Payload
Spec: §8.3.5.15.1–§8.3.5.15.2, p. 76 — no additional flags; “struct TIMESTAMP_Payload { Time_t transmit_timestamp; };”
Repo: crates/xrce/src/submessages/timestamp.rs (TimestampPayload,
TimePoint, TimePoint::encode_into, TimePoint::decode_at)
Tests: crates/xrce/src/submessages/timestamp.rs::tests::timestamp_roundtrip_via_submessage,
crates/xrce/src/submessages/timestamp.rs::tests::time_t_roundtrip_be,
crates/xrce/src/submessages/timestamp.rs::tests::a_timestamp_body_has_the_dheader_of_an_appendable_time_t
Status: done — TIMESTAMP_Payload is @extensibility(FINAL); Time_t has
no annotation in Annex A and is APPENDABLE (body: DHEADER 8 and 8 octets). The 8
octets of the reference implementation are written by the setting
unannotated_types: final (Rust UnannotatedTypes::Final); both forms are read
(7f85e76debd, 220857a1e90).
§8.3.5.16 TIMESTAMP_REPLY as an answer
Spec: §8.3.5.16, p. 76 — “The TIMESTAMP_REPLY submessage is used to reply to a timestamp information message.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_timestamp)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::timestamp_reply_echoes_originate_and_uses_real_wall_clock,
crates/xrce-agent/src/daemon/session.rs::tests::the_agent_sends_a_timestamp_and_reads_the_reply,
crates/xrce-client/src/lib.rs::tests::the_client_sends_and_reads_timestamps
Status: done — the agent answers TIMESTAMP, the client answers the agent’s
TIMESTAMP (send_timestamp_reply).
§8.3.5.16 TIMESTAMP_REPLY on STREAMID_NONE
Spec: §8.3.5.16, p. 76 — “The TIMESTAMP_REPLY submessage does not belong to any stream, for this reason the MessageHeader shall have the streamId set to STREAM_ID_NONE”.
Repo: crates/xrce-agent/src/daemon/session.rs (handle_timestamp); crates/xrce-client/src/lib.rs (send_control)
Tests: crates/xrce-agent/tests/spec_items_session.rs::the_timestamp_reply_of_the_agent_is_on_streamid_none
Status: done — the code sets StreamId::NONE in the reply of the agent and of the client; the test checks the header of the agent’s TIMESTAMP_REPLY (02c704651e4).
### §8.3.5.16 Flags and payload TIMESTAMP_REPLY_Payload
Spec: §8.3.5.16.1–§8.3.5.16.2, p. 76 — no additional flags; “struct TIMESTAMP_REPLY_Payload { Time_t transmit_timestamp; Time_t receive_timestamp; Time_t originate_timestamp; };”
Repo: crates/xrce/src/submessages/timestamp_reply.rs
(TimestampReplyPayload)
Tests: crates/xrce/src/submessages/timestamp_reply.rs::tests::timestamp_reply_roundtrip_le,
crates/xrce/src/submessages/timestamp_reply.rs::tests::timestamp_reply_roundtrip_via_submessage,
crates/xrce/src/transport_udp.rs::tests::loopback_roundtrip_timestamp_reply
Status: done — TIMESTAMP_REPLY_Payload is @extensibility(FINAL) with
three Time_t, each APPENDABLE (DHEADER 8, 36 octets together); with
unannotated_types: final three times 8 octets; both forms are read
(7f85e76debd).
§8.3.5.16 Meaning of the three timestamps
Spec: §8.3.5.16.2, p. 76 — “The transmit_timestamp shall contain the timestamp of the sender of the TIMESTAMP_REPLY message at the time the message is sent. The originate_timestamp shall contain the transmit_timestamp of the related TIMESTAMP […]. The receive_timestamp the shall contain the timestamp at which the related TIMESTAMP message was received.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_timestamp,
wall_clock_now, handle_timestamp_reply)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::timestamp_reply_echoes_originate_and_uses_real_wall_clock,
crates/xrce-agent/src/daemon/session.rs::tests::the_agent_sends_a_timestamp_and_reads_the_reply
Status: done — originate_timestamp is the transmit_timestamp of the
TIMESTAMP; transmit_timestamp and receive_timestamp of the agent’s reply
come from one reading of the clock. From the four times of a client’s
TIMESTAMP_REPLY the agent computes offset and round trip.
§8.4 Interaction Model
§8.4.1 Typical flows, partly replaceable by configuration
Spec: §8.4.1, p. 77 — “This section describes typical message flows. […] some of the message flows are optional and may be replaced by out-of-band configuration of the XRCE Client and Agent.”
Repo: —
Tests: —
Status: n/a (informative) — description; the flows are in the following
items.
§8.4.2 Sending through a pre-configured DataWriter
Spec: §8.4.2, p. 77 — “The XRCE Agent has been pre-configured to create an XRCE Application containing a DomainParticipant, Publisher and DataWriter. The DataWriter pre-configured object_id is known to the XRCE Client. […] The reception of the CREATE_CLIENT triggers the creation or reuse of the corresponding XRCE objects. […] Subsequent WRITE_DATA messages reference the ObjectId of those DataWriters”. Figure 8: CREATE_CLIENT(reuse = 1), STATUS_AGENT, WRITE_DATA, DELETE.
Repo: crates/xrce-agent/src/daemon/session.rs (make_client_applications,
ensure_predefined); crates/xrce-agent/src/daemon/config.rs
(client_applications); crates/xrce/src/object_id.rs
(ObjectId::from_reference)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_client_writes_through_a_preconfigured_data_writer_without_a_create,
crates/xrce-agent/src/daemon/session.rs::tests::a_create_client_makes_the_objects_configured_for_the_client,
crates/xrce-agent/src/daemon/session.rs::tests::a_preconfigured_object_is_made_only_for_a_client_allowed_to_create_it,
crates/xrce-agent/src/daemon/config.rs::tests::client_applications_are_read,
crates/xrce/src/object_id.rs::tests::from_reference_matches_the_examples_of_the_spec
Status: done — WRITE_DATA on the ObjectId of a configured resource (MD5 of
the name, §9.3) makes the DomainParticipant with everything inside it for the
client; the AccessController (§7.4) applies. The text names an
application_object_id in CREATE_CLIENT and a flag reuse;
CLIENT_Representation (Annex A) and §8.3.5.1.1 have neither. The trigger is
the agent key client_applications: (ClientKey, Application or
DomainParticipant reference); CREATE_CLIENT makes the objects, a second
CREATE_CLIENT of the same session keeps using them (468aa0940da, 2ba972cd270).
§8.4.3 Receiving through a pre-configured DataReader
Spec: §8.4.3, p. 77–78 — “The XRCE Agent has been pre-configured to create an XRCE Application containing a DomainParticipant, Subscriber and DataReader. The DataReader pre-configured object_id is known to the XRCE Client. […] A subsequent READ messag e references the ObjectId of those DataReaders”. Figure 9: CREATE_CLIENT(reuse=1), STATUS_AGENT, READ_DATA, DATA, DELETE.
Repo: crates/xrce-agent/src/daemon/session.rs (handle_read_data,
ensure_predefined, make_client_applications)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_client_reads_through_a_preconfigured_data_reader_without_a_create,
crates/xrce-agent/src/daemon/session.rs::tests::a_create_client_makes_the_objects_configured_for_the_client
Status: done — READ_DATA on the ObjectId of the configured DataReader
makes it, DATA comes with the request_id of the READ_DATA. The same deviation
from the text (application_object_id, reuse) and the same agent key
client_applications: as in §8.4.2 (2ba972cd270).
§8.4.4 Discovery of an agent through GET_INFO
Spec: §8.4.4, p. 78–79 — “This flow is only required when the Client is not pre-configured with the TransportLocator of the XRCE Agent. It allows an XRCE Client to be configured to content one or more TransportLocators (which may include multicast addresses) in order to dynamically discover the presence and actual Address of the Agents.” Figure 10: GET_INFO(OBJECTID_AGENT, CLIENT_Representation), INFO(AGENT_Representation): STATUS_OK, INFO(): STATUS_ERR_INCOMPATIBLE, then CREATE_CLIENT and STATUS_AGENT.
Repo: crates/xrce-agent/src/daemon/discovery.rs
(run_discovery_responder, build_info_reply, bind_discovery_socket);
crates/xrce-agent/src/daemon/session.rs (client_info_status,
handle_get_info); crates/xrce/src/discovery.rs (MulticastDiscovery)
Tests: crates/xrce-agent/src/daemon/discovery.rs::tests::discovery_responder_answers_get_info_on_agent,
crates/xrce-agent/src/daemon/discovery.rs::tests::the_info_mask_selects_activity_and_configuration,
crates/xrce-agent/src/daemon/discovery.rs::tests::a_client_of_another_major_version_is_answered_incompatible,
crates/xrce-agent/src/daemon/discovery.rs::tests::the_discovery_group_is_the_one_given,
crates/xrce/src/discovery.rs::tests::loopback_send_recv_roundtrip
Status: done — the agent answers GET_INFO(OBJECTID_AGENT) on the discovery
port with INFO (AGENT_Representation and AGENT_ActivityInfo by the InfoMask),
with and without a session; the multicast address is configurable
(discovery.address:). Annex A’s GET_INFO_Payload has no field for the
CLIENT_Representation of Figure 10; Annex A is the default, Figure 10 is an
extension behind the InfoMask (GetInfoPayload::with_client_info, client:
AgentDiscovery::with_client_info) that an agent without it ignores
(fd2e9a5bcfd, ca0cf7e08bf).
§8.4.4 Discovery on the client side
Spec: §8.4.4, p. 78–79 — as above.
Repo: crates/xrce-client/src/discovery.rs (AgentDiscovery,
discover_over_udp, connect_over_tcp); crates/xrce-client/src/lib.rs
(XrceClient::request_agent_info)
Tests: crates/xrce-client/src/discovery.rs::tests::get_info_goes_to_the_candidates_every_period,
crates/xrce-client/src/discovery.rs::tests::a_suitable_answer_ends_the_search,
crates/xrce-client/src/discovery.rs::tests::answers_that_are_not_suitable_are_passed_over,
crates/xrce-client/src/discovery.rs::tests::the_search_over_udp_finds_the_agent_that_answers,
crates/xrce-client/src/discovery.rs::tests::the_search_over_tcp_connects_to_the_agent_that_accepts,
crates/xrce-client/src/lib.rs::tests::request_agent_info_works_before_the_session_and_sends_the_mask,
crates/xrce-client/src/lib.rs::tests::an_info_is_read_into_an_event
Status: done — the client sends GET_INFO to a list of addresses at a fixed period, evaluates the INFO and connects to the first agent that fits (UDP, TCP). The tests reach the agents by unicast on loopback; reception on a multicast group is not tested (fd2e9a5bcfd).
§8.4.4 INFO with STATUS_ERR_INCOMPATIBLE
Spec: §8.4.4, Figure 10, p. 79 — “INFO(): STATUS_ERR_INCOMPATIBLE”.
Repo: crates/xrce-agent/src/daemon/session.rs (client_info_status,
handle_get_info); crates/xrce-agent/src/daemon/discovery.rs
(build_info_reply)
Tests: crates/xrce-agent/src/daemon/discovery.rs::tests::a_client_of_another_major_version_is_answered_incompatible,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_the_agent_checks_the_version_in_client_info,
crates/xrce-client/src/discovery.rs::tests::client_info_names_the_version_and_hides_the_client_key
Status: done — if the GET_INFO carries a CLIENT_Representation of another
major version than the agent’s, the answer is an INFO with
STATUS_ERR_INCOMPATIBLE; an unreadable one gives STATUS_ERR_INVALID_DATA.
The client_info is the extension behind the InfoMask of the item above
(fd2e9a5bcfd).
§8.4.4 Selection among several agents
Spec: §8.4.4, p. 78 — “the XRCE Client may discover more than one XRCE Agent. In that case it may use the information received about the XRCE Agent configuration […] and the XRCE Agent activity […] to select the most appropriate XRCE Agent and even connect to more than one XRCE Agents.”
Repo: —
Tests: —
Status: n/a (informative) — permission for the client.
§8.4.5 Connecting with CREATE_CLIENT and STATUS_AGENT
Spec: §8.4.5, p. 79–80 — “An XRCE Client connects to an Agent using the CREATE_CLIENT message. The Agent responds with a STATUS_AGENT indicating whether the connection succeeded and the ClientProxy was created on behalf of the XRCE Client.”
Repo: crates/xrce-client/src/lib.rs (XrceClient::connect);
crates/xrce-agent/src/daemon/session.rs (handle_create_client,
agent_status_reply)
Tests: crates/xrce-client/src/lib.rs::tests::full_lifecycle_creates_unique_request_ids_and_real_submessages,
crates/xrce-agent/src/daemon/session.rs::tests::create_client_happy_path_registers_and_replies_ok
Status: done
§8.4.6 Creating a complete application
Spec: §8.4.6, p. 80 — “An XRCE Client uses the CREATE message to create an XRCE Application. The CREATE message carries a CREATE_Payload containing an ObjectVariant with ObjectKind set to OBJK_APPLICATION. The corresponding OBJK_APPLICATION_Representation may use the REPRESENTATION_BY_REFERENCE to refer to an Application pre-configured in the Agent or it may use the REPRESENTATION_AS_XML_STRING to fully describe the Application including any necessary Types, Qos, and DDS Entities.”
Repo: crates/xrce-agent/src/daemon/session.rs (plan_dds_create, branch
ObjectKind::Application); crates/xrce-agent/src/daemon/entity_repr.rs
(application_definition); crates/xrce-agent/src/daemon/definitions.rs
(SystemDefinitions::add_application_library)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::what_a_configuration_client_defines_is_referenced_by_another_client,
crates/xrce-agent/src/daemon/session.rs::tests::a_create_client_makes_the_objects_configured_for_the_client,
crates/xrce-agent/src/daemon/definitions.rs::tests::the_example_file_defines_the_objects_of_table_16
Status: done — CREATE(OBJK_APPLICATION) with an <application_library>
makes the DomainParticipants of the application with topics, publishers,
subscribers and endpoints; BY_REFERENCE names an application of the agent’s
definitions (9d5c64dc398, 2ba972cd270).
§8.4.7 Defining a QosProfile
Spec: §8.4.7, p. 80 — “An XRCE Client uses the CREATE message to define Qos Profile. The CREATE message carries a CREATE_Payload containing an ObjectVariant with ObjectKind set to OBJK_QOSPROFILE. The corresponding OBJK_QOSPROFILE_Representation may use the REPRESENTATION_AS_XML_STRING to fully describe the Qos Profile.” Other objects are later created with this profile.
Repo: crates/xrce-agent/src/daemon/session.rs (plan_dds_create, branch
ObjectKind::QosProfile, definition_to_register, rebuild_profiles);
crates/xrce-agent/src/daemon/entity_repr.rs (apply_qos_profile)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::type_and_qos_profile_xml_follow_their_clauses,
crates/xrce-agent/src/daemon/session.rs::tests::what_a_configuration_client_defines_is_referenced_by_another_client,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_qos_profile_reference_applies_the_profile
Status: done — the profile belongs to the agent’s definitions as long as the
object exists; a later CREATE names it as Library::Profile (qos_profile_ref,
base_name). In Figure 13 client and agent are swapped (9d5c64dc398).
§8.4.8 Defining types
Spec: §8.4.8, p. 81 — “An XRCE Client uses the CREATE message to create an XRCE Type. The CREATE message carries a CREATE_Payload containing an ObjectVariant with ObjectKind set to OBJK_TYPE. The corresponding OBJK_TYPE_Representation may use the REPRESENTATION_AS_XML_STRING to fully describe the DDS-XTYPES Type including any referenced types.”
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (types)
Tests: crates/xrce-agent/tests/spec_items_session.rs::a_type_by_reference_names_a_known_type_by_its_fully_qualified_name
Status: done — a type as <types> is compiled and known under its name; it may refer to types the agent already knows (item on §7.7.3.3.2 “Reference to known types”).
### §8.4.9 Creating a topic
Spec: §8.4.9, p. 81 — “An XRCE Client uses the CREATE message to create an XRCE Topic. The CREATE message carries a CREATE_Payload containing an ObjectVariant with ObjectKind set to OBJK_TOPIC. The corresponding OBJK_TOPIC_Representation may use the REPRESENTATION_IN_BINARY or the REPRESENTATION_AS_XML_STRING to fully define the Topic.”
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (topic,
topic_from_xml); crates/xrce-agent/src/daemon/session.rs (plan_dds_create)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_topic_gets_the_type_its_type_name_names,
crates/xrce-agent/tests/replay_foreign_session.rs::replay_creates_the_dds_entities_the_real_clients_describe,
crates/xrce-agent/src/daemon/session.rs::tests::a_topic_of_an_unknown_type_is_refused_when_the_agent_is_told_to
Status: done — the XML form in the first test, the binary form from the
eProsima capture in the second. A topic of a type the agent does not know gives
STATUS_ERR_UNKNOWN_REFERENCE (agent key unknown_topic_types: refuse,
default; forward creates it), third test (969c784c93b).
§8.4.10 Creating a DataWriter and writing
Spec: §8.4.10, p. 82 — “An XRCE Client uses the CREATE message to create an XRCE DataWriter. […] The corresponding DATAREADER_Representation may use the REPRESENTATION_IN_BINARY or the REPRESENTATION_AS_XML_STRING to fully define the DataWriter. Both these representations allow specification of the DataWriter Qos. The DATAREADER_Representation may also use the REPRESENTATION_BY_REFERENCE to refer to a DataWriter definition known to the Agent.” Figure 16: CREATE, STATUS, WRITE_DATA, DELETE_RESOURCE(DataWriter, Session).
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (endpoint,
endpoint_from_xml); crates/xrce-agent/src/daemon/session.rs
(plan_dds_create, format_is_allowed, handle_write_data, handle_delete)
Tests: crates/xrce-agent/tests/e2e_udp_loopback.rs::e2e_udp_loopback_keyed_dispose_reliable_besteffort_and_fragments,
crates/xrce-agent/tests/replay_foreign_session.rs::replay_creates_the_dds_entities_the_real_clients_describe,
crates/xrce-agent/src/daemon/session.rs::tests::references_resolve_against_the_profile_files,
crates/xrce-agent/src/daemon/session.rs::tests::the_formats_of_each_kind_are_enforced
Status: done — XML in the first test, the binary form in the second. Annex A
and §7.7.3.1 give the DataWriter only binary and XML; §8.4.10 also names
REPRESENTATION_BY_REFERENCE. Annex A is the default (the reference gives
STATUS_ERR_INVALID_DATA, fourth test); the agent key representation_formats: any admits the reference (third test) (0429eab4fb2, 23d8f50c712). The text
writes DATAREADER_Representation for the DataWriter; Figure 16 names
DELETE_RESOURCE, no such submessage exists (DELETE is meant).
§8.4.11 Creating a DataReader and reading
Spec: §8.4.11, p. 82–83 — “An XRCE Client uses the CREATE message to create an XRCE DataReader. […] The corresponding OBJK_DATAREADER_Representation may use the REPRESENTATION_IN_BINARY or the REPRESENTATION_AS_XML_STRING to fully define the DataReader. […] may also use the REPRESENTATION_BY_REFERENCE”. Figure 17: CREATE, STATUS, READ, DATA.
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (endpoint,
endpoint_from_xml); crates/xrce-agent/src/daemon/session.rs
(plan_dds_create, format_is_allowed, handle_read_data, pump_read)
Tests: crates/xrce-agent/tests/e2e_udp_loopback.rs::e2e_udp_loopback_keyed_dispose_reliable_besteffort_and_fragments,
crates/xrce-agent/tests/replay_foreign_session.rs::replay_creates_the_dds_entities_the_real_clients_describe,
crates/xrce-agent/src/daemon/session.rs::tests::references_resolve_against_the_profile_files,
crates/xrce-agent/src/daemon/session.rs::tests::the_formats_of_each_kind_are_enforced
Status: done — binary and XML as for the DataWriter; the reference to a
DataReader is not provided by Annex A and §7.7.3.1 and is admitted only with the
agent key representation_formats: any (third and fourth test) (0429eab4fb2).
The introduction says “to publish data” for the DataReader.
§8.4.12 Information on a resource
Spec: §8.4.12, p. 83 — “An XRCE Client may use this mechanism to determine the QoS of any of the DDS proxy entities that the XRCE Agent manages on behalf of the XRCE Client. It may also be used to read QoS profiles and type declarations that are known to the XRCE Agent. […] The XRCE Agent responds with an INFO message containing an ObjectVariant. The ObjectKind of the ObjectVariant is the appropriate for the specified ObjectId.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_get_info,
object_info, ensure_predefined)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_an_object_returns_the_object_variant_it_was_created_with,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_a_missing_object_is_an_info_with_unknown_reference,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_a_data_writer_reports_its_activity,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_a_data_reader_reports_its_activity
Status: done — GET_INFO on an object of the client gives an INFO with the
ObjectVariant it was created with (with its ObjectKind) and the activity of
a DataWriter or DataReader by the InfoMask (ca0cf7e08bf). GET_INFO on the
ObjectId of a QoS profile or type from the agent’s definitions makes the
object for the client (ensure_predefined, 2ba972cd270); this branch has no
test of its own.
§8.4.13 Updating a resource
Spec: §8.4.13, p. 84 — “An XRCE Client uses the CREATE message with the attribute reuse set to TRUE and the attribute replace set to TRUE to indicate it wants to update the Object identified by the ObjectId. […] The XRCE Agent updates the Object using the new configuration contained in the ObjectVarian t and responds with a STATUS message.”
Repo: crates/xrce/src/object_store.rs (ObjectStore::create,
CreateOutcome::Replaced); crates/xrce-agent/src/daemon/session.rs
(handle_create); crates/xrce-client/src/lib.rs (XrceClient::update_object)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_create_with_reuse_and_replace_updates_the_object,
crates/xrce-agent/src/daemon/session.rs::tests::the_update_of_a_missing_object_creates_it_or_is_refused,
crates/xrce-agent/src/daemon/session.rs::tests::a_replace_that_fails_returns_the_object_to_its_previous_configuration,
crates/xrce/src/object_store.rs::tests::create_reuse_and_replace_replaces_an_unequal_object,
crates/xrce-client/src/lib.rs::tests::update_object_sends_a_create_with_reuse_and_replace
Status: done — CREATE with reuse and replace replaces an unequal object
(Table 5); if the DDS side fails, the old configuration applies again. The
update of a missing object contradicts itself in the spec: §7.8.3.2 requires
STATUS_ERR_UNKNOWN_REFERENCE, Table 5 and §8.4.13 create it. The default is
Table 5; the agent key update_of_missing_object: refuse gives
STATUS_ERR_UNKNOWN_REFERENCE (3b066516f69, 70963ac46ec).
§8.4.14 Reliability per stream, only on reliable streams
Spec: §8.4.14, p. 84 — “Reliability is implemented separately for each Stream, and only for the reliable streams which are identified by the stream_id value being between 0x80 and 0xFF.”
Repo: crates/xrce/src/reliable.rs (ReliableStreamState::new);
crates/xrce-agent/src/daemon/session.rs (reliable per (client, stream),
handle_message)
Tests: crates/xrce/src/reliable.rs::tests::constructor_panics_on_best_effort_stream,
crates/xrce-agent/src/daemon/session.rs::tests::best_effort_messages_get_increasing_sequence_numbers
Status: done
§8.4.14 Two endpoints, each with its own state machine
Spec: §8.4.14, p. 84 — “A Stream has exactly two endpoints, the sending endpoint and the receiving endpoint. […] The sender and receiver endpoint on a Stream each execute its own protocol state machine.”
Repo: crates/xrce/src/reliable.rs (ReliableStreamState: sender
submit, pending_heartbeat, recv_acknack; receiver recv_data,
drain_in_order, pending_acknack)
Tests: crates/xrce/src/reliable.rs::tests::end_to_end_sender_receiver_with_loss_recovery
Status: done — both halves live in one state per stream; agent and client use one of them per direction.
§8.4.14 Serial number arithmetic
Spec: §8.4.14, p. 84 — “Sequence number arithmetic and comparisons shall use Serial Number Arithmetic as specified in clause 8.3.2.3 sequenceNr.”
Repo: crates/xrce/src/reliable.rs (serial_min_in_flight,
serial_max_in_flight); crates/xrce/src/serial_number.rs
Tests: crates/xrce/src/reliable.rs::tests::heartbeat_window_across_wrap_reports_rfc1982_order,
crates/xrce/src/reliable.rs::tests::acknack_retransmit_of_lost_sample_across_wrap
Status: done
§8.4.14.1 State of the sender
Spec: §8.4.14.1, p. 85 — “The sender maintains two state variables associated with the stream. The HighestSentSequenecNumber and the HighestAcknowledgedSequenceNumber. Each time a message is sent the HighestSentSequenecNumber is increased. The reception of ACKNACK messages updates the HiguestAcknowledgedSequenceNumber.” Figure 20: “receive(ACKNACK) /save HigestAcknowledgedSeqNumber repair SequenceNumber in NACK”.
Repo: crates/xrce/src/reliable.rs (submit, recv_acknack);
crates/xrce-agent/src/daemon/session.rs (handle_acknack)
Tests: crates/xrce/src/reliable.rs::tests::submit_assigns_monotonic_seqnrs,
crates/xrce/src/reliable.rs::tests::recv_acknack_clears_acked_seqnrs,
crates/xrce-agent/src/daemon/session.rs::tests::acknack_nack_triggers_retransmission_of_the_exact_buffered_bytes
Status: done — the sender keeps the open messages instead of two numbers;
window_base corresponds to the highest acknowledged number plus one.
§8.4.14.1 HEARTBEAT until full acknowledgement
Spec: §8.4.14.1, p. 85 — “While the HighestAcknowledgedSequenceNumber is less than the HighestSentSequenceNumber the sender sends HeartBeat messages that announce the HighestSentSequenecNumber to the receiver. These HeartBeat messages may be periodic or optimized using on vendor specific mechanism. The requirement is that they are sent at some rate until HighestAcknowledgedSequenceNumber matches the HighestSentSequenceNumber.”
Repo: crates/xrce/src/reliable.rs (pending_heartbeat,
DEFAULT_HEARTBEAT_PERIOD); crates/xrce-agent/src/daemon/session.rs
(tick); crates/xrce-client/src/lib.rs (XrceClient::tick)
Tests: crates/xrce/src/reliable.rs::tests::pending_heartbeat_fires_first_time,
crates/xrce/src/reliable.rs::tests::pending_heartbeat_silenced_until_period_elapsed,
crates/xrce/src/reliable.rs::tests::pending_heartbeat_none_when_window_empty
Status: done — every 500 ms. Figure 20 writes the transition to “Initial”
with HiguestReceivedSeqNumber, the text with the highest acknowledged
number.
§8.4.14.2 State of the receiver
Spec: §8.4.14.2, p. 85–86 — “The receiver maintains two state variables associated with the stream. The HighestReceivedSequenceNumber and the HighestAnnouncedSequenceNumber. Each time a Message is received the HighestReceivedSequenceNumber may be updated (assuming all previous messages have been received). […] Each time a HEARTBEAT is received the HighestAnnouncedSequenceNumber may be adjusted.”
Repo: crates/xrce/src/reliable.rs (recv_data, drain_in_order,
pending_acknack)
Tests: crates/xrce/src/reliable.rs::tests::recv_data_buffers_in_order,
crates/xrce/src/reliable.rs::tests::pending_acknack_marks_missing_slots
Status: done — the highest announced number is not stored; it enters the
ACKNACK on the HEARTBEAT as hint_last_seen.
§8.4.14.2 The client sends ACKNACK while messages are missing
Spec: §8.4.14.2, p. 86 — “If the receiver is a n XRCE Client, then while the HiguestReceivedSequenceNumber is less than the HighestAnnouncedSequenceNumber, the received sends ACKNACK messages to request the messages corresponding to the missing sequence numbers. These ACKNACK messages may be periodic or optimized using on vendor specific mechanism.”
Repo: crates/xrce-client/src/lib.rs (handle_heartbeat)
Tests: crates/xrce-client/src/lib.rs::tests::heartbeat_is_answered_with_acknack
Status: done — the client sends ACKNACK on every HEARTBEAT, not on a timer
of its own (Figure 21: NackPeriod); the agent sends HEARTBEAT every 500 ms
as long as messages are open.
§8.4.14.2 The agent sends ACKNACK only on HEARTBEAT
Spec: §8.4.14.2, p. 86 — “If the receiver is the XRCE Agent, then it only sends ACKNACK messages in response to receiving a HEARTBEAT.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_heartbeat)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::out_of_order_reliable_messages_wait_for_the_gap_and_report_a_truthful_acknack
Status: done — as in the item on §8.3.5.11.
§8.5 XRCE Object Operation Traceability
§8.5 Table 14 create_client
Spec: §8.5, Table 14, p. 86 — “XRCE Root / create_client / CREATE_CLIENT / STATUS_AGENT”.
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create_client,
agent_status_reply)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::create_client_happy_path_registers_and_replies_ok,
crates/xrce-agent/src/daemon/session.rs::tests::create_client_rejects_wrong_major_version,
crates/xrce-agent/src/daemon/session.rs::tests::a_wrong_cookie_is_answered_with_a_status_agent
Status: done — a wrong cookie is answered with STATUS_AGENT and
STATUS_ERR_INVALID_DATA (d7aec9c2d78). The caption of Table 14 reads
“Predefined XRCE Objects from parsing the Example XML configuration XML file”,
like that of Table 16.
§8.5 Table 14 get_info of the Root
Spec: §8.5, Table 14, p. 86 — “XRCE Root / get_info / GET_INFO / INFO”.
Repo: crates/xrce-agent/src/daemon/discovery.rs
(run_discovery_responder); crates/xrce-agent/src/daemon/session.rs
(handle_get_info)
Tests: crates/xrce-agent/src/daemon/discovery.rs::tests::discovery_responder_answers_get_info_on_agent,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_the_agent_in_a_session_returns_activity_and_representation,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_without_a_session_is_answered_for_the_agent_only,
crates/xrce-agent/src/daemon/transport.rs::tests::the_udp_listener_answers_get_info_before_a_session
Status: done
§8.5 Table 14 delete_client with STATUS_AGENT
Spec: §8.5, Table 14, p. 86 — “XRCE Root / delete_client / DELETE / STATUS_AGENT”.
Repo: crates/xrce-agent/src/daemon/session.rs (delete_client_reply); crates/xrce-agent/src/daemon/config.rs (delete_client_reply)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::delete_client_is_answered_with_status_unless_status_agent_is_named, crates/xrce-agent/src/daemon/config.rs::tests::the_reply_to_delete_client_can_be_set
Status: done — DELETE(OBJECTID_CLIENT) is answered with STATUS (§8.3.5.4; in the IDL of Annex A only STATUS carries a ResultStatus); the STATUS_AGENT of Table 14 is the setting delete_client_reply: status_agent. The client takes a STATUS_AGENT that arrives with no CREATE_CLIENT pending for the answer to its DELETE. 9aeb3465b72.
### §8.5 Table 14 create
Spec: §8.5, Table 14, p. 86 — “XRCE ProxyClient / create / CREATE (flags for creation) / STATUS”.
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create)
Tests: crates/xrce-agent/tests/replay_foreign_session.rs::replay_matches_the_real_agents_create_client_create_and_delete_replies
Status: done
§8.5 Table 14 update
Spec: §8.5, Table 14, p. 86 — “XRCE ProxyClient / update / CREATE (flags for reuse) / STATUS”.
Repo: crates/xrce/src/object_store.rs (ObjectStore::create);
crates/xrce-agent/src/daemon/session.rs (handle_create);
crates/xrce-client/src/lib.rs (XrceClient::update_object)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_create_with_reuse_and_replace_updates_the_object,
crates/xrce-client/src/lib.rs::tests::update_object_sends_a_create_with_reuse_and_replace,
crates/xrce/src/object_store.rs::tests::create_reuse_and_replace_replaces_an_unequal_object
Status: done — as in the item on §8.4.13, including the setting
update_of_missing_object. The table names only “flags for reuse”, §8.4.13 sets
reuse and replace; the update is a CREATE with both (3b066516f69).
§8.5 Table 14 get_info of the ProxyClient
Spec: §8.5, Table 14, p. 86 — “XRCE ProxyClient / get_info / GET_INFO / INFO”.
Repo: crates/xrce-agent/src/daemon/session.rs (handle_get_info,
object_info)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_an_object_returns_the_object_variant_it_was_created_with,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_a_missing_object_is_an_info_with_unknown_reference,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_a_data_writer_reports_its_activity
Status: done — GET_INFO on an object gives INFO, on an unknown ObjectId an
INFO with STATUS_ERR_UNKNOWN_REFERENCE, without permission STATUS_ERR_DENIED
(ca0cf7e08bf, d7338ca58f2).
§8.5 Table 14 delete
Spec: §8.5, Table 14, p. 86 — “XRCE ProxyClient / delete / DELETE / STATUS”.
Repo: crates/xrce-agent/src/daemon/session.rs (handle_delete)
Tests: crates/xrce-agent/tests/endpoint_client_fixtures.rs::delete_fixture_decodes_and_removes_the_object_create_added,
crates/xrce-agent/tests/replay_foreign_session.rs::replay_matches_the_real_agents_create_client_create_and_delete_replies
Status: done
§8.5 Table 14 write
Spec: §8.5, Table 14, p. 86 — “XRCE DataWriter / write / WRITE_DATA, FRAGMENT / STATUS”.
Repo: crates/xrce-agent/src/daemon/session.rs (handle_write_data,
process_message_submessages)
Tests: crates/xrce-agent/tests/e2e_udp_loopback.rs::e2e_udp_loopback_keyed_dispose_reliable_besteffort_and_fragments,
crates/xrce-agent/src/daemon/session.rs::tests::a_successful_write_is_answered_with_status_ok
Status: done — WRITE_DATA direct and in FRAGMENT; a successful WRITE_DATA
gives STATUS with STATUS_OK, a failure its error code (869304e6b63). The
eProsima agent does not answer a successful WRITE_DATA; this agent follows the
text of the spec.
§8.5 Table 14 read
Spec: §8.5, Table 14, p. 86 — “XRCE DataReader / read / READ_DATA / DATA, FRAGMENT, STATUS”.
Repo: crates/xrce-agent/src/daemon/session.rs (handle_read_data,
pump_read, emit_possibly_fragmented)
Tests: crates/xrce-agent/tests/e2e_udp_loopback.rs::e2e_udp_loopback_keyed_dispose_reliable_besteffort_and_fragments,
crates/xrce-agent/src/daemon/session.rs::tests::a_sample_above_the_clients_mtu_on_a_reliable_stream_splits_into_fragments,
crates/xrce-agent/src/daemon/session.rs::tests::read_data_with_an_unhonorable_content_filter_is_rejected_not_silently_unfiltered
Status: done
§9 XRCE Agent Configuration
§9.1 Prior knowledge of the agent for REPRESENTATION_BY_REFERENCE
Spec: §9.1, p. 87 — “The XRCE Agent may be configured such that it has a priori knowledge XRCE Objects. This allows XRCE Clients to reference and create XRCE Objects in a very compact manner using the representation format REPRESENTATION_BY_REFERENCE, see clause 7.7.3.3.1 REPRESENTATION_BY_REFERENCE format.”
Repo: —
Tests: —
Status: n/a (informative) — permission. The clause titled
“REPRESENTATION_BY_REFERENCE format” is §7.7.3.1.1; §7.7.3.3.1 belongs to XRCE
Type.
§9.1 Two standard mechanisms, others allowed
Spec: §9.1, p. 87 — “This specification provides two standard mechanism s to configure the XRCE Agent. Implementations may also provide additional mechanisms: Remote configuration using the XRCE Protocol; Local file-based configuration”.
Repo: —
Tests: —
Status: n/a (informative) — overview; the two mechanisms are in the
items on §9.2 and §9.3. The profile files in the Fast DDS format
(xml_profile_files:) are an additional mechanism.
§9.2 ConfigurationClient with the ordinary protocol
Spec: §9.2, p. 87 — “An application may use a n XRCE Client with the only purpose of defining and creating XRCE Objects that are intended for other applications. […] The protocol used by the XRCE ConfigurationClient is the same used by any other XRCE Client. The only difference is that an XRCE ConfigurationClient never uses the READ_DATA or WRITE messages.”
Repo: —
Tests: —
Status: n/a (informative) — description of a role of the client; it
needs no message of its own.
§9.2 Objects of the ConfigurationClient for other clients
Spec: §9.2, p. 87–88 — “Any other XRCE Client can reference XRCE Objects created by an XRCE ConfigurationClient.” Figure 22: the ConfigurationClient creates with CREATE, another client with CREATE(REPRESENTATION_BY_REFERENCE) and reads with READ_DATA. “These XRCE Objects are later referenced by a different XRCE Client using the representation formats REPRESENTATION_BY_REFERENCE.”
Repo: crates/xrce-agent/src/daemon/definitions.rs (SystemDefinitions);
crates/xrce-agent/src/daemon/session.rs (definition_to_register,
rebuild_profiles, ensure_predefined);
crates/xrce-agent/src/daemon/profiles.rs (AgentProfiles::predefined_objects)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::what_a_configuration_client_defines_is_referenced_by_another_client,
crates/xrce-agent/src/daemon/session.rs::tests::a_client_writes_through_a_preconfigured_data_writer_without_a_create
Status: done — a ConfigurationClient creates QosProfile, Application and
DomainParticipant with CREATE (XML); another client creates them with
REPRESENTATION_BY_REFERENCE as long as the ConfigurationClient’s object exists
(the test covers QosProfile and Application). Type and DomainParticipant take
the same path (definition_to_register), without a test of their own. A Domain
has no ObjectKind (§7.7.5, Annex A) and comes from the files. Figure 22 calls
the answer to CREATE_CLIENT STATUS_CLIENT; the submessage is called
STATUS_AGENT (9d5c64dc398, 2ba972cd270).
§9.2 Another network or another transport
Spec: §9.2, p. 87 — “Note that the XRCE ConfigurationClient may be communicating with the Agent using a different network or transport, which may not have the same constraints as a typical XRCE Client.”
Repo: —
Tests: —
Status: n/a (informative) — note.
§9.3 Loading an XML file according to dds-xml_system_example.xsd
Spec: §9.3, p. 88 — “The XRCE Agent shall provide a configuration or run-time option to load a n XML file formatted according to the schema defined in the [DDS-XML] machine-readable file dds-xml_system_example.xsd.”
Repo: crates/xrce-agent/src/daemon/config.rs (xml_profile_files,
qos_library_files); crates/xrce-agent/src/daemon/profiles.rs
(AgentProfiles::load, AgentProfiles::add_profiles);
crates/xrce-agent/src/daemon/definitions.rs
(SystemDefinitions::add_document)
Tests: crates/xrce-agent/src/daemon/profiles.rs::tests::types_and_qos_libraries_in_a_dds_document_are_read,
crates/xrce-agent/src/daemon/profiles.rs::tests::the_example_file_of_the_spec_defines_the_objects_of_table_16
Status: done — xml_profile_files: takes a document with the root <dds>
(or a library as the root) and reads <types>, <qos_library>,
<domain_library>, <domain_participant_library> and <application_library>
(452ffeb7f84, 9d5c64dc398). The schema file is not in the cache; checked against
§9.3.1.
§9.3 Domain, Application and DomainParticipant libraries of the configuration file
Spec: §9.3, p. 88 — as above.
Repo: crates/xrce-agent/src/daemon/profiles.rs
(AgentProfiles::add_profiles); crates/xrce-agent/src/daemon/definitions.rs
(add_domain_library, add_participant_library, add_application_library)
Tests: crates/xrce-agent/src/daemon/definitions.rs::tests::a_participant_library_and_inheritance,
crates/xrce-agent/src/daemon/definitions.rs::tests::the_example_file_defines_the_objects_of_table_16,
crates/xrce-agent/src/daemon/profiles.rs::tests::a_library_can_be_the_root_and_a_clash_of_ids_is_refused
Status: done — the three libraries are read, also as the root of the
document, with base_name inheritance. Other elements of <dds> appear only in
the start-up log (AgentProfiles::unused) (452ffeb7f84, 9d5c64dc398).
§9.3 One XRCE object per element, for all clients by reference
Spec: §9.3, p. 88 — “The XRCE Agent shall parse the XML file and for each of the elements defined in Table 15, it shall construct the corresponding XRCE Object specified in Table 15. All the created XRCE Objects shall be made available to XRCE clients such that they may refer to them using the representation format REPRESENTATION_BY_REFERENCE.”
Repo: crates/xrce-agent/src/daemon/profiles.rs
(AgentProfiles::predefined_objects); crates/xrce-agent/src/daemon/session.rs
(ensure_predefined, predefined_index); crates/xrce/src/object_id.rs
(ObjectId::from_reference)
Tests: crates/xrce-agent/src/daemon/profiles.rs::tests::the_example_file_of_the_spec_defines_the_objects_of_table_16,
crates/xrce-agent/src/daemon/profiles.rs::tests::a_library_can_be_the_root_and_a_clash_of_ids_is_refused,
crates/xrce-agent/src/daemon/session.rs::tests::a_client_writes_through_a_preconfigured_data_writer_without_a_create,
crates/xrce/src/object_id.rs::tests::from_reference_matches_the_examples_of_the_spec
Status: done — the agent knows every element of Table 15 as an object with
the ObjectId from the MD5 of the reference (§9.3, Table 16); every client gets
it with CREATE and REPRESENTATION_BY_REFERENCE or on first access to the
ObjectId. Two top-level objects with the same ObjectId are refused when the
file is loaded (468aa0940da, 2ba972cd270).
§9.3 Table 15
Spec: §9.3, Table 15, p. 88 — “
Repo: crates/xrce-agent/src/daemon/profiles.rs (add_types,
AgentProfiles::resolve_type_ref);
crates/xrce-agent/src/daemon/entity_repr.rs (types);
crates/xrce-agent/src/daemon/session.rs (plan_dds_create, branch
ObjectKind::Type)
Tests: crates/xrce-agent/src/daemon/profiles.rs::tests::types_and_qos_libraries_in_a_dds_document_are_read,
crates/xrce-agent/src/daemon/profiles.rs::tests::the_example_file_of_the_spec_defines_the_objects_of_table_16,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::an_xml_type_library_compiles_to_named_complete_types,
crates/xrce-agent/src/daemon/session.rs::tests::a_configured_type_is_known_to_every_client
Status: done — the types are known to all clients under their fully
qualified name with modules (ShapesDemoTypes::ShapeType); a topic finds them
through type_name. CREATE with OBJK_TYPE and REPRESENTATION_BY_REFERENCE
accepts a known name (plan_dds_create, without a test of its own). References
of a <types> to other known types: item on §7.7.3.3.2 (452ffeb7f84,
9d5c64dc398).
§9.3 Table 15
Spec: §9.3, Table 15, p. 88 — “
Repo: crates/xrce-agent/src/daemon/profiles.rs
(AgentProfiles::qos_profile, AgentProfiles::predefined_objects);
crates/xrce-agent/src/daemon/entity_repr.rs (apply_qos_profile);
crates/xrce-agent/src/daemon/session.rs (plan_dds_create, branch
ObjectKind::QosProfile)
Tests: crates/xrce-agent/src/daemon/profiles.rs::tests::types_and_qos_libraries_in_a_dds_document_are_read,
crates/xrce-agent/src/daemon/profiles.rs::tests::the_example_file_of_the_spec_defines_the_objects_of_table_16,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_qos_profile_reference_applies_the_profile,
crates/xrce-agent/src/daemon/session.rs::tests::what_a_configuration_client_defines_is_referenced_by_another_client
Status: done — an endpoint names the profile as Library::Profile; CREATE
with OBJK_QOSPROFILE makes a profile that later CREATEs use (9d5c64dc398). The
row writes “XRCE Types” for the QosProfile.
§9.3 Table 15
Spec: §9.3, Table 15, p. 89 — “
Repo: crates/xrce-agent/src/daemon/definitions.rs (DomainDef,
SystemDefinitions::add_domain_library, SystemDefinitions::domain);
crates/xrce-agent/src/daemon/entity_repr.rs (participant: domain_ref,
domain_reference)
Tests: crates/xrce-agent/src/daemon/definitions.rs::tests::a_participant_library_and_inheritance,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_domain_reference_is_resolved_against_the_domain_libraries,
crates/xrce-agent/src/daemon/profiles.rs::tests::the_example_file_of_the_spec_defines_the_objects_of_table_16
Status: done — <domain_library> is read; a Domain is named
Library::Domain and resolved by domain_ref (XML) and domain_reference
(binary) of a DomainParticipant. The Domain has no ObjectKind (§7.7.5, Annex
A): a CREATE cannot name it, it has no ObjectId (452ffeb7f84, 0b67c04800c).
§9.3 Table 15 in
Spec: §9.3, Table 15, p. 89 — “
Repo: crates/xrce-agent/src/daemon/definitions.rs (DomainDef::topics,
SystemDefinitions::scope_of, ParticipantScope::topic)
Tests: crates/xrce-agent/src/daemon/definitions.rs::tests::a_participant_library_and_inheritance
Status: done — the topics of a Domain are in the scope of every
DomainParticipant that names the Domain (§7.7.3.7.1); a DataWriter or DataReader
finds them under their name, also through the base_name of a Domain
(9d5c64dc398).
§9.3 Table 15
Spec: §9.3, Table 15, p. 89 — “
Repo: crates/xrce-agent/src/daemon/definitions.rs
(SystemDefinitions::add_application_library, application);
crates/xrce-agent/src/daemon/profiles.rs
(AgentProfiles::predefined_objects); crates/xrce/src/object_id.rs
(ObjectId::from_reference)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::what_a_configuration_client_defines_is_referenced_by_another_client,
crates/xrce-agent/src/daemon/session.rs::tests::a_create_client_makes_the_objects_configured_for_the_client,
crates/xrce-agent/src/daemon/definitions.rs::tests::the_example_file_defines_the_objects_of_table_16
Status: done — Commits 452ffeb7f84, 2ba972cd270. <application_library> is
read, also as the root of a file. The Application is known under
“Library::Application” (example “Apps::App”); its ObjectId comes from the MD5 of
that string. Another client creates it with REPRESENTATION_BY_REFERENCE for as
long as the object that defined it exists.
§9.3 Table 15
Spec: §9.3, Table 15, p. 89 — “
Repo: crates/xrce-agent/src/daemon/definitions.rs
(SystemDefinitions::add_participant_library, participant,
plan_participant); crates/xrce-agent/src/daemon/session.rs (create_nested,
ensure_predefined)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_participant_definition_creates_the_objects_inside_it,
crates/xrce-agent/src/daemon/definitions.rs::tests::a_participant_library_and_inheritance,
crates/xrce-agent/src/daemon/profiles.rs::tests::a_library_can_be_the_root_and_a_clash_of_ids_is_refused,
crates/xrce-agent/src/daemon/definitions.rs::tests::the_example_file_defines_the_objects_of_table_16
Status: done — Commits 452ffeb7f84, 9d5c64dc398, 2ba972cd270.
<domain_participant_library> is read, also as the root of a file. The
participant is known under “Library::Participant”, inside an Application under
“Library::Application::Participant” (Table 16:
“MyApplications::ShapesDemoApp::MyParticipant”); its ObjectId comes from the MD5
of the string. The form <participant profile_name="…"> of a Fast DDS profiles
file stays readable beside it.
§9.3 Table 15 in
Spec: §9.3, Table 15, p. 89 — “
Repo: crates/xrce-agent/src/daemon/definitions.rs (plan_participant: the
topics of the participant and of its domain);
crates/xrce-agent/src/daemon/session.rs (create_nested)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_topic_is_created_by_name_or_by_register_type_ref,
crates/xrce-agent/src/daemon/definitions.rs::tests::the_example_file_defines_the_objects_of_table_16,
crates/xrce-agent/src/daemon/definitions.rs::tests::a_participant_library_and_inheritance
Status: done — Commits 9d5c64dc398, b97657ef4ec. A topic in the participant
is an object with the ObjectId of its name (example “Square” {0xce, 0xb2}). The
objects of the same participant name it with that name (topic_ref="Square" of
a DataWriter becomes the ObjectId of the topic); a name the participant does not
hold is refused. The form <topic profile_name="…"> in the Fast DDS format
stays readable beside it.
§9.3 Table 15 and
Spec: §9.3, Table 15, p. 89 — “
Repo: crates/xrce-agent/src/daemon/definitions.rs (plan_participant);
crates/xrce-agent/src/daemon/session.rs (create_nested);
crates/xrce-agent/src/daemon/dcps_bridge.rs (container_for checks that topic
and Publisher/Subscriber belong to the same participant)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_publisher_with_nested_data_writers_creates_them,
crates/xrce-agent/src/daemon/definitions.rs::tests::the_example_file_defines_the_objects_of_table_16,
crates/xrce-agent/src/daemon/definitions.rs::tests::what_cannot_be_planned_is_refused
Status: done — Commits 9d5c64dc398, b97657ef4ec. Publisher and Subscriber are
objects with the ObjectId of their name (example “MyPublisher” {0x13, 0xe3}),
without a library in front, and apply within the scope of their participant. Two
participants of one client that define an entity of the same name derive the
same ObjectId (the spec derives from the name only); the second is
STATUS_ERR_ALREADY_EXISTS (read from the code, not covered by a test).
§9.3 Table 15 and
Spec: §9.3, Table 15, p. 89 — “
Repo: crates/xrce-agent/src/daemon/session.rs (create_embedded,
create_nested, ensure_predefined);
crates/xrce-agent/src/daemon/definitions.rs (plan_participant)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_publisher_with_nested_data_writers_creates_them,
crates/xrce-agent/src/daemon/session.rs::tests::a_client_writes_through_a_preconfigured_data_writer_without_a_create,
crates/xrce-agent/src/daemon/session.rs::tests::a_client_reads_through_a_preconfigured_data_reader_without_a_create,
crates/xrce-agent/src/daemon/definitions.rs::tests::the_example_file_defines_the_objects_of_table_16
Status: done — Commits 9d5c64dc398, b97657ef4ec, 2ba972cd270. DataWriter
and DataReader are objects with the ObjectId of their name (example
“MySquareWriter” {0x1c, 0xc5}) and hang under their Publisher or Subscriber
(§9.3.1; Table 15 names <domain_participant> as the parent element). A client
writes and reads through them without a CREATE.
§9.3 ObjectId from the MD5 of the reference
Spec: §9.3, p. 89 — “The XRCE Objects created from the file-based configuration shall have their ObjectId automatically derived from the REPRESENTATION_BY_REFERENCE string. Specifically, the ObjectIdPrefix (see 7.7.6) shall be set to the first 2 bytes of the MD5 hash computed on the REPRESENTATION_BY_REFERENCE string. The MD5 treats each string character as a byte and does not include the NUL terminating character of the string.” Example: “MyWriter”, MD5 0x03e26181adfef529038bf0dce7cab871, ObjectIdPrefix {0x03, 0xe2}.
Repo: crates/xrce/src/object_id.rs (ObjectId::from_reference: MD5 of the
string without the NUL, the first two bytes, the low 4 bits replaced by the
ObjectKind)
Tests: crates/xrce/src/object_id.rs::tests::from_reference_matches_the_examples_of_the_spec
Status: done — Commits 468aa0940da. “MyWriter” gives the MD5
0x03e26181adfef529038bf0dce7cab871 (test with the crate md-5; also recomputed
with Python hashlib, measured), the ObjectIdPrefix {0x03, 0xe2} and, with the
kind DataWriter, the ObjectId {0x03, 0xe5}. The last sentence of the spec writes
“The ObjectIdPrefix shall be computed by combining the ObjectIdPrefix with the
ObjectKind”; the ObjectId is meant. The comment in
crates/xrce/src/xml_config.rs refers to ObjectId::from_reference.
§9.3.1 Example file
Spec: §9.3.1, p. 90–91 — “The following XML file could be used to configure
an XRCE Agent.” <types> with module ShapesDemoTypes, <qos_library name="MyQosLibrary">, <application_library name="MyApplications"> with
<application name="ShapesDemoApp">, participant MyParticipant, three
topics, MyPublisher with MySquareWriter and MyCircleWriter,
MySubscriber with MyTriangleRdr.
Repo: crates/xrce-agent/src/daemon/profiles.rs
(AgentProfiles::add_profiles reads the file)
Tests: crates/xrce-agent/src/daemon/profiles.rs::tests::the_example_file_of_the_spec_defines_the_objects_of_table_16
Status: n/a (informative) — example. The test loads the file with the
domain and the type added. domain_ref names
“ShapesDomainLibrary::ShapesDomain”, which the file does not define;
register_type type_ref="ShapeType" names the type without its module
ShapesDemoTypes.
§9.3.1 Table 16 predefined objects
Spec: §9.3.1, Table 16, p. 92 — “An XRCE Agent loading the above configuration file would have the pre-defined XRCE Objects shown in Table 16.” Twelve rows with reference, ObjectPrefix and ObjectId, e.g. “ShapesDemoTypes::ShapeType” {0x59, 0x51} {0x59, 0x5a}.
Repo: crates/xrce/src/object_id.rs (ObjectId::from_reference);
crates/xrce-agent/src/daemon/profiles.rs (AgentProfiles::predefined_objects)
Tests: crates/xrce/src/object_id.rs::tests::from_reference_matches_the_examples_of_the_spec,
crates/xrce-agent/src/daemon/profiles.rs::tests::the_example_file_of_the_spec_defines_the_objects_of_table_16,
crates/xrce-agent/src/daemon/definitions.rs::tests::the_example_file_defines_the_objects_of_table_16
Status: done — Commits 468aa0940da, 452ffeb7f84. The test in object_id.rs
recomputes all twelve rows of Table 16 from their own string (prefix, ObjectId,
kind in the low nibble). The agent tests check the ObjectIds of the objects it
derives from the file. Two strings of Table 16 differ from the file in §9.3.1:
“MyApplications::SimpleShapesDemoApplication” instead of
“MyApplications::ShapesDemoApp” (MD5 prefix of “ShapesDemoApp”: {0xeb, 0x1d})
and “MyTriangleReader” instead of “MyTriangleRdr” (MD5 prefix of
“MyTriangleRdr”: {0x50, 0x38}). The agent derives from the names of the file by
the rule of §9.3, so the ObjectIds of these two rows differ from the table.
There is no setting for the other reading. The participant is named
“MyApplications::ShapesDemoApp::MyParticipant”, not after the pattern of Table
15.
§10 XRCE Deployments
§10 Operations with one agent, exchange through DDS
Spec: §10, p. 93 — “All the operations described in the DDS-XRCE PIM pertain to the interaction of a client application with a single DDS-XRCE Agent. […] client applications may interact with each other despite connecting to different DDS-XRCE Agents. These interactions would happen as a consequence of the DDS-XRCE Agents creating and performing operations on DDS DomainParticipant entities”.
Repo: —
Tests: —
Status: n/a (informative) — description.
§10.1 Client through the agent to any DDS participant
Spec: §10.1, p. 93 — “The DDS DomainParticipant will discover the proxy DDS Entities that the XRCE Agent creates on behalf of the Client and with use the standard DDS-RTPS Interoperability protocol to communicate wit the Agent. The XRCE Client will communicate with the XRCE Agent using the XRCE Protocol. Using this protocol it can direct the XRCE Agent to create new DDS entities and use these entities to read and write data on the DDS Global Data Space.”
Repo: crates/xrce-agent/src/daemon/dcps_bridge.rs (RealDdsPort l. 310,
runtime_for l. 396)
Tests: crates/xrce-agent/tests/e2e_udp_loopback.rs::e2e_udp_loopback_keyed_dispose_reliable_besteffort_and_fragments,
crates/xrce-agent/src/daemon/dcps_bridge.rs::tests::full_chain_against_a_real_leased_domain
Status: done — the first test writes and reads against a DCPS participant of its own in the same process.
§10.2 Clients at different agents through DDS
Spec: §10.2, p. 93 — “XRCE Agents appear as DDS DomainParticipants in the DDS Dom ain. For this reason XRCE Client applications that are connected to different XRCE Agents will communicate with each other without the need for further configuration.”
Repo: crates/xrce-agent/src/daemon/dcps_bridge.rs (runtime_instance, runtime_for)
Tests: crates/xrce-agent/tests/two_agents.rs::two_clients_on_two_agents_exchange_a_sample_through_dds
Status: done — two daemons in one domain, a DataWriter through the first, a DataReader through the second: the sample arrives with equal bytes. The GUID prefixes of the runtimes were derived from the domain and the host alone, so two agents on one host did not discover each other; they carry the process and a counter (a03a6c8cbc2). The test is written, not run. ### §10.3 Several clients at one agent as with entities of their own
Spec: §10.3, p. 94 — “Multiple XRCE Client applications may be connected to the same XRCE Agent. In it up to the implementation of the XRCE Agent whether the DDS Entities it creates are exclusive to each XRCE Client or alternatively are shared across XRCE Clients. However, the behavior observable by the XRCE Client shall be as if the DDS XRCE Agent creates separate DDS Objects exclusive to each XRCE Client. […] If the XRCE Agent shares DDS entities among different XRCE Clients, then the requiremen t to behave ‘as if’ each had its own separate entities requires that the local DDS DataWriter entities discover and match the local DDS DataReader entities in the same DomainParticipant.”
Repo: crates/xrce-agent/src/daemon/dcps_bridge.rs (runtime_for l. 396:
one DcpsRuntime per domain for all clients, a further one per domain and
USER_DATA through own_runtime_slot; create_writer l. 654, create_reader l.
716)
Tests: crates/xrce-agent/src/daemon/dcps_bridge.rs::tests::two_large_samples_reach_a_default_reader_on_the_same_agent
Status: done — the writer of one client reaches the reader of another
client in the same DcpsRuntime. A separate GUID and the QoS of the participant
per client are not checked; by the code, a participant with its own USER_DATA
gets a DcpsRuntime of its own (read, not covered by a test).
§10.3 Shortcut between local writer and reader
Spec: §10.3, p. 94 — “An implementation of an XRCE Agent may choose to create faster communication path between the local XRCE DataWriter and DataReader objects […]. This ‘shortcut’ can be implemented as an optimization”.
Repo: —
Tests: —
Status: n/a (informative) — permission; the agent goes through the
DcpsRuntime.
§10.4 Federation of agents
Spec: §10.4, p. 95 — “The specification supports federated deployments where XRCE Agents appear as Clients to other XRCE Agents. In other to support these deployments the XRCE Agent implementation must implement the client -side of the XRCE Protocol in addition to the server part. Supporting this kind of deployment is an implementation decision”.
Repo: —
Tests: —
Status: open — an optional deployment that requires a client side in the agent; crates/xrce-agent has no client side.
§10.5 Direct communication between applications
Spec: §10.5, p. 96 — “The specification supports applications having direct communications using only the XRCE Protoco l. In order to do this each application must implement both the XRCE Client and the XRCE Agent part of the protocol.”
Repo: —
Tests: —
Status: n/a (informative) — deployment option.
§10.6 Combined deployment
Spec: §10.6, p. 97–98 — “Figure 28 below illustrates a scenario where the different deployments are combined into a single system.”
Repo: —
Tests: —
Status: n/a (informative) — figure.
§11 Transport Mappings
§11.1 Not bound to one transport
Spec: §11.1, p. 99 — “The XRCE protocol is not limited to any specific transports. It can be mapped to most existing network transports such as UDP, TCP and low bandwidth transports such as Bluetooth, ZigBee and 6LoWPAN.”
Repo: —
Tests: —
Status: n/a (informative) — description; ZeroDDS has UDP, TCP and a
serial line (items on §11.2, §11.3 and Annex C).
§11.1 Expected properties (1) to (4)
Spec: §11.1, p. 99 — “To run without additional overhead, it is expected that the transport supports the following functionality: (1) Deliver messages of at least 64 bytes. (2) Handle the integrity of messages, dropping any messages that are corru pted. […] (3) Provide the size of the received message as well as the source address. […] (4) Support bi-directional communication.”
Repo: —
Tests: —
Status: n/a (informative) — expectation of the transport. The serial
line adds length, addresses and CRC (items on Annex C).
§11.1 Expected property (5) security
Spec: §11.1, p. 99 — “(5) Provide transport-level security, specifically the means for the Client to authenticate the Agent and the means for secure (encrypted and authenticated) message exchange. Alternatively , the XRCE Agent and Client can be deployed on top of a secure network layer (e.g. an encrypted VPN).”
Repo: crates/xrce-agent/src/daemon/transport/secure.rs
(run_tls_listener, run_dtls_listener);
crates/xrce-agent/src/daemon/config.rs (ListenerConfig::Tls,
ListenerConfig::Dtls)
Tests: crates/xrce-agent/tests/secure_listeners.rs::tls::a_client_that_trusts_the_agents_certificate_opens_a_session,
crates/xrce-agent/tests/secure_listeners.rs::dtls::a_client_that_trusts_the_agents_certificate_opens_a_session
Status: n/a (informative) — expectation of the transport. Under the
features tls and dtls the agent has the listeners kind: tls and kind: dtls with the agent’s certificate and key (eb44fbbf575): the client
authenticates the agent, the messages travel encrypted (item on §8.3.2.4
“Protection of the ClientKey by the transport”). The listeners udp, tcp and
serial are not secured. The tests run only with the respective feature.
§11.1 Not required: reliability, ordering, notification of losses
Spec: §11.1, p. 99 — “The following functionality is explicitly not required from the transport: (1) It does not need to provide reliability. […] (2) It does not need to provide ordering. […] (3) It does not need to provide notification of dropped messages.”
Repo: —
Tests: —
Status: n/a (informative) — permission; reliability and ordering are in
the items on §8.3.2.3 and §8.4.14.
§11.1 Envelope for missing properties
Spec: §11.1, p. 99 — “Transports that do not meet some of the above pre-requisites may still be used by adding the missing information as an envelope around the XRCE message. […] If the transport does not support integrity a CRC suffix could be added to the XRCE message.”
Repo: —
Tests: —
Status: n/a (informative) — possibility; the envelopes for TCP and the
serial line are in the items on §11.3.3 and Annex C.
§11.2 UDP without security, DTLS or VPN
Spec: §11.2, p. 99 — “The UDP transport meets all the functionality listed in clause 11.1. Except that it does not provide security. For applications requiring security there is the ‘Datagram Transport Layer Security’ (DTLS) standard [DTLS] that provides security in top of UDP/IP. Alternatively, UDP mat be deployed on a private network (VPN)”.
Repo: crates/xrce-agent/src/daemon/transport/secure.rs
(run_dtls_listener); crates/xrce/src/transport_dtls.rs (WebrtcDtls,
WebrtcDtlsServer)
Tests: crates/xrce-agent/tests/secure_listeners.rs::dtls::a_client_that_trusts_the_agents_certificate_opens_a_session,
crates/xrce-agent/tests/secure_listeners.rs::dtls::a_plain_text_create_client_on_the_dtls_port_is_not_answered,
crates/xrce/tests/dtls_e2e.rs::dtls_handshake_and_roundtrip
Status: n/a (informative) — note. Under the feature dtls the agent has
the listener kind: dtls (DTLS 1.2 with the agent’s certificate,
eb44fbbf575); a plain-text CREATE_CLIENT on that port is not answered. The
tests run only with that feature.
§11.2.1 UDP v4 with ADDRESS_FORMAT_MEDIUM
Spec: §11.2.1, p. 99 — “When XRCE is mapped to the UDP v4, the TransportLocator union shall use the TransportLocatorFormat discriminator ADDRESS_FORMAT_MEDIUM. This selects the member medium_locator of type TransportLocatorMedium […] struct TransportLocatorMedium { octet address[4]; unsigned short port; };”
Repo: crates/xrce-agent/src/daemon/server.rs (listener_locators l. 438);
crates/xrce/src/transport_locator.rs (TransportLocatorMedium,
TransportLocator::encode_member)
Tests: crates/xrce-agent/src/daemon/server.rs::tests::listener_locators_maps_udp_tcp_and_ipv6,
crates/xrce/src/transport_locator.rs::tests::medium_has_a_padding_octet_and_a_port_in_the_byte_order_of_the_flag,
crates/xrce/src/transport_locator.rs::tests::a_udp_locator_carries_the_default_agent_port
Status: done — Commits 299b3a41398. a UDP listener with an IPv4 address is
announced as TransportLocator::Medium (discriminator ADDRESS_FORMAT_MEDIUM):
four address octets, one padding octet, the port as an unsigned short in the
byte order of the E flag.
§11.2.1 UDP v6 with ADDRESS_FORMAT_LARGE
Spec: §11.2.1, p. 99–100 — “When XRCE is mapped to the UDP v6, the TransportLocator union shall use the TransportLocatorFormat discriminator ADDRESS_FORMAT_LARGE. […] struct TransportLocatorLarge { octet address[16]; unsigned long port; }; The address field shall contain the IP v6 address and the port field shall contain the UDP/IP v6 port number.”
Repo: crates/xrce-agent/src/daemon/server.rs (listener_locators l. 438);
crates/xrce/src/transport_locator.rs (TransportLocatorLarge,
TransportLocator::encode_member)
Tests: crates/xrce-agent/src/daemon/server.rs::tests::listener_locators_maps_udp_tcp_and_ipv6,
crates/xrce/src/transport_locator.rs::tests::large_has_three_padding_octets_and_a_32_bit_port
Status: done — Commits 299b3a41398. a UDP listener with an IPv6 address is
announced as TransportLocator::Large: 16 address octets, three padding octets,
the port as an unsigned long.
§11.2.2 Agent as UDP server, client as UDP client
Spec: §11.2.2, p. 100 — “The UDP Server sends replies back the Client using the address and port received in the message. […] When communicating over UDP the XRCE Agent shall behave as an UDP Server and the XRCE Client as the UDP Client.”
Repo: crates/xrce-agent/src/daemon/transport.rs (run_udp_listener l.
428, PeerTable, Route::Udp); crates/xrce/src/transport_udp.rs
(XrceUdpSender::bind l. 54)
Tests: crates/xrce-agent/src/daemon/transport.rs::tests::udp_listener_answers_create_client_over_loopback,
crates/xrce-agent/src/daemon/transport.rs::tests::a_client_registering_again_is_answered_at_its_new_address
Status: done — the answer goes to the address under which the client last registered with CREATE_CLIENT; without an entry, to the source address.
§11.2.2 Port of the agent pre-configured
Spec: §11.2.2, p. 100 — “The XRCE Agent shall be pre-configured with the port number it shall listen to.”
Repo: crates/xrce-agent/src/daemon/config.rs (ListenerConfig::Udp,
default 0.0.0.0:2018)
Tests: crates/xrce-agent/src/daemon/config.rs::tests::default_config_has_one_udp_listener_on_2018,
crates/xrce-agent/src/daemon/config.rs::tests::a_listener_can_be_written_as_one_string
Status: done — the specification names no default port.
agent_default_port in crates/xrce/src/transport_udp.rs (l. 27) computes
7400 + 4 · domain; the agent does not use the function.
§11.2.2 Address and port of the agent pre-configured in the client
Spec: §11.2.2, p. 100 — “The XRCE Client shall be pre-configured with the UDP/IP address and port of the XRCE Agent.”
Repo: crates/xrce/src/transport_udp.rs (XrceUdpSender::bind l. 54);
crates/xrce-client/src/lib.rs (ClientTransport l. 89)
Tests: crates/xrce/src/transport_udp.rs::tests::loopback_roundtrip_create_client,
crates/xrce-agent/tests/e2e_udp_loopback.rs::e2e_udp_loopback_keyed_dispose_reliable_besteffort_and_fragments
Status: done — XrceClient gets the address through its
ClientTransport; crates/xrce-client itself has no UDP transport, the test
builds it in e2e_udp_loopback.rs.
§11.2.3 No envelope, exactly one message per datagram
Spec: §11.2.3, p. 100 — “The mapping of the XRCE Protocol to UDP/IP does not add any additional envelopes around the XRCE message. The UDP/IP payload shall contain exactly one XRCE message.”
Repo: crates/xrce/src/transport_udp.rs (send_message l. 67,
recv_message l. 89)
Tests: crates/xrce/src/transport_udp.rs::tests::rfc768_udp_delivers_one_datagram_per_message_with_boundaries_intact,
crates/xrce/src/transport_udp.rs::tests::rfc768_datagram_larger_than_udp_payload_limit_is_rejected
Status: done
§11.2.4 Multicast address and port of the agent
Spec: §11.2.4, p. 100 — “XRCE Agent discovery may be done using UDP/IP multicast. The XRCE Agents shall be pre-configured with the multicast address and port number they shall listen to. By default, they shall be the address 239.255.0.2 and the port 7400.”
Repo: crates/xrce/src/discovery.rs (XRCE_DISCOVERY_GROUP,
XRCE_DISCOVERY_PORT); crates/xrce-agent/src/daemon/discovery.rs
(bind_discovery_socket l. 146); crates/xrce-agent/src/daemon/config.rs
(discovery_address, discovery_port)
Tests: crates/xrce/src/discovery.rs::tests::discovery_constants_match_spec,
crates/xrce/src/discovery.rs::tests::the_discovery_port_is_bound_shared,
crates/xrce-agent/src/daemon/discovery.rs::tests::the_discovery_group_is_the_one_given,
crates/xrce-agent/src/daemon/config.rs::tests::the_discovery_group_can_be_set
Status: done — Commits fd2e9a5bcfd. default group 239.255.0.2 and port 7400;
discovery.address: and discovery.port: set both (item below).
§11.2.4 Setting the multicast address
Spec: §11.2.4, p. 100 — as above.
Repo: crates/xrce-agent/src/daemon/config.rs (discovery_address, key
discovery.address); crates/xrce-agent/src/daemon/discovery.rs
(bind_discovery_socket l. 146); crates/xrce-agent/src/daemon/server.rs (call
l. 400)
Tests: crates/xrce-agent/src/daemon/config.rs::tests::the_discovery_group_can_be_set,
crates/xrce-agent/src/daemon/discovery.rs::tests::the_discovery_group_is_the_one_given
Status: done — Commits fd2e9a5bcfd. the agent joins the configured group; the
configuration and bind_discovery_socket refuse an address that is no IPv4
multicast address. In the client the multicast address is an entry of the
candidate list of discover_over_udp.
§11.2.4 Periodic GET_INFO of the client to the multicast address
Spec: §11.2.4, p. 100 — “To discover Agents via multicast the XRCE Client shall send the GET_INFO message (see 8.3.5.3) periodically to the configured multicast address and port. […] The XRCE Client shall stop sending the periodic message once it receives a suitable response from an Agent.”
Repo: crates/xrce-client/src/discovery.rs (AgentDiscovery::poll,
on_datagram, discover_over_udp); crates/xrce/src/discovery.rs
(MulticastDiscovery::send_multicast)
Tests: crates/xrce-client/src/discovery.rs::tests::get_info_goes_to_the_candidates_every_period,
crates/xrce-client/src/discovery.rs::tests::a_suitable_answer_ends_the_search,
crates/xrce-client/src/discovery.rs::tests::the_search_over_udp_finds_the_agent_that_answers
Status: done — Commits fd2e9a5bcfd. GET_INFO(OBJECTID_AGENT) without session
and without ClientKey goes out at the first call and then every period to all
addresses of the list (multicast address and port or unicast candidates); a
suitable answer (INFO with STATUS_OK and the same major version) ends the
sending, a STATUS_ERR_INCOMPATIBLE or another major version does not. The test
with sockets sends to unicast candidates on loopback; reception on a real
multicast group is not checked.
§11.2.4 Answer of the agent with its TransportLocators
Spec: §11.2.4, p. 100 — “This message shall invoke the get_info operation (see 7.8.2.2) on the XRCE Agent, which shall respond and include its TransportLocators.”
Repo: crates/xrce-agent/src/daemon/discovery.rs (run_discovery_responder
l. 43, build_info_reply l. 107); crates/xrce-agent/src/daemon/server.rs
(listener_locators l. 438)
Tests: crates/xrce-agent/src/daemon/discovery.rs::tests::discovery_responder_answers_get_info_on_agent,
crates/xrce-agent/src/daemon/server.rs::tests::listener_locators_maps_udp_tcp_and_ipv6
Status: done — Commits ca0cf7e08bf, 299b3a41398. INFO with
AGENT_ActivityInfo.address_seq as the TransportLocatorSeq of the UDP and TCP
listeners (Medium for IPv4, Large for IPv6) and with the AGENT_Representation.
The agent does not announce listeners with DTLS or TLS and the serial line;
Annex A has no TransportLocatorFormat for them.
§11.2.4 Unicast discovery over a list of addresses
Spec: §11.2.4, p. 100 — “XRCE Agent discovery may be done using UDP/IP unicast. The XRCE Clients shall be pre-configured with a list of candidate UDP addresses and ports where XRCE Agents may be located. To discover Agents via unicast the XRCE Client shall send the GET_INFO message (see 8.3.5.3) periodically to the configured addresses and ports. […] The XRCE Client shall stop sending the periodic message once it receives a suitable response from an Agent.”
Repo: crates/xrce-client/src/discovery.rs
(AgentDiscovery::new(candidates, period), discover_over_udp)
Tests: crates/xrce-client/src/discovery.rs::tests::get_info_goes_to_the_candidates_every_period,
crates/xrce-client/src/discovery.rs::tests::the_search_over_udp_finds_the_agent_that_answers
Status: done — Commits fd2e9a5bcfd. the client takes a list of candidate
addresses, sends GET_INFO periodically to all of them and stops at a suitable
answer.
§11.3 TCP without security and length, TLS or VPN
Spec: §11.3, p. 100–101 — “The TCP transport meets all the functionality listed in clause 11.1. except it does not provide security nor information on the message size. For applications requiring security there is the ‘Transport Layer Security (TLS)’ standard [TLS] […]. The message size shall be added as a prefix ahead of the XRCE message as defined in 11.3.3.”
Repo: crates/xrce-agent/src/daemon/transport/secure.rs
(run_tls_listener); crates/xrce/src/transport_tls.rs (RustlsTlsClient,
RustlsTlsServer)
Tests: crates/xrce-agent/tests/secure_listeners.rs::tls::a_client_that_trusts_the_agents_certificate_opens_a_session,
crates/xrce-agent/tests/secure_listeners.rs::tls::a_plain_text_create_client_on_the_tls_port_is_not_answered,
crates/xrce/tests/tls_e2e.rs::tls_handshake_and_message_roundtrip
Status: n/a (informative) — note; the length is in the item on §11.3.3.
Under the feature tls the agent has the listener kind: tls (TLS with the
agent’s certificate, eb44fbbf575); the 2-byte length prefix is inside the
encrypted stream. The tests run only with that feature.
§11.3.1 TCP v4 with ADDRESS_FORMAT_MEDIUM
Spec: §11.3.1, p. 101 — “When XRCE is mapped to the TCP/IP version 4, the TransportLocator union shall use the TransportLocatorFormat discriminator ADDRESS_FORMAT_MEDIUM.”
Repo: crates/xrce-agent/src/daemon/server.rs (listener_locators l. 438);
crates/xrce/src/transport_locator.rs (TransportLocatorMedium)
Tests: crates/xrce-agent/src/daemon/server.rs::tests::listener_locators_maps_udp_tcp_and_ipv6,
crates/xrce/src/transport_locator.rs::tests::medium_has_a_padding_octet_and_a_port_in_the_byte_order_of_the_flag
Status: done — Commits 299b3a41398. a TCP listener with an IPv4 address is
announced as TransportLocator::Medium (ADDRESS_FORMAT_MEDIUM); the
discriminator 0x04 no longer exists.
§11.3.1 TCP v6 with ADDRESS_FORMAT_LARGE
Spec: §11.3.1, p. 101 — “When XRCE is mapped to the TCP/IP version 6, the TransportLocator union shall use the TransportLocatorFormat discriminator ADDRESS_FORMAT_LARGE. […] The address field shall contain the IP v6 address and the port field shall contain the TCP/IP v6 port number.”
Repo: crates/xrce-agent/src/daemon/server.rs (listener_locators l. 438);
crates/xrce/src/transport_locator.rs (TransportLocatorLarge)
Tests: crates/xrce-agent/src/daemon/server.rs::tests::listener_locators_maps_udp_tcp_and_ipv6,
crates/xrce/src/transport_locator.rs::tests::large_has_three_padding_octets_and_a_32_bit_port
Status: done — Commits 299b3a41398. a TCP listener with an IPv6 address is
announced as TransportLocator::Large, with the port number in locator_port.
§11.3.2 Agent as TCP server, client as TCP client
Spec: §11.3.2, p. 101 — “The TCP Server accepts the connection from the Client. This establishes a bi-directional communication channel. […] The TCP Server can send and receive messages to and from the Client. When communicating over TCP the XRCE Agent shall behave as a TCP Server and the XRCE Client as the TCP Client.”
Repo: crates/xrce/src/transport_tcp.rs (XrceTcpServer::accept l. 160,
XrceTcpClient::connect l. 52); crates/xrce-agent/src/daemon/transport.rs
(run_tcp_listener l. 550, run_tcp_connection l. 485)
Tests: crates/xrce/src/transport_tcp.rs::tests::tcp_loopback_create_client_roundtrip,
crates/xrce/src/transport_tcp.rs::tests::tcp_loopback_three_message_chain,
crates/xrce-agent/src/daemon/transport.rs::tests::a_tcp_client_gets_the_messages_of_the_agent_over_its_connection
Status: done — the roles are checked in the transport and at the agent’s TCP listener; the agent sends over the connection without a request too (items below).
§11.3.2 TCP listener of the agent
Spec: §11.3.2, p. 101 — as above.
Repo: crates/xrce-agent/src/daemon/transport.rs (run_tcp_listener l.
550, run_tcp_connection l. 485)
Tests: crates/xrce-agent/src/daemon/transport.rs::tests::a_tcp_client_gets_the_messages_of_the_agent_over_its_connection
Status: done — the test starts the listener, registers a client over TCP
and receives STATUS_AGENT. The agent does not use XrceTcpServer.
§11.3.2 Messages of the agent without a request over TCP
Spec: §11.3.2, p. 101 — “The TCP Server can send and receive messages to and from the Client.”
Repo: crates/xrce-agent/src/daemon/transport.rs (run_ticker l. 410,
deliver l. 367, Route)
Tests: crates/xrce-agent/src/daemon/transport.rs::tests::a_tcp_client_gets_the_messages_of_the_agent_over_its_connection
Status: done — Commits d1cfe57959b. one thread (run_ticker, transport.rs
l. 410) calls tick for all listeners; deliver (l. 367) sends each message
the way its client registered on: the socket of a UDP listener or the queue of
the writer of a TCP connection or serial line. The routes of a connection go
with it. The test receives over the connection a message the agent sends
without a request.
§11.3.2 Port of the agent pre-configured
Spec: §11.3.2, p. 101 — “The XRCE Agent shall be pre-configured with the port number it shall listen to.”
Repo: crates/xrce-agent/src/daemon/config.rs (ListenerConfig::Tcp)
Tests: crates/xrce-agent/src/daemon/config.rs::tests::a_listener_can_be_written_as_one_string
Status: done
§11.3.2 Address and port of the agent pre-configured in the client
Spec: §11.3.2, p. 101 — “The XRCE Client shall be pre-configured with the TCP/IP address and port of the XRCE Agent.”
Repo: crates/xrce/src/transport_tcp.rs (XrceTcpClient::connect l. 52);
crates/xrce-client/src/discovery.rs (TcpTransport, connect_over_tcp)
Tests: crates/xrce/src/transport_tcp.rs::tests::tcp_loopback_create_client_roundtrip,
crates/xrce-client/src/discovery.rs::tests::the_search_over_tcp_connects_to_the_agent_that_accepts
Status: done — Commits fd2e9a5bcfd. crates/xrce-client has a
ClientTransport over TCP in TcpTransport (feature std); connect_over_tcp
connects to the pre-configured addresses and sends CREATE_CLIENT.
§11.3.3 Length in two bytes, little-endian
Spec: §11.3.3, p. 101 — “The mapping of the XRCE Protocol to TCP/IP adds a 2-byte prefix as an envelope the XRCE message. The 2-byte prefix shall contain the length of the XRCE message that follows encoded as little endian.”
Repo: crates/xrce/src/transport_tcp.rs (TCP_LENGTH_PREFIX_SIZE l. 37,
XrceTcpClient::send_message l. 70, recv_message l. 103)
Tests: crates/xrce/src/transport_tcp.rs::tests::tcp_length_prefix_size_constant,
crates/xrce/src/transport_tcp.rs::tests::rfc793_byte_stream_is_delimited_by_the_length_prefix_not_by_writes,
crates/xrce/src/transport_tcp.rs::tests::rfc793_frame_split_across_two_writes_is_reassembled
Status: done
§11.3.3 Exactly one message, alignment unchanged
Spec: §11.3.3, p. 101 — “After the 2-byte envelope the TCP/IP payload shall contain exactly one XRCE message. The alignment of the XRCE message shall not be changed by the added 2-byte prefix. Stated differently the XRCE message shall consider its first byte to be aligned to an 8-byte (XCDR maximum alignment) boundary.”
Repo: crates/xrce/src/transport_tcp.rs (send_message: msg.encode()
before the length)
Tests: crates/xrce/src/transport_tcp.rs::tests::tcp_loopback_three_message_chain,
crates/xrce/src/submessages/mod.rs::tests::message_two_submessages_padded_correctly
Status: done — the message is encoded without knowledge of the length. §8.2.1 names an alignment of 16 bytes for the start of the message, §11.3.3 one of 8 bytes.
§11.3.4 Multicast discovery also for TCP
Spec: §11.3.4, p. 102 — “XRCE Agent discovery may be done using UDP/IP multicast even if the communication will be over TCP. The XRCE Agents may be pre-configured with the multicast address and port number they shall listen to. By default they shall be the address 239.255.0.2 and the port 7400.”
Repo: crates/xrce-agent/src/daemon/server.rs (responder independent of the
kind of listener); crates/xrce-agent/src/daemon/discovery.rs
(bind_discovery_socket l. 146)
Tests: crates/xrce-agent/src/daemon/discovery.rs::tests::discovery_responder_answers_get_info_on_agent,
crates/xrce/src/discovery.rs::tests::discovery_constants_match_spec
Status: done — the locator of a TCP listener in the answer is dealt with in the item on §11.3.1.
§11.3.4 Periodic GET_INFO of the client for TCP
Spec: §11.3.4, p. 102 — “To discover Agents via multicast the XRCE Client shall send the GET_INFO message (see 8.3.5.3) periodically to the configured multicast address and port. […] The XRCE Client shall stop sending the periodic message once it receives a suitable response from an Agent.”
Repo: crates/xrce-client/src/discovery.rs (AgentDiscovery,
discover_over_udp)
Tests: crates/xrce-client/src/discovery.rs::tests::get_info_goes_to_the_candidates_every_period,
crates/xrce-client/src/discovery.rs::tests::a_suitable_answer_ends_the_search,
crates/xrce-client/src/discovery.rs::tests::the_search_over_udp_finds_the_agent_that_answers
Status: done — Commits fd2e9a5bcfd. as in the item on §11.2.4: the client
searches for the agent with GET_INFO to the multicast address and then
connects over TCP (item below).
§11.3.4 Discovery through TCP connections to a list of addresses
Spec: §11.3.4, p. 102 — “The XRCE Clients shall be pre-configured with a list of candidate TCP addresses and ports where XRCE Agents may be located. To discover Agents via unicast the XRCE Client shall periodically attempt to establish TCP connections to the configured addresses and ports. One a connection is established it shall send the CREATE_CLIENT message […]. The XRCE Client shall stop making periodic connection attempts once it receives a suitable response from an Agent.”
Repo: crates/xrce-client/src/discovery.rs (connect_over_tcp)
Tests: crates/xrce-client/src/discovery.rs::tests::the_search_over_tcp_connects_to_the_agent_that_accepts
Status: done — Commits fd2e9a5bcfd. each period the client tries to connect to
every address of the list; on a connection it sends CREATE_CLIENT and stops at a
STATUS_AGENT with STATUS_OK.
§11.4 Other transports
Spec: §11.4, p. 102 — “The XRCE Protocol is well suited to be mapped to other transports […]. it is expected that future revisions of this specification will provide additional transport mappings. An example Serial Transport mapping can be found in Annex C.1”
Repo: —
Tests: —
Status: n/a (informative) — outlook; the serial line is in the items on
Annex C.
Annex A IDL Types
Annex A Types equal to §7.7 and §8.3.5
Spec: Annex A, p. 103–120 — “module dds { module xrce { […] }; };” with ClientKey, ObjectKind, ObjectId, XrceCookie, XrceVersion, XrceVendorId, Time_t, SessionId, StreamId, RepresentationFormat and the representations of the objects, CreationMode, RequestId, StatusValue, ResultStatus, InfoMask, the ActivityInfo types, ObjectInfo, BaseObjectRequest, BaseObjectReply, DataFormat, DataDeliveryControl, ReadSpecification, SampleInfoFlags, SampleInfoDelta, SampleData, Sample, SampleDelta, PackedSamples, DataRepresentation, the payloads of the submessages and SubmessageId.
Repo: —
Tests: —
Status: n/a (informative) — mapping: where Annex A has the same form as
§7.7 or §8.3.5, the requirement is in the item there. Deviating and additional
forms are in the following items. Annex A writes
SESSIONID_NONE_WITH_CLIENT_KEY, §8.3.2.1 SESSION_ID_NONE_WITH_CLIENT_KEY;
Annex A writes STREAMID_BUILTIN_BEST_EFFORTS.
Annex A Types without @extensibility
Spec: Annex A, p. 104–112, p. 119 — “struct Time_t { long seconds; unsigned long nanoseconds; };”, “struct TransportLocatorMedium { […] };”, “struct Property { string name; string value; };”, “struct ResultStatus { StatusValue status; octet implementation_status; };”, “struct ACKNACK_Payload { […] };” without annotation; DDS-XTypes 1.3 §7.3.1.2.1.8, p. 96: “In the event that the representation of a given type does not indicate the type’s extensibility kind, the type shall be considered appendable.”
Repo: crates/xrce/src/encoding.rs (UnannotatedTypes,
with_unannotated_types, begin_unannotated, end_unannotated);
crates/xrce-agent/src/daemon/config.rs (unannotated_types)
Tests: crates/xrce/tests/unannotated_types.rs::the_default_is_appendable_with_a_dheader,
crates/xrce/tests/unannotated_types.rs::the_final_setting_writes_the_reference_implementations_octets,
crates/xrce/tests/unannotated_types.rs::both_forms_are_read_in_either_setting,
crates/xrce/tests/unannotated_types.rs::the_reference_implementations_octets_are_read_in_the_default_setting,
crates/xrce/src/transport_locator.rs::tests::by_default_the_union_and_its_case_have_a_dheader,
crates/xrce-agent/src/daemon/config.rs::tests::the_extensibility_of_unannotated_types_can_be_set
Status: done — Commits 7f85e76debd, 220857a1e90, 5f31939a719. Without
@extensibility the type is APPENDABLE (DDS-XTypes 1.3 §7.3.1.2.1.8): Time_t,
ResultStatus, Property, TransportLocator and ACKNACK_Payload carry a
DHEADER in XCDR2; this is the default. The octets of the eProsima capture
(STATUS 6 bytes payload, ACKNACK 5 bytes, read from
tools/wire-capture/xrce-sessions/agent-to-client.hex) are the named setting
FINAL: agent key unannotated_types: final, Rust API
zerodds_xrce::encoding::UnannotatedTypes::Final; every SDK has the option
“unannotated types” (82fa0a977e2). The readers accept both forms.
Annex A OBJK_OTHER = 0x0F
Spec: Annex A, p. 103 — “const ObjectKind OBJK_OTHER = 0x0F;”
Repo: crates/xrce/src/object_kind.rs (OBJK_OTHER l. 43,
ObjectKind::Other, ObjectKind::from_u8)
Tests: crates/xrce/src/object_kind.rs::tests::all_spec_kinds_roundtrip,
crates/xrce/src/object_kind.rs::tests::raw_const_values_match_spec
Status: done — Commits daf2a618f74. the value 0x0F is named OBJK_OTHER as in
Annex A; OBJK_DOMAIN no longer exists. The spec gives the Domain no ObjectKind
(item on §7.7.3.4).
Annex A OBJECTID_AGENT {0xFF, 0xFD}
Spec: Annex A, p. 103 — “#define OBJECTID_AGENT {0xFF,0xFD}”
Repo: crates/xrce/src/object_id.rs (OBJECTID_AGENT l. 44)
Tests: crates/xrce/src/object_id.rs::tests::agent_singleton_has_kind_agent,
crates/xrce-agent/src/daemon/discovery.rs::tests::discovery_responder_answers_get_info_on_agent
Status: done
Annex A OBJECTID_SESSION {0xFF, 0xFF}
Spec: Annex A, p. 103 — “#define OBJECTID_SESSION {0xFF,0xFF}”
Repo: crates/xrce/src/object_id.rs (OBJECTID_SESSION l. 42,
OBJECTID_INVALID l. 40)
Tests: crates/xrce/src/object_id.rs::tests::session_object_id_is_all_ones,
crates/xrce/src/object_id.rs::tests::reserved_object_ids_per_spec_7_6_and_annex_a
Status: done — Commits daf2a618f74. OBJECTID_SESSION is {0xFF, 0xFF};
OBJECTID_INVALID is {0x00, 0x00} (§7.6). The spec does not say what
OBJECTID_SESSION stands for; the code does not use the constant.
Annex A XRCE_VENDOR_INVALID
Spec: Annex A, p. 104 — “typedef octet XrceVendorId[2]; #define XRCE_VENDOR_INVALID1 0x00 #define XRCE_VENDOR_INVALID1 0x00”
Repo: —
Tests: —
Status: n/a (informative) — constants without a rule. The line appears
twice with the same name; presumably the two octets of an invalid vendor are
meant.
Annex A TransportLocatorFormat
Spec: Annex A, p. 104 — “@bit_bound(8) enum TransportLocatorFormat { ADDRESS_FORMAT_SMALL, ADDRESS_FORMAT_MEDIUM, ADDRESS_FORMAT_LARGE, ADDRESS_FORMAT_STRING };” and p. 105 “union TransportLocator switch (TransportLocatorFormat) { […] case ADDRESS_FORMAT_LARGE: TransportLocatorLarge medium_locator; […] };”
Repo: crates/xrce/src/transport_locator.rs (fmt_disc l. 50,
TransportLocator::encode_into, decode_at)
Tests: crates/xrce/src/transport_locator.rs::tests::medium_has_a_padding_octet_and_a_port_in_the_byte_order_of_the_flag,
crates/xrce/src/transport_locator.rs::tests::large_has_three_padding_octets_and_a_32_bit_port,
crates/xrce/src/transport_locator.rs::tests::small_is_two_address_octets_and_a_one_octet_port,
crates/xrce/src/transport_locator.rs::tests::string_length_is_aligned_to_four,
crates/xrce/src/transport_locator.rs::tests::unknown_discriminator_rejected
Status: done — Commits 299b3a41398. the four values 0 to 3; the discriminator
is one octet before the member, by default behind the DHEADER of the union (item
on Annex A “Types without @extensibility”). Annex A names the member for LARGE
medium_locator; on the wire the name has no effect.
Annex A Discriminators 0x04 and 0x05
Spec: Annex A, p. 104 — as above.
Repo: crates/xrce/src/transport_locator.rs (fmt_disc has only 0x00 to
0x03)
Tests: crates/xrce/src/transport_locator.rs::tests::unknown_discriminator_rejected
Status: done — Commits 299b3a41398. fmt_disc::TCP and fmt_disc::SERIAL and
TransportLocator::Tcp and Serial are removed; the test refuses the
discriminators 4 and 5. TCP listeners are announced as Medium or Large, the
serial line not at all.
Annex A TransportLocatorSmall
Spec: Annex A, p. 104–105 — “struct TransportLocatorSmall { octet address[2]; octet locator_port; };”
Repo: crates/xrce/src/transport_locator.rs (TransportLocatorSmall:
address: [u8; 2], port: u8)
Tests: crates/xrce/src/transport_locator.rs::tests::small_is_two_address_octets_and_a_one_octet_port
Status: done — Commits 299b3a41398. two address octets and one port octet,
without padding.
Annex A TransportLocatorMedium
Spec: Annex A, p. 105 — “struct TransportLocatorMedium { octet address[4]; unsigned short locator_port; };”
Repo: crates/xrce/src/transport_locator.rs (TransportLocatorMedium,
encode_member)
Tests: crates/xrce/src/transport_locator.rs::tests::medium_has_a_padding_octet_and_a_port_in_the_byte_order_of_the_flag,
crates/xrce/src/transport_locator.rs::tests::a_udp_locator_carries_the_default_agent_port
Status: done — Commits 299b3a41398. as in the item on §11.2.1: one padding
octet after the address, the port as a number in the byte order of the E flag.
Annex A TransportLocatorLarge
Spec: Annex A, p. 105 — “struct TransportLocatorLarge { octet address[16]; unsigned long locator_port; };”
Repo: crates/xrce/src/transport_locator.rs (TransportLocatorLarge,
TransportLocator::encode_into, TransportLocator::decode_at)
Tests: crates/xrce/src/transport_locator.rs::tests::large_has_three_padding_octets_and_a_32_bit_port,
crates/xrce/src/transport_locator.rs::tests::a_locator_sequence_is_a_count_and_aligned_locators
Status: done — Commits 299b3a41398, 7f85e76debd. 16 address octets, three
padding bytes, the port as an unsigned long in the byte order of the E flag.
The union and the struct of its case carry a DHEADER each when they have no
@extensibility (APPENDABLE per DDS-XTypes 1.3 §7.3.1.2.1.8); the agent key
unannotated_types: final writes them without. The test of the padding bytes
runs in the Final setting, the test of the sequence in the default.
Annex A TransportLocatorString
Spec: Annex A, p. 105 — “struct TransportLocatorString { string value; };”
Repo: crates/xrce/src/transport_locator.rs (TransportLocator::String,
TRANSPORT_LOCATOR_STRING_MAX, TransportLocator::encode_into)
Tests: crates/xrce/src/transport_locator.rs::tests::string_length_is_aligned_to_four,
crates/xrce/src/transport_locator.rs::tests::a_long_string_locator_is_not_cut_at_256,
crates/xrce/src/transport_locator.rs::tests::a_string_without_its_nul_is_refused
Status: done — Commits 299b3a41398. the length is an unsigned long, aligned
to 4 and in the byte order of the E flag; the characters and a NUL follow. The
upper limit is 65 535 bytes (the size of a submessage), no longer 256.
Annex A Property and PropertySeq
Spec: Annex A, p. 105 — “struct Property { string name; string value; };
typedef sequence
Repo: crates/xrce/src/handshake.rs (Property, encode_properties,
decode_properties, decode_property, MAX_PROPERTIES)
Tests: crates/xrce/src/handshake.rs::tests::a_property_has_a_dheader_by_default,
crates/xrce/src/handshake.rs::tests::a_big_endian_client_representation_with_properties_reads_back,
crates/xrce/src/handshake.rs::tests::a_big_endian_agent_representation_with_properties_reads_back,
crates/xrce/src/handshake.rs::tests::padding_counts_from_the_start_of_the_payload,
crates/xrce/src/handshake.rs::tests::max_properties_cap_enforced_on_decode,
crates/xrce/src/handshake.rs::tests::a_malformed_property_seq_is_an_error_not_absent_properties,
crates/xrce-agent/src/daemon/session.rs::tests::an_unreadable_property_seq_is_refused_with_invalid_data
Status: done — Commits ca0cf7e08bf, 7f85e76debd, b9255734bfb. the number of
elements and the lengths of the strings are unsigned longs, aligned to 4 from
the start of the payload; in CLIENT_Representation the number lies at offset
16. A Property without @extensibility carries a DHEADER (default);
unannotated_types: final writes it without; both forms are read. The byte
order follows the E flag. A sequence that cannot be read is an error and does
not count as absent; the agent answers it with STATUS_ERR_INVALID_DATA. Upper
limit on reading: 64 elements.
Annex A CLIENT_Representation
Spec: Annex A, p. 105–106 — “@extensibility(FINAL) struct CLIENT_Representation { XrceCookie xrce_cookie; XrceVersion xrce_version; XrceVendorId xrce_vendor_id; ClientKey client_key; SessionId session_id; @optional PropertySeq properties; };”
Repo: crates/xrce/src/handshake.rs (ClientRepresentation, encode_with,
decode_with, encode_into, decode_at)
Tests: crates/xrce/src/handshake.rs::tests::client_representation_decodes_the_captured_create_client_prefix,
crates/xrce/src/handshake.rs::tests::client_representation_roundtrip_with_properties,
crates/xrce/src/handshake.rs::tests::by_default_the_representations_have_no_timestamp,
crates/xrce/src/handshake.rs::tests::the_prose_form_has_a_time_t_after_the_vendor_id
Status: done — Commits ca0cf7e08bf, b9255734bfb, f8bdf3cd878. the code
follows the form of Annex A; @optional is an octet 0 or 1, properties lies
as in the item above. The text of §7.8.2.1 also names a Time_t client_timestamp after xrce_vendor_id; the IDL and the bytes of Annex B.1
do not have it. The form of Annex A is the default; the form of the text is the
named setting RepresentationTimestamps::Present (agent key
representation_timestamps: present, XrceClient::set_representation_timestamps,
option representation timestamps in every SDK). The two octets after
properties (requested_mtu) are an extension of eProsima, aligned to 2.
Annex A AGENT_Representation
Spec: Annex A, p. 106 — “@extensibility(FINAL) struct AGENT_Representation { XrceCookie xrce_cookie; XrceVersion xrce_version; XrceVendorId xrce_vendor_id; @optional PropertySeq properties; };”
Repo: crates/xrce/src/handshake.rs (AgentRepresentation, encode_with,
decode_with, encode_into, decode_at)
Tests: crates/xrce/src/handshake.rs::tests::agent_representation_decodes_the_captured_status_agent_body,
crates/xrce/src/handshake.rs::tests::agent_representation_roundtrip_no_properties,
crates/xrce/src/handshake.rs::tests::the_agent_representation_follows_the_setting_the_same_way
Status: done — Commits ca0cf7e08bf, b9255734bfb, f8bdf3cd878. the form with
agent_timestamp (§7.8.2.1) is the same named setting as for
CLIENT_Representation (representation_timestamps, default absent per
Annex A).
Annex A OBJK_DomainParticipant_Binary
Spec: Annex A, p. 109 — “@extensibility(APPENDABLE) struct OBJK_DomainParticipant_Binary { @optional string<128> domain_reference; @optional string<128> qos_profile_reference; };”
Repo: crates/xrce-agent/src/daemon/binary_forms.rs (participant,
ParticipantBinary); crates/xrce-agent/src/daemon/entity_repr.rs
(participant)
Tests: crates/xrce-agent/src/daemon/binary_forms.rs::tests::participant_binary_in_both_forms,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_spec_binary_participant_is_read,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_domain_reference_is_resolved_against_the_domain_libraries,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_participant_qos_profile_reference_is_applied
Status: done — Commits f548fee2522, 0b67c04800c. the blob is read as XCDR2:
Annex A (DHEADER, two @optional references), then the form of §7.7.3.6.3
(long domain_id first), then the two references without a DHEADER that the
eProsima client sends. domain_reference is resolved against the Domains of the
<domain_library> files (STATUS_ERR_UNKNOWN_REFERENCE for a name in no
library; the domain_id of the Domain must agree with that of the
representation). qos_profile_reference applies the participant QoS of the
profile (USER_DATA, ENTITY_FACTORY; any other policy gives
STATUS_ERR_INCOMPATIBLE).
Annex A OBJK_Topic_Binary as APPENDABLE
Spec: Annex A, p. 109 — “@extensibility(APPENDABLE) struct OBJK_Topic_Binary { string<256> topic_name; @optional string<256> type_reference; @optional DDS:XTypes::TypeIdentifier type_identifier; };”
Repo: crates/xrce-agent/src/daemon/binary_forms.rs (topic,
TopicBinary, Form::AnnexA, Form::Clauses); crates/xrce-agent/src/daemon/entity_repr.rs
(topic)
Tests: crates/xrce-agent/src/daemon/binary_forms.rs::tests::annex_a_topic_has_a_dheader,
crates/xrce-agent/src/daemon/binary_forms.rs::tests::the_36_octet_example_of_the_clause_is_a_topic,
crates/xrce-agent/src/daemon/binary_forms.rs::tests::a_topic_with_a_type_identifier_reads_it_and_one_without_a_type_is_refused,
crates/xrce-agent/src/daemon/binary_forms.rs::tests::string_bounds_are_checked,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_spec_binary_topic_names_its_topic_and_type
Status: done — Commits f548fee2522. both the form of Annex A (a DHEADER in front
of the members) and the FINAL form of §7.7.3.7.3 (no DHEADER, the 36 octets of
the example in §7.7.3.1.3) are read; §7.7.3.7.3 gives no extensibility.
string<256> is checked. A type_identifier takes precedence over
type_reference; if both are missing the agent answers
STATUS_ERR_INVALID_DATA.
Annex A OBJK_Publisher_Binary as APPENDABLE
Spec: Annex A, p. 109 — “@extensibility(FINAL) struct
OBJK_Publisher_Binary_Qos { @optional sequence
Repo: crates/xrce-agent/src/daemon/binary_forms.rs (container,
ContainerBinary); crates/xrce-agent/src/daemon/entity_repr.rs (container)
Tests: crates/xrce-agent/src/daemon/binary_forms.rs::tests::publisher_binary_of_annex_a,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::an_annex_a_binary_publisher_gives_its_partitions,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_captured_binary_publisher_has_default_qos
Status: done — Commits f548fee2522. the form of Annex A (DHEADER,
publisher_name, qos with partitions and group_data) is read; if that
fails, container reads the form of §7.7.3.8.2 without a DHEADER, which the
eProsima client sends. §7.7.3.8.2 names the QoS structure
OBJK_PUBLISHER_QosBinary; this has no effect on the wire.
Annex A OBJK_Subscriber_Binary as APPENDABLE
Spec: Annex A, p. 109 — “@extensibility(APPENDABLE) struct OBJK_Subscriber_Binary { @optional string subscriber_name; @optional OBJK_Subscriber_Binary_Qos qos; };”
Repo: crates/xrce-agent/src/daemon/binary_forms.rs (container,
ContainerBinary); crates/xrce-agent/src/daemon/entity_repr.rs (container
with element = subscriber)
Tests: crates/xrce-agent/src/daemon/binary_forms.rs::tests::publisher_binary_of_annex_a,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::an_annex_a_binary_publisher_gives_its_partitions
Status: done — Commits f548fee2522. the same function and the same layout as
for the publisher; the tests read the blob of the publisher, a test with a
blob of its own for the subscriber is missing.
Annex A EndpointQosFlags with is_history_keep_all
Spec: Annex A, p. 110 — “@bit_bound(16) bitmask EndpointQosFlags { @position(0) is_reliable, @position(1) is_history_keep_all, […] };”
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (apply_endpoint_binary,
spec_flags, flags); crates/xrce-agent/src/daemon/binary_forms.rs
(EndpointBinary::bit1_is_keep_all)
Tests: crates/xrce-agent/src/daemon/binary_forms.rs::tests::writer_binary_of_annex_a_with_qos,
crates/xrce-agent/src/daemon/binary_forms.rs::tests::reader_binary_of_the_clause,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::an_annex_a_binary_writer_names_its_topic_and_qos,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_clause_binary_reader_names_its_topic_and_qos,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_captured_binary_writer_is_reliable_keep_last_transient_local
Status: done — Commits f548fee2522. Annex A (bit 1 = is_history_keep_all)
and §7.7.3.10.2 (bit 1 = is_history_keep_last) contradict each other. The bit
is read according to the form in which the blob is readable: the form of
Annex A first, then the form of the clause; the classic CDR structure of
eProsima (qos_flags 0x000b in the capture) reads bit 1 as KEEP_LAST. Bits
outside EndpointQosFlags and more than one durability bit give
STATUS_ERR_INVALID_DATA.
Annex A OBJK_DataWriter_Binary_Qos
Spec: Annex A, p. 110 — “@extensibility(FINAL) struct OBJK_DataWriter_Binary_Qos : OBJK_Endpoint_Binary_Qos { @optional unsigned long ownership_strength; };”
Repo: crates/xrce-agent/src/daemon/binary_forms.rs (endpoint_qos)
Tests: crates/xrce-agent/src/daemon/binary_forms.rs::tests::writer_binary_of_annex_a_with_ownership_strength, crates/xrce-agent/src/daemon/binary_forms.rs::tests::writer_binary_of_annex_a_with_qos
Status: done — the XCDR2 forms read ownership_strength as an unsigned long; the classic CDR structure of eProsima reads 64 bits. The test reads a present ownership_strength in an XCDR2 blob in both byte orders (ffa5e2770b1).
### Annex A OBJK_DataReader_Binary_Qos
Spec: Annex A, p. 110 — “@extensibility(FINAL) struct OBJK_DataReader_Binary_Qos : OBJK_Endpoint_Binary_Qos { @optional unsigned long timebasedfilter_msec; @optional string contentbased_filter; };”
Repo: crates/xrce-agent/src/daemon/binary_forms.rs (endpoint_qos,
EndpointQosBinary::timebasedfilter_msec, contentbased_filter);
crates/xrce-agent/src/daemon/entity_repr.rs (apply_endpoint_binary)
Tests: crates/xrce-agent/src/daemon/binary_forms.rs::tests::reader_binary_of_the_clause,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_clause_binary_reader_names_its_topic_and_qos,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_annex_b_binary_examples_read_as_their_qos
Status: done — Commits f548fee2522, b91241aebb1. timebasedfilter_msec is read
as an unsigned long (value 50 in the test), contentbased_filter as a
string (“x>100” in the example B.2.7). The classic CDR structure of eProsima
remains as the fallback.
Annex A OBJK_DataWriter_Binary
Spec: Annex A, p. 110–111 — “@extensibility(APPENDABLE) struct OBJK_DataWriter_Binary { string topic_name; @optonal OBJK_DataWriter_Binary_Qos qos; };”
Repo: crates/xrce-agent/src/daemon/binary_forms.rs (endpoint,
EndpointBinary); crates/xrce-agent/src/daemon/entity_repr.rs (endpoint)
Tests: crates/xrce-agent/src/daemon/binary_forms.rs::tests::writer_binary_of_annex_a_with_qos,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::an_annex_a_binary_writer_names_its_topic_and_qos,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_captured_binary_writer_is_reliable_keep_last_transient_local,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_blob_of_no_form_is_refused_naming_each_reading
Status: done — Commits f548fee2522, b91241aebb1. three forms are read in this
order: Annex A (DHEADER, topic_name, @optional qos), the form of §7.7.3.10.2
(no DHEADER, endpoint_qos as a mandatory member) and the classic CDR structure
of eProsima (ObjectId of the topic instead of topic_name). A blob in no form
is refused; the message names the result of each form.
Annex A OBJK_DataReader_Binary
Spec: Annex A, p. 110 — “@extensibility(APPENDABLE) struct OBJK_DataReader_Binary { string topic_name; @optional OBJK_DataReader_Binary_Qos qos; };”
Repo: crates/xrce-agent/src/daemon/binary_forms.rs (endpoint with
writer = false); crates/xrce-agent/src/daemon/entity_repr.rs (endpoint)
Tests: crates/xrce-agent/src/daemon/binary_forms.rs::tests::reader_binary_of_the_clause,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_clause_binary_reader_names_its_topic_and_qos,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_annex_b_binary_examples_read_as_their_qos,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_captured_binary_reader_is_reliable_keep_last_transient_local
Status: done — Commits f548fee2522, b91241aebb1. the same three forms as for
the DataWriter; Annex A with a filter is read through B.2.7, the form of the
clause through the test with depth 5 and timebasedfilter_msec 50.
Annex A ObjectVariant with OBJK_AGENT and OBJK_CLIENT
Spec: Annex A, p. 111 — “@extensibility(FINAL) union ObjectVariant switch(ObjectKind) { // case OBJK_INVALID : indicates default or selected by Agent. No data. case OBJK_AGENT : AGENT_Representation client; case OBJK_CLIENT : CLIENT_Representation client; […] };”
Repo: crates/xrce/src/object_info.rs (ObjectConfig::Agent,
ObjectConfig::Client, ObjectInfo::config); crates/xrce-agent/src/daemon/session.rs
(agent_object_info, client_object_info)
Tests: crates/xrce/src/object_info.rs::tests::the_config_of_the_agent_is_its_agent_representation,
crates/xrce/src/submessages/get_info.rs::tests::client_info_follows_the_info_mask,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_the_agent_checks_the_version_in_client_info
Status: done — Commits ca0cf7e08bf. the cases OBJK_AGENT and OBJK_CLIENT
are in ObjectConfig, the config of ObjectInfo (INFO) and the client_info
of GET_INFO; the kind octet and the representation follow each other. The
ObjectVariant enum for CREATE does not have these two cases: a representation
of kind Agent or Client is not read there. Both members are called client in
the IDL; this has no effect on the wire.
Annex A ActivityInfoVariant with case OBJECTID_AGENT
Spec: Annex A, p. 113 — “@extensibility(FINAL) union ActivityInfoVariant switch (ObjectKind) { case OBJECTID_AGENT : AGENT_ActivityInfo agent; case OBJK_DATAWRITER : […] case OBJK_DATAREADER : […] };”
Repo: crates/xrce/src/object_info.rs (ActivityInfoVariant,
ActivityInfoVariant::discriminator: Agent 0x0D, DataWriter 0x05, DataReader
0x06)
Tests: crates/xrce/src/object_info.rs::tests::agent_activity_info_has_a_dheader_and_a_locator_sequence,
crates/xrce/src/object_info.rs::tests::data_reader_activity_info_is_a_dheader_and_a_short,
crates/xrce/src/object_info.rs::tests::data_writer_activity_info_is_a_dheader_a_long_long_and_a_short
Status: done — Commits ca0cf7e08bf. the discriminator is an ObjectKind (one
octet); OBJECTID_AGENT is an ObjectId of two octets and no value of
ObjectKind, so the text of Annex A cannot be taken literally. The case of the
agent has the discriminator OBJK_AGENT (0x0D). The members carry the DHEADER
(AGENT_ActivityInfo: availability, address_seq as a
TransportLocatorSeq).
Annex A FORMAT_MASK = 0x0E
Spec: Annex A, p. 114 — “const DataFormat FORMAT_MASK = 0x0E; // 0b0000 1110”
Repo: crates/xrce/src/submessages/write_data.rs
(DataFormat::FORMAT_MASK, DataFormat::from_flag_bits)
Tests: crates/xrce/src/submessages/write_data.rs::tests::write_data_rejects_reserved_format,
crates/xrce/src/submessages/write_data.rs::tests::data_format_raw_roundtrip,
crates/xrce/src/submessages/read_data.rs::tests::the_data_format_octet_has_the_values_of_annex_a
Status: done
Annex A SampleInfo with SampleInfoDetail
Spec: Annex A, p. 114–115 — “typedef octet SampleInfoFormat; const SampleInfoFormat FORMAT_EMPTY = 0x00; […] FORMAT_SEQNUM = 0x01; […] FORMAT_TIMESTAMP = 0x02; […] FORMAT_SEQN_TIMS = 0x03; […] struct SeqNumberAndTimestamp { unsigned long sequence_number; unsigned long session_time_offset; }; union SampleInfoDetail switch(SampleInfoFormat) { case FORMAT_EMPTY: case FORMAT_SEQNUM: unsigned long sequence_number; case FORMAT_TIMESTAMP: unsigned long session_time_offset; case FORMAT_TIMESTAMP: SeqNumberAndTimestamp seqnum_n_timestamp; }; struct SampleInfo { SampleInfoFlags state; SampleInfoDetail detail; };”
Repo: crates/xrce/src/sample_info.rs (SampleInfo, info_format); crates/xrce/src/encoding.rs (SampleInfoForm)
Tests: crates/xrce/src/sample_info.rs::tests::the_union_of_annex_a_is_read_by_its_discriminator, crates/xrce/src/sample_info.rs::tests::the_flat_form_ignores_the_padding_octet
Status: done — SampleInfo is the state with the SampleInfoDetail union of Annex A: FORMAT_EMPTY, FORMAT_SEQNUM, FORMAT_TIMESTAMP, FORMAT_SEQN_TIMS. The union gives the case FORMAT_TIMESTAMP twice and lets FORMAT_EMPTY fall through to FORMAT_SEQNUM; the intended reading is used (nothing, sequence number, offset, both). FORMAT_SEQN_TIMS is the 12 octets of the flat struct of §7.7.1 and of the figures of Annex B.5.3 to B.5.5, the discriminator in the first padding octet. The default is SampleInfoForm::AnnexA; the flat form (sample_info: flat) is for a client that sends zeros as padding (the union reads them as FORMAT_EMPTY). 5c2466a4563.
### Annex A ACKNACK_Payload with unsigned short
Spec: Annex A, p. 119 — “struct ACKNACK_Payload { unsigned short first_unacked_seq_num; octet nack_bitmap[2]; octet stream_id; };”
Repo: crates/xrce/src/submessages/acknack.rs (AckNackPayload,
encode_body, decode_body)
Tests: crates/xrce/src/submessages/acknack.rs::tests::acknack_le_roundtrip,
crates/xrce/src/submessages/acknack.rs::tests::acknack_be_roundtrip,
crates/xrce/tests/unannotated_types.rs::the_default_is_appendable_with_a_dheader,
crates/xrce/tests/unannotated_types.rs::the_final_setting_writes_the_reference_implementations_octets,
crates/xrce/src/reliable.rs::tests::acknack_retransmit_of_lost_sample_across_wrap
Status: done — Commits 7f85e76debd. §8.3.5.11.2 writes short; the bytes of the
field are the same. In Annex A the structure carries no @extensibility: it is
APPENDABLE and has a DHEADER in the default (9 octets); the 5 octets of the
reference agent are written by unannotated_types: final, both forms are read.
The code holds the field as i16 and calculates with SerialNumber16.
Annex A HEARTBEAT_Payload with unsigned short
Spec: Annex A, p. 119 — “@extensibility(FINAL) struct HEARTBEAT_Payload { unsigned short first_unacked_seq_num; unsigned short last_unacked_seq_num; octet stream_id; };”
Repo: crates/xrce/src/submessages/heartbeat.rs (HeartbeatPayload,
encode_body, decode_body)
Tests: crates/xrce/src/submessages/heartbeat.rs::tests::heartbeat_le_roundtrip,
crates/xrce/src/submessages/heartbeat.rs::tests::heartbeat_be_roundtrip,
crates/xrce/src/reliable.rs::tests::heartbeat_window_across_wrap_reports_rfc1982_order
Status: done — the structure is explicitly @extensibility(FINAL), the
body has 5 octets without a DHEADER. §8.3.5.12.2 writes short first_unacked_seq_nr
and short last_unacked_seq_nr; the bytes are the same.
Annex B Example Messages (Non-Normative)
Annex B.1 CREATE_CLIENT
Spec: Annex B.1, p. 121–122 — CREATE_CLIENT of vendor_id {0x0F, 0x0F},
client_key {0x22, 0x33, 0x44, 0x55}, session_id 0xDD; header {0x80, 0x00,
0x00, 0x00}, bytes 8–21 CLIENT_Representation, byte 21 “properties? =
FALSE”.
Repo: crates/xrce/src/handshake.rs (ClientRepresentation::encode);
crates/xrce/src/submessages/create_client.rs (CreateClientPayload)
Tests: crates/xrce/src/submessages/create_client.rs::tests::annex_b_1_create_client_example_bytes,
crates/xrce/src/handshake.rs::tests::the_prose_form_has_a_time_t_after_the_vendor_id
Status: done — Commits be97b3247a6, f8bdf3cd878. the test reproduces the header
and bytes 8–21. The text names request_id and client_timestamp, which the
layout does not contain; with the setting representation_timestamps: present
the code writes the Time_t of the text, and the second test checks that form
with the values of the example. CREATE_CLIENT has no flags 0x07 (“reuse,
replace”); submessageLength reads “26 = 0x001B”, the body has 14 bytes.
Annex B.2.1 DomainParticipant with REPRESENTATION_BY_REFERENCE
Spec: Annex B.2.1, p. 123–125 — CREATE with OBJK_PARTICIPANT,
REPRESENTATION_BY_REFERENCE, reference “MyLibrary::MyParticipant” (25 bytes
with NUL), domain_id 0.
Repo: crates/xrce/src/object_repr.rs (ObjectVariant::encode_for_kind,
ObjectVariant::decode_for_kind_at)
Tests: crates/xrce/src/object_repr.rs::tests::participant_representation_matches_the_captured_create_bytes
Status: n/a (informative) — example. The test checks the form from the
capture of eProsima: length at bytes 16–19, characters from byte 20. The example
puts the length at bytes 16–19 and the characters at bytes 24–48; bytes 20–23
are not explained, the code does not read the bytes of the example.
submessageLength reads 26, the payload has 44 bytes. The text refers to
Table 20 instead of Table 18.
Annex B.2.2 DomainParticipant with REPRESENTATION_IN_BINARY
Spec: Annex B.2.2, p. 125–127 — “Bytes 16-19 DHEADER of
OBJK_DomainParticipant_Binary (because extensibility is APPENDABLE) Encodes the
endianness and length […] 0x80000002 = {0x02, 0x00, 0x00, 0x80}”, then two
octets for the @optional members and domain_id.
Repo: crates/xrce/src/object_repr.rs (ObjectVariant::decode_for_kind_at);
crates/xrce-agent/src/daemon/binary_forms.rs (participant)
Tests: crates/xrce/src/object_repr.rs::tests::annex_b_2_2_participant_variant,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_spec_binary_participant_is_read
Status: done — Commits b91241aebb1, f548fee2522. the DHEADER 0x80000002 stands
where eProsima sends the length of binary_representation; the code reads it
there as a DHEADER (bit 31 is no part of the length), followed by the two
@optional octets and the domain_id.
Annex B.2.3 DataWriter with REPRESENTATION_IN_BINARY
Spec: Annex B.2.3, p. 127–129 — DHEADER 0x8000000C, topic_name “Square”
(7 bytes with NUL), qos? = 0, publisher_id {0xBB, 0xB3}.
Repo: crates/xrce/src/object_repr.rs (ObjectVariant::decode_for_kind_at);
crates/xrce-agent/src/daemon/binary_forms.rs (endpoint)
Tests: crates/xrce/src/object_repr.rs::tests::annex_b_2_3_writer_variant_reads_as_the_blob_and_its_publisher,
crates/xrce-agent/src/daemon/binary_forms.rs::tests::writer_binary_of_annex_a_with_qos
Status: done — Commits f548fee2522. the blob with topic_name and qos? = 0 and
the publisher_id after it are read. The text calls the publisher
subscriber_id.
Annex B.2.4 DataWriter with QoS
Spec: Annex B.2.4, p. 129–132 — “RELIABILITY policy set to BEST_EFFORT,
HISTORY policy set to KEEP_ALL and DEADLINE policy set to a period of 2
minutes”; “qos_flags = 0x0003 Indicates the flags for is_reliable and
is_history_keep_all are both set.”; byte 34 history_depth?, byte 35
padding, bytes 36–39 deadline = 120000.
Repo: crates/xrce/src/object_repr.rs (ObjectVariant::decode_for_kind_at);
crates/xrce-agent/src/daemon/entity_repr.rs (endpoint)
Tests: crates/xrce/src/object_repr.rs::tests::annex_b_2_4_writer_with_qos_in_both_readings_of_the_padding,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_annex_b_binary_examples_read_as_their_qos,
crates/xrce-agent/src/daemon/binary_forms.rs::tests::writer_binary_of_annex_a_with_qos
Status: done — Commits b91241aebb1. read as XCDR2 of the printed IDL. Byte 35,
which the table calls padding, is the octet for @optional deadline_msec (1);
the value starts at byte 36. The padding byte 43 before publisher_id is read
both counted in the DHEADER (24) and outside it (23). The text names
BEST_EFFORT, qos_flags 0x0003 and the table set is_reliable; the bytes are
read.
Annex B.2.5 DataWriter with REPRESENTATION_AS_XML_STRING
Spec: Annex B.2.5, p. 132–134 — <data_writer name="MyWriter" topic_ref="Square"><data_writer_qos base_name="MyQosLib::MyProfile"> <deadline>[...]</deadline></data_writer_qos></data_writer>, length 181,
publisher_id at bytes 201–202.
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (endpoint_from_xml:
topic_ref as a name, <data_writer_qos> and <datawriter_qos> with
base_name)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_data_writer_states_its_qos_over_a_profile
Status: n/a (informative) — example. The code resolves topic_ref="Square"
as a name and reads <data_writer_qos base_name="…"> over a profile of the
agent (9d5c64dc398); the test has the form of the example, not its bytes. In
the figure the discriminator is 0x01, in Table 22 0x02; the text names 180 and
181 characters and “MyQosLib:MyProfile” with one colon.
Annex B.2.6 DataReader with REPRESENTATION_IN_BINARY
Spec: Annex B.2.6, p. 134–136 — DataReader “Square” with DHEADER,
topic_name, qos? = 0, subscriber_id {0xCC, 0xC4}.
Repo: crates/xrce/src/object_repr.rs (ObjectVariant::decode_for_kind_at);
crates/xrce-agent/src/daemon/entity_repr.rs (endpoint)
Tests: crates/xrce/src/object_repr.rs::tests::annex_b_2_6_reader_with_default_qos,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_annex_b_binary_examples_read_as_their_qos
Status: done — Commits b91241aebb1. the DHEADER 12 (0x8000000C, as in B.2.3) is
read. The text prints the DHEADER as {0xB5, 0x00, 0x00, 0x00}; that does not fit
the 26 octets of the message, the code refuses the printed value. Table 23 sets
the discriminator to 0x05 (OBJK_DATAWRITER) for OBJK_DATAREADER (0x06) and
lists bytes 24–30 twice.
Annex B.2.7 DataReader with QoS and filter
Spec: Annex B.2.7, p. 136–139 — “HISTORY policy set to KE EP_ALL and
DEADLINE policy set to a period of 5 minutes”, qos_flags 0x0002, deadline
180000, contentbased_filter “x>100”.
Repo: crates/xrce/src/object_repr.rs (ObjectVariant::decode_for_kind_at);
crates/xrce-agent/src/daemon/entity_repr.rs (endpoint)
Tests: crates/xrce/src/object_repr.rs::tests::annex_b_2_7_reader_with_qos_and_filter,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_annex_b_binary_examples_read_as_their_qos
Status: done — Commits b91241aebb1. read as XCDR2 of the printed IDL; byte 35 is
the octet for deadline_msec, no padding byte stands before the
subscriber_id. 180000 ms are 3 minutes (read), the text names 5; the figure and
Table 24 name publisher_id instead of subscriber_id at the end.
Annex B.3.1 WRITE_DATA with one sample
Spec: Annex B.3.1, p. 139–141 — flags 0x01, submessageLength 6, bytes 8–13
{0xAA, 0x01, 0x44, 0x05, 0x19, 0x00}.
Repo: crates/xrce/src/submessages/write_data.rs (WriteDataPayload)
Tests: crates/xrce/src/submessages/write_data.rs::tests::write_data_matches_the_annex_b_example
Status: done — the test reproduces flags, length and body byte for byte.
Table 25 is called “READ_DATA (single sample)”.
Annex B.3.2 WRITE_DATA with a sequence without SampleInfo
Spec: Annex B.3.2, p. 141–143 — flags 0x09, data_seq.length = 4, four
short {0x14, 0x00}, {0x11, 0x00}, {0x1A, 0x00}, {0x24, 0x00}.
Repo: crates/xrce/src/submessages/write_data.rs; crates/xrce/src/submessages/data.rs; crates/xrce/src/submessages/read_data.rs; crates/xrce/src/sample_info.rs
Tests: crates/xrce/tests/annex_b_examples.rs::b_3_2_write_data_with_a_sequence_without_sample_info
Status: done — the example is tested with its bytes: id 0x07, flags 0x09, length 16 (the figure prints the length 6 of B.3.1), four values 20, 17, 26, 36 (5c2466a4563). ### Annex B.3.3 WRITE_DATA with timestamp
Spec: Annex B.3.3, p. 143–146 — “Byte 12 info.state = 0x00 […] Byte 13 info.detail.discriminator = FORMAT_TIMESTAMP Bytes 14-15 padding Bytes 16-19 info. Detail.session_time_offset Bytes 20-21 serialized_data”.
Repo: —
Tests: —
Status: n/a (informative) — example in the form of Annex A with
SampleInfoDetail. The form of Annex A is item “Annex A SampleInfo with
SampleInfoDetail”. submessageLength reads “13 = 0x000D” with {0x06, 0x00},
the body has 14 bytes.
Annex B.3.4 WRITE_DATA with a disposed sample
Spec: Annex B.3.4, p. 146–148 — “Byte 12 info.state = 0x02 […] Byte 13 Info.detail.discriminator = FORMAT_NONE […] Bytes 14-19 Serialized_data”.
Repo: —
Tests: —
Status: n/a (informative) — example in the form of Annex A (as for B.3.3). The figure and the table name FORMAT_EMPTY and
FORMAT_NONE; submessageLength reads 6, the body has 12 bytes.
Annex B.4.1 READ_DATA for one sample
Spec: Annex B.4.1, p. 148–150 — “submessageId = READ_DATA = 0x07”, flags
0x01, “submessageLength = 7”, byte 12 preferred_stream_id 0x00, byte 13
data_format 0x00, bytes 14 and 15 the octets for @optional = 0.
Repo: crates/xrce/src/submessages/write_data.rs; crates/xrce/src/submessages/data.rs; crates/xrce/src/submessages/read_data.rs; crates/xrce/src/sample_info.rs
Tests: crates/xrce/tests/annex_b_examples.rs::b_4_1_read_data_for_a_sample
Status: done — the example is tested with all eight octets of the payload; id 0x08 (the figure prints 0x07), length 8 (the figure prints 7) (5c2466a4563). ### Annex B.4.2 READ_DATA with filter and DataDeliveryControl
Spec: Annex B.4.2, p. 150–153 — data_format 0x08, content_filter
“x>100” with length 6, DHEADER 0x80000008, max_samples 100,
max_elapsed_time 30000, max_rate 1024 “{0x00, 0x40}”, min_pace_period
1000.
Repo: crates/xrce/src/submessages/read_data.rs (ReadDataPayload,
ReadSpecification, DataDeliveryControl)
Tests: crates/xrce/src/submessages/read_data.rs::tests::annex_b_4_2_read_data_with_filter_and_delivery_control,
crates/xrce/src/submessages/read_data.rs::tests::the_content_filter_is_a_string_with_a_nul_and_an_aligned_length
Status: done — Commits b589558e671. data_format 0x08 (FORMAT_DATA_SEQ),
content_filter_expression as an XCDR2 string, DataDeliveryControl with a
DHEADER; the test reads the bytes of the figure (bit 31 of the DHEADER is no
part of the length) and writes the plain DHEADER 8. Table 30 puts the DHEADER
and max_samples both at bytes 28–29; for 1024 the text prints {0x00, 0x40},
little-endian it is {0x00, 0x04}; byte 14 and byte 26 read “set to FALSE
indicating there it is present”. The form without a DHEADER is written by
XrceClient::set_delivery_control_form(DeliveryControlForm::Bare).
Annex B.5.1 DATA with one sample
Spec: Annex B.5.1, p. 154–155 — flags 0x00 (big-endian),
submessageLength 8, FooType.count = 19 as {0x00, 0x00, 0x00, 0x13}.
Repo: crates/xrce/src/submessages/write_data.rs; crates/xrce/src/submessages/data.rs; crates/xrce/src/submessages/read_data.rs; crates/xrce/src/sample_info.rs
Tests: crates/xrce/tests/annex_b_examples.rs::b_5_1_data_with_one_sample
Status: done — the example (big-endian, flags 0x00) is decoded with its bytes and re-encoded (5c2466a4563).
### Annex B.5.2 DATA with a sequence without SampleInfo
Spec: Annex B.5.2, p. 155–157 — submessageLength 16, data_seq.length = 2,
two long.
Repo: crates/xrce/src/submessages/write_data.rs; crates/xrce/src/submessages/data.rs; crates/xrce/src/submessages/read_data.rs; crates/xrce/src/sample_info.rs
Tests: crates/xrce/tests/annex_b_examples.rs::b_5_2_data_with_a_sequence_without_sample_info
Status: done — the example is tested: id 0x09 (the figure prints 0x08), flags 0x08 (E flag clear, FORMAT_DATA_SEQ; the figure prints 0x00), sequenceNr {0x0A,0x00} = 10 (the text says 1), request_id {AA,01} by the table (the text says {AA,02}) (5c2466a4563).
### Annex B.5.3 DATA with one sample and SampleInfo
Spec: Annex B.5.3, p. 157–159 — IDL with SampleInfoDetail; figure: “info.state
| info.sequence_number | info.session_time_offset | XCDR_Serialization(foo)”.
Repo: crates/xrce/src/submessages/data.rs (DataPayloadSample);
crates/xrce/src/sample_info.rs (SampleInfo)
Tests: crates/xrce/src/submessages/data.rs::tests::data_sample_matches_annex_b_5_3_layout,
crates/xrce/src/sample_info.rs::tests::sample_info_matches_annex_b_5_3_layout,
crates/xrce-agent/src/daemon/session.rs::tests::a_read_for_sample_is_answered_with_a_sample_each
Status: done — the tests reproduce the figure of the example. The figure
has the form of §7.7.1, the IDL above it that of Annex A (item “Annex A
SampleInfo with SampleInfoDetail”).
Annex B.5.4 DATA with a sequence with SampleInfo
Spec: Annex B.5.4, p. 159–161 — submessageLength 40, sample_seq.length
= 2, per element info (12 bytes) and data (4 bytes).
Repo: crates/xrce/src/submessages/write_data.rs; crates/xrce/src/submessages/data.rs; crates/xrce/src/submessages/read_data.rs; crates/xrce/src/sample_info.rs
Tests: crates/xrce/tests/annex_b_examples.rs::b_5_4_data_with_a_sequence_with_sample_info
Status: done — the example is tested with the 12 octets of the SampleInfo per element (length 40; flags 0x0A instead of 0x00; SampleInfoForm::Flat) (5c2466a4563).
### Annex B.5.5 DATA with PackedSamples
Spec: Annex B.5.5, p. 161–163 — submessageLength 36, info_base (12
bytes), sample_delta_seq.length = 2, per element info_delta (4 bytes) and
data (4 bytes).
Repo: crates/xrce/src/submessages/write_data.rs; crates/xrce/src/submessages/data.rs; crates/xrce/src/submessages/read_data.rs; crates/xrce/src/sample_info.rs
Tests: crates/xrce/tests/annex_b_examples.rs::b_5_5_data_with_packed_samples
Status: done — the example is tested after the figure: request_id/object_id, info_base (12), count, two SampleInfoDelta with data, 36 octets; Table 34 lists info_base at bytes 8 to 19 without request_id and object_id, which fits neither (5c2466a4563).
Annex C Additional Transport Mappings
Annex C.1 Framing according to RFC 1662 for serial lines
Spec: Annex C.1, p. 165 — “This section normalizes the communication over serial protocols such as SPI, I2C or RS-232. For this propose, the XRCE Messages are framed using an HDLC-like framing similar to [IETF RFC-1662]. This framing is designed to meet all the functionality listen in clause 11.1, except that it does not provide security.”
Repo: crates/xrce/src/transport_serial.rs (encode_frame_with, SerialFramer);
crates/xrce-agent/src/daemon/transport.rs (SerialLine::take_frame, serial::run_serial_listener,
feature serial)
Tests: crates/xrce/src/transport_serial.rs::tests::the_framer_takes_frames_split_and_back_to_back_and_skips_noise,
crates/xrce-agent/src/daemon/transport.rs::tests::the_clients_of_a_serial_line_are_told_apart_by_their_address
Status: done — Commits 8dae8498ba1. frames after C.1.1 to C.1.3 in
zerodds-xrce, the agent and the endpoint SDKs (C, C++, Java, Python,
Ada-native). Micro-XRCE-DDS 3.0.1 frames the same way but computes
frameCheck as CRC-16/ARC over the payload alone (StreamFramingProtocol.cpp,
stream_framing_protocol.c, read from the source); the agent takes and makes
those frames with frame_check: crc16-arc-payload
(FrameCheck::Crc16ArcPayload). Not measured against a Micro-XRCE-DDS client
over a line.
Annex C.1.1 Structure of the frame
Spec: Annex C.1.1, p. 165 — “flag | sourceAddress | remoteAddress |
payloadLength | payload (up to 64KB) | frameCheck”, one octet each for flag
and the two addresses, 16 bits for payloadLength and frameCheck.
Repo: crates/xrce/src/transport_serial.rs (encode_frame_with, FrameAssembler::push)
Tests: crates/xrce/src/transport_serial.rs::tests::a_frame_carries_the_addresses_the_length_and_a_little_endian_check
Status: done — 7E | sourceAddress | remoteAddress | payloadLength | payload | frameCheck; the frame ends after payloadLength octets of payload
and two octets of frameCheck.
Annex C.1.1.1 BEGIN_FLAG 0x7E
Spec: Annex C.1.1.1, p. 165 — “Each frame begins with a BEGIN_FLAG byte which has a hexadecimal value of 0x7E.”
Repo: crates/xrce/src/transport_serial.rs (FLAG_BYTE, encode_frame_with)
Tests: crates/xrce/src/transport_serial.rs::tests::a_frame_carries_the_addresses_the_length_and_a_little_endian_check
Status: done
Annex C.1.1.2 sourceAddress
Spec: Annex C.1.1.2, p. 165 — “The sourceAddress indicates the address of the frame sender.”
Repo: crates/xrce/src/transport_serial.rs (SerialFrame::source); crates/xrce-agent/src/daemon/transport.rs (PeerTable::resolve_on_line,
bind_line)
Tests: crates/xrce-agent/src/daemon/transport.rs::tests::the_clients_of_a_serial_line_are_told_apart_by_their_address
Status: done — the agent sends with its address (address:, default 0,
the address the Micro-XRCE-DDS examples send to). A frame belongs to the
client its header or CREATE_CLIENT names, else to the one registered from its
sourceAddress.
Annex C.1.1.3 remoteAddress
Spec: Annex C.1.1.3, p. 165 — “The remoteAddress indicates the address of the frame recipient.”
Repo: crates/xrce/src/transport_serial.rs (SerialFrame::remote); crates/xrce-agent/src/daemon/transport.rs (SerialLine::take_frame,
Route::Serial)
Tests: crates/xrce-agent/src/daemon/transport.rs::tests::the_clients_of_a_serial_line_are_told_apart_by_their_address
Status: done — the agent takes only frames to its address; its messages to a client carry that client’s address.
Annex C.1.1.4 payloadLength little-endian
Spec: Annex C.1.1.4, p. 166 — “The payloadLength indicates the length of the payload field in bytes, that is, the XRCE Message. The payloadLength shall be encoded using little endian format.”
Repo: crates/xrce/src/transport_serial.rs (encode_frame_with, FrameAssembler::push)
Tests: crates/xrce/src/transport_serial.rs::tests::a_frame_carries_the_addresses_the_length_and_a_little_endian_check
Status: done
Annex C.1.1.5 payload is an XRCE message
Spec: Annex C.1.1.5, p. 166 — “The payload shall contain an XRCE Message.”
Repo: crates/xrce/src/transport_serial.rs (encode_message, decode_frame,
SerialFramer::push_bytes)
Tests: crates/xrce/src/transport_serial.rs::tests::the_framer_takes_frames_split_and_back_to_back_and_skips_noise,
crates/xrce/src/transport_serial.rs::tests::decode_frame_returns_the_rest_after_the_frame
Status: done — the limit is 65 535 octets, what payloadLength holds;
encode_frame refuses a longer payload with FrameTooLong.
Annex C.1.1.6 frameCheck according to RFC 1662
Spec: Annex C.1.1.6, p. 166 — “The frameCheck shall contain the 16-bits cyclic redundancy check (CRC) of the original frame without including the BEGIN_FLAG or transparency stuffing. The frameCheck shall be computed as it is described in [IETF RFC-1662] using the polynomials: x 16 + x 12 + x 5 + 1.”
Repo: crates/xrce/src/transport_serial.rs (fcs16, FrameCheck::compute)
Tests: crates/xrce/src/transport_serial.rs::tests::the_frame_check_is_the_fcs16_of_rfc_1662,
crates/xrce/src/transport_serial.rs::tests::a_frame_carries_the_addresses_the_length_and_a_little_endian_check
Status: done — FCS-16 of RFC 1662 (reflected 0x8408, init 0xFFFF,
complemented) over addresses, payloadLength and payload; 0x906E for
“123456789”, the check value of RFC 1662 Appendix C.
Annex C.1.1.6 frameCheck little-endian
Spec: Annex C.1.1.6, p. 166 — “The frameCheck shall be encoded using little endian format.”
Repo: crates/xrce/src/transport_serial.rs (encode_frame_with)
Tests: crates/xrce/src/transport_serial.rs::tests::a_frame_carries_the_addresses_the_length_and_a_little_endian_check
Status: done
Annex C.1.2 Stuffing with ESCAPE_FLAG and XOR_FLAG
Spec: Annex C.1.2, p. 166 — “The ESCAPE_FLAG has a hexadecimal value of 0x7D. Each byte inside the frame which value matches with the BEGIN_FLAG or the ESCAPE_FLAG is replaced by two bytes: the ESCAPE_FLAG followed by the original byte XOR with the XOR_FLAG which has a value of 0x20. […] each ESCAPE_FLAG found shall be discarded and an XOR with the XOR_FLAG operator shall be applied on the next byte.”
Repo: crates/xrce/src/transport_serial.rs (ESCAPE_BYTE, STUFF_XOR, encode_frame_with,
FrameAssembler::push)
Tests: crates/xrce/src/transport_serial.rs::tests::flag_and_escape_octets_are_stuffed_everywhere_after_the_flag,
crates/xrce/src/transport_serial.rs::tests::escape_errors_and_short_frames_are_refused
Status: done — everything after the flag is stuffed, addresses, length and
frameCheck too. After 0x7D the code refuses every byte that does not become
0x7E or 0x7D; the spec does not require that.
Annex C.1.3 Dropping on a wrong CRC
Spec: Annex C.1.3, p. 166 — “A frame shall be dropped in the following cases: When the frameCheck attached to the frame is not the same as the computed CRC.”
Repo: crates/xrce/src/transport_serial.rs (FrameAssembler::push); crates/xrce-agent/src/daemon/transport.rs
(run_serial_listener: message “frame dropped” with the reason)
Tests: crates/xrce/src/transport_serial.rs::tests::a_frame_with_a_wrong_check_is_refused,
crates/xrce/src/transport_serial.rs::tests::the_frame_check_of_micro_xrce_dds_is_taken_when_chosen
Status: done
Annex C.1.3 Dropping on a BEGIN_FLAG before the end of the payload
Spec: Annex C.1.3, p. 166 — “When a (non escaped) BEGIN_FLAG is found before the payload is completely read.”
Repo: crates/xrce/src/transport_serial.rs (SerialFramer::push_bytes, decode_frame_inner_with)
Tests: crates/xrce/src/transport_serial.rs::tests::a_begin_flag_inside_a_frame_drops_it_and_begins_the_next
Status: done — the frame is dropped with BeginFlagInFrame, and the flag
begins the next frame.
Audit-Status
490 done / 0 partial / 2 open / 0 blocked / 77 n/a (informative).
Forms of other DDS products in DDS-XML: the readers of crates/xml follow the schemas of DDS-XML 1.0 and refuse a foreign form (<domainparticipant_qos>, the qos_profile_ref attribute, baseType, the IDL names long and octet as type, and others) with an error that names the form and the specification’s. The agent setting vendor_forms: accept reads them (needed for profile files of eProsima) and lists each form read at start; the default is refuse. This is checked only by reading the code and the tests; nothing was run on this machine.
Open items: dds-xrce-1.0.open.en.md.
DDS-XRCE 1.0 — Spec-Coverage
Quelle: internal/standards/cache/omg/dds-xrce-1.0.pdf (166 Seiten, OMG formal/2020-02-01) —
OMG DDS-XRCE 1.0
Audit Item für Item gegen die PDF nach internal/spec-coverage/PROCESS.md.
Seitenangaben sind PDF-Seiten (PDF-Seite = gedruckte Seite + 8). Jedes Feld
der Typen von §7.7 und Annex A, jede Submessage mit Flags und Payload, jede
Prüfung und jeder Rückgabewert der Operationen von §7.8, jede Regel der
Reliable Streams, jede Zeile von Table 5, Table 6 und Table 15 und jede
Abbildung auf einen Transport ist ein eigenes Item. done steht nur, wo Code
und Test die Anforderung abdecken; ein zitierter Test nennt die Testfunktion als
datei::modul::name. Eine Fundstelle im Repo nennt Datei, Symbol und, wo es
hilft, die Zeile (Z.); die Zeilen beziehen sich auf den Stand, mit dem diese
Datei eingecheckt wurde (Zeilenangaben sind nur noch dort genannt, wo sie
helfen). Jede Aussage über Verhalten ist aus dem Code gelesen; die zitierten
Tests liefen auf dem Linux-Testhost, dieses Audit führt keinen Test aus. Wo
Code eine Anforderung abbildet, aber kein Test sie prüft, ist das Item
partial und die Notiz nennt, welcher Test fehlt.
Kontext: DDS-XRCE ist in ZeroDDS über diese Teile verteilt:
crates/xrce/· docs.rs — Codec der Nachrichten (MessageHeader,Submessage, die 16 Payloads), die Typen von §7.7 (ObjectId,ObjectVariant,ResultStatus,ObjectInfo,SampleInfo,TransportLocator),CLIENT_RepresentationundAGENT_Representation(handshake), Reliable Streams (reliable), Fragmentierung (fragment), fortgesetztes Lesen (continuous_read), der Objektspeicher je Client (object_store), Transporte für UDP, TCP und eine serielle Leitung (transport_*), DTLS und TLS hinter den Featuresdtlsundtls, ein Erzeuger von CREATE-Nachrichten aus einer XML-Datei (xml_config).crates/xrce-agent/· docs.rs —XrceAgent(Registry der Clients, Objektspeicher, Warteschlange der Samples je Reader); unter dem Featuredaemondie Sitzungslogik (daemon::session::SessionEngine), das Lesen der Repräsentationen (daemon::entity_repr), Profile (daemon::profiles), die Anbindung anzerodds-dcps(daemon::dcps_bridge::RealDdsPort), Listener für UDP, TCP und seriell (daemon::transport), Discovery (daemon::discovery) und das Binaryzerodds-xrce-agentd.crates/xrce-client/· docs.rs —XrceClient, ein synchroner Client über dem TraitClientTransport.crates/endpoint-e2e/tests/xrce_write_framing.rs— prüft die WRITE_DATA-Rahmen der Endpoint-SDKs weiterer Sprachen gegen den Codec voncrates/xrce.
Die Spec definiert keine Programmierschnittstelle des Clients (§8.1, S. 57: “Do not have a standard API”). Die Endpoint-SDKs der Sprachen sind deshalb nicht als Items geführt; die C-API von ZeroDDS hat keine Funktionen für XRCE.
Mehrere Strukturen haben in §7/§8 und in Annex A verschiedene Formen
(CLIENT_Representation, SampleInfo, die Binärformen der Objekte u. a.). Das
Item nennt die Form, nach der der Code richtet; die Form der anderen Stelle
steht als eigenes Item. Wo der Code der Form folgt, die eProsima
Micro-XRCE-DDS 3.0.1 sendet, beruht das auf dem Mitschnitt unter
tools/wire-capture/xrce-sessions/; ein Lauf gegen einen eProsima-Agent oder
-Client ist nicht Teil dieses Audits.
Die Spec nennt dds_xrce_types.idl und dds_xrce_model.xmi als normative
maschinenlesbare Dateien (S. 1). Sie liegen nicht im Cache; ein Abgleich mit
ihnen fehlt.
Offene Punkte: keine.
§1 Scope
§1 Scope
Spec: §1, S. 11 — “This specification defines an XRCE Protocol between a resource constrained, low-powered device (client) and an Agent (the server). […] The specification’s purpose and scope are to ensure that applications based on different vendors’ implementations of the XRCE Protocol and XRCE Agent are compatible and interoperable.”
Repo: —
Tests: —
Status: n/a (informative) — Übersicht; Protokoll und Agent sind ab §7
einzeln geführt.
§2 Conformance
§2 Zehn Profile als Konformitätspunkte
Spec: §2, S. 12 — “This specification defines ten profiles. Each constitutes a separate conformance point”.
Repo: —
Tests: —
Status: n/a (informative) — Zuordnung; ob ein Profil erfüllt ist, folgt
aus dem Status der zugeordneten Items. Die Tests in
crates/xrce/tests/profile_conformance.rs prüfen nur, dass die Werte der
SubmessageId dekodieren; sie belegen kein Verhalten.
§2 Read Access profile
Spec: §2, S. 12 — “Provides the clients the ability to read data on pre-configured Topics with pre-configured QoS policies. Requires implementation of all submessage types except for CREATE, INFO, WRITE_DATA, and DELETE, including the associated behaviors.”
Repo: —
Tests: —
Status: n/a (informative) — Zuordnung: Items zu §8.3.5 (alle Submessages
außer CREATE, INFO, WRITE_DATA, DELETE), §7.8.5, §8.4.3, §8.4.14. GET_INFO ohne
Sitzung und InfoMask (ca0cf7e08bf), die Formate von DATA (fd5253ca805),
MAX_SAMPLES_ZERO (8bcb1d00161) und vorkonfigurierte DataReader (2ba972cd270)
sind in diesen Items geführt.
§2 Write Access profile
Spec: §2, S. 12 — “Provides the clients the ability to write data on pre-configured Topics with pre-configured QoS policies. Requires implementation of all submessage types except for CREATE, INFO, READ_DATA, DATA, and DELETE, including the associated behaviors.”
Repo: —
Tests: —
Status: n/a (informative) — Zuordnung: Items zu §8.3.5, §7.8.4, §8.4.2,
§8.4.14. STATUS auf WRITE_DATA (869304e6b63), die Sequenzformate von WRITE_DATA
(f40bd568ad1) und vorkonfigurierte DataWriter (2ba972cd270) sind in diesen Items
geführt.
§2 Configure Entities profile
Spec: §2, S. 12 — “Provides the clients the ability define DomainParticipant, Topic, Publisher, Subscriber, DataWriter, and DataReader entities using pre-configured QoS policies and data-types. Requires implementation of the CREATE_CLIENT, DELETE_CLIENT, CREATE, and DELETE submessage and the associated behaviors.”
Repo: —
Tests: —
Status: n/a (informative) — Zuordnung: Items zu §7.8.2, §7.8.3, §7.7.3 und
Table 6. Eine Submessage DELETE_CLIENT gibt es in Table 10 nicht;
delete_client läuft über DELETE (§8.3.5.4). Die Prüfung des Participant für
Publisher und Subscriber (505c2e56d24) und die DDS-XML-Formen der
Repräsentationen (9d5c64dc398, b97657ef4ec) sind in diesen Items geführt.
§2 Configure QoS profile
Spec: §2, S. 12 — “Provides client the ability to define QoS profiles to be used by DDS entities. Requires implementation of the CREATE submessage and the associated behaviors for object kind OBJK_QOSPROFILE.”
Repo: —
Tests: —
Status: n/a (informative) — Zuordnung: Items zu §7.7.3.2, Table 6
OBJK_QOSPROFILE und §8.4.7. Die DDS-XML-Form des QosProfile ist umgesetzt
(9d5c64dc398, b97657ef4ec); welche Policies der Agent anwendet, steht in den
Items zu §7.1.
§2 Configure types profile
Spec: §2, S. 12 — “Provides client the ability to explicitly define data types to be used for DDS Topics. Requires implementation of the CREATE submessage and the associated behaviors for object kind OBJK_TYPE.”
Repo: —
Tests: —
Status: n/a (informative) — Zuordnung: Items zu §7.7.3.3, Table 6
OBJK_TYPE und §8.4.8. Der Verweis eines <types> auf Typen, die der Agent schon
kennt (§7.7.3.3.2), ist dort done.
§2 Discovery access profile
Spec: §2, S. 12 — “Provides the clients the ability to discover the Topics and Types available on the DDS Global Data Space. Requires implementation of the GET_INFO and INFO submessage and the associated behaviors.”
Repo: —
Tests: —
Status: n/a (informative) — Zuordnung: Items zu §7.8.2.2, §7.8.3.3,
§8.3.5.3, §8.3.5.7 und §7.7.13. GET_INFO liefert den Agent (auch ohne Sitzung),
die Objekte des Client und die für ihn konfigurierten Objekte (ca0cf7e08bf,
2ba972cd270). Eine Abfrage der Topics und Typen des Global Data Space hat der
Agent nicht; in session.rs, dds_port.rs und dcps_bridge.rs ist kein Code
dafür.
§2 File based configuration profile
Spec: §2, S. 12 — “Provides a standard way to configure the Agent using XML files. Requires implementation of the file-based configuration mechanism described in clause 9.3”.
Repo: —
Tests: —
Status: n/a (informative) — Zuordnung: Items zu §9.3 und Table 15.
§2 UDP Transport profile
Spec: §2, S. 12 — “Implements the mapping of the protocol to the UDP transport. Requires implementing the mechanisms described in clause 11.2 (UDP Transport).”
Repo: —
Tests: —
Status: n/a (informative) — Zuordnung: Items zu §11.2.
§2 TCP Transport profile
Spec: §2, S. 12 — “Implements the mapping of the protocol to the TCP transport. Requires implementing the mechanisms described in clause 11.3 (TCP Transport).”
Repo: —
Tests: —
Status: n/a (informative) — Zuordnung: Items zu §11.3.
§2 Complete profile
Spec: §2, S. 12 — “Complete profile. Requires implementation of the complete specification.”
Repo: —
Tests: —
Status: n/a (informative) — Zuordnung: alle Items dieses Dokuments.
§3 References
§3.1 [IETF RFC-1982] Serial Number Arithmetic
Spec: §3.1, S. 13 — “[IETF RFC-1982] Serial Number Arithmetic.”
Repo: —
Tests: —
Status: n/a (informative) — Literatur; die Anforderung steht im Item zu
§8.3.2.3.
§3.1 [IDL] IDL 4.2
Spec: §3.1, S. 13 — “[IDL] Interface Definition Language (IDL), version 4.2”.
Repo: —
Tests: —
Status: n/a (informative) — Literatur; die Typen von Annex A sind in IDL
geschrieben und als Items zu §7.7 und Annex A geführt.
§3.1 [DDS] DDS 1.4
Spec: §3.1, S. 13 — “[DDS] Data Distribution Service for Real-Time Systems Specification, version 1.4”.
Repo: —
Tests: —
Status: n/a (informative) — Literatur; DDS-Entitäten in den Items zu
Table 6, die Syntax der Filter im Item zu Table 9.
§3.1 [DDS-XML] DDS Consolidated XML Syntax 1.0
Spec: §3.1, S. 13 — “[DDS-XML] DDS Consolidated XML Syntax, version 1.0”.
Repo: —
Tests: —
Status: n/a (informative) — Literatur; die XML-Formen in den Items zu
§7.7.3 und §9.3.
§3.1 [DDS-XTYPES] XTypes 1.2
Spec: §3.1, S. 13 — “[DDS-XTYPES] Extensible And Dynamic Topic Types for DDS, version 1.2”.
Repo: —
Tests: —
Status: n/a (informative) — Literatur; XCDR2 im Item zu §7.7.
§3.1 [UML] 2.5
Spec: §3.1, S. 13 — “[UML] Unified Modeling Language, version 2.5”.
Repo: —
Tests: —
Status: n/a (informative) — Literatur für die Diagramme.
§3.1 [UDP] RFC 768
Spec: §3.1, S. 13 — “[UDP] User Datagram Protocol, IETF RFC 768”.
Repo: —
Tests: —
Status: n/a (informative) — Literatur; die Abbildung in den Items zu
§11.2.
§3.1 [TCP] RFC 793
Spec: §3.1, S. 13 — “[TCP] Transmission Control Protocol, STD 7, IETF RFC 793”.
Repo: —
Tests: —
Status: n/a (informative) — Literatur; die Abbildung in den Items zu
§11.3.
§3.1 [DTLS] RFC 6347
Spec: §3.1, S. 13 — “[DTLS] Datagram Transport Layer Security, version 1.2, IETF RFC 6347”.
Repo: —
Tests: —
Status: n/a (informative) — Literatur; die Spec nennt DTLS in §11.2
(S. 99) als Möglichkeit. crates/xrce/src/transport_dtls.rs (Feature dtls)
ist im Item zu §11.2 genannt.
§3.1 [TLS] RFC 5246
Spec: §3.1, S. 13 — “[TLS] The Transport Layer Security (TLS) Protocol, version 1.2, IETF RFC 5246”.
Repo: —
Tests: —
Status: n/a (informative) — Literatur; die Spec nennt TLS in §11.3
(S. 100–101) als Möglichkeit. crates/xrce/src/transport_tls.rs (Feature
tls) ist im Item zu §11.3 genannt.
§3.1 [IETF RFC-1662] PPP in HDLC-like Framing
Spec: §3.1, S. 13 — “[IETF RFC-1662] PPP in HDLC-like Framing.”
Repo: —
Tests: —
Status: n/a (informative) — Literatur; die Rahmung in den Items zu
Annex C.
§3.2 [SMART] Smart Transducers 1.0
Spec: §3.2, S. 13 — “[SMART] Smart Transducers Specification, version 1.0”.
Repo: —
Tests: —
Status: n/a (informative) — nicht normative Literatur.
§4 Terms and Definitions
§4 Begriffe
Spec: §4, S. 14 — Definitionen von “Data Distribution Service (DDS)”, “DDS Domain”, “DDS DomainParticipant”, “DDS Global Data Space”, “GUID”.
Repo: —
Tests: —
Status: n/a (informative) — Begriffe.
§5 Symbols
§5 Abkürzungen
Spec: §5, S. 15 — DDS, IDL, RTPS, XRCE.
Repo: —
Tests: —
Status: n/a (informative) — Abkürzungen.
§6 Additional Information
§6.1 Changes to Adopted OMG Specifications
Spec: §6.1, S. 16 — “This specification does not change any adopted OMG specification.”
Repo: —
Tests: —
Status: n/a (informative) — Hinweis.
§6.2 Acknowledgements
Spec: §6.2, S. 16 — einreichende Firmen (Real-Time Innovations, eProsima, TwinOaks Computing).
Repo: —
Tests: —
Status: n/a (informative) — Danksagung.
§7.1 General
§7.1 Der Agent ist ein DDS-Participant
Spec: §7.1, S. 17 — “The XRCE Agent is a DDS Participant in the DDS Global Data Space. The DDS-XRCE protocol allows the client to use the XRCE Agent as a proxy in order to produce and consume data in the DDS Global Data Space.”
Repo: crates/xrce-agent/src/daemon/dcps_bridge.rs (RealDdsPort,
runtime_for: ein DcpsRuntime je Domain)
Tests: crates/xrce-agent/tests/e2e_udp_loopback.rs::e2e_udp_loopback_keyed_dispose_reliable_besteffort_and_fragments
Status: done — der Test schreibt und liest über einen DomainParticipant
von zerodds-dcps ohne XRCE auf der anderen Seite.
§7.1 UML-Modell des Agent
Spec: §7.1, S. 17 — “this specification defines a UML model for the XRCE Agent. This model, called the DDS-XRCE Object Model, defines the objects, interfaces, and operations to be implemented by the agent.”
Repo: —
Tests: —
Status: n/a (informative) — Zuordnung; die Objekte stehen in den Items zu
§7.4 bis §7.6, die Operationen in §7.8.
§7.1 Jedes Topic mit jeder QoS
Spec: §7.1, S. 17 — “Despite being simpler, the DDS-XRCE Object Model provides XRCE clients complete access to the DDS Global Data space. Any DDS Topic may be published or subscribed to on any DDS with any QoS.”
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (apply_qos_profile, qos_policy, TopicQos, participant_qos_of); crates/xrce-agent/src/daemon/dcps_bridge.rs (create_writer, create_reader, create_participant_with)
Tests: crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_qos_of_a_topic_is_the_default_of_its_endpoints, crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_qos_of_an_xml_participant_is_applied, crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_participant_qos_profile_reference_is_applied, crates/xrce-agent/src/daemon/dcps_bridge.rs::tests::a_participant_qos_is_applied_to_the_participant
Status: done — jede Policy, die die DDS-Entität hat, wird angewandt: am Endpunkt RELIABILITY, DURABILITY, DURABILITY_SERVICE, HISTORY, DEADLINE, LATENCY_BUDGET, LIFESPAN, LIVELINESS, OWNERSHIP, OWNERSHIP_STRENGTH, DESTINATION_ORDER, TRANSPORT_PRIORITY, TIME_BASED_FILTER, PARTITION, USER_DATA, TOPIC_DATA, RESOURCE_LIMITS; am Publisher und Subscriber PARTITION, GROUP_DATA, PRESENTATION, ENTITY_FACTORY; am Topic als Vorgabe seiner Endpunkte (TopicQos); am DomainParticipant USER_DATA (eigene Runtime) und ENTITY_FACTORY, aus dem qos_profile_reference der Binärform und aus <domain_participant_qos> der XML-Form (0b67c04800c, 3906abf91b8). Was die Runtime nicht kann, wird nicht angenommen und ignoriert: STATUS_ERR_INCOMPATIBLE, es sei denn unsupported_qos: ignore (Einstellung für die Profildateien anderer Hersteller).
### §7.1 QoS, die der Agent nicht anwenden kann
Spec: §7.1, S. 17 — wie oben.
Repo: crates/xrce-agent/src/daemon/session.rs (plan_not_applied, create_core); crates/xrce-agent/src/daemon/entity_repr.rs (apply_qos_profile); crates/xrce-agent/src/daemon/config.rs (unsupported_qos)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::qos_the_agent_cannot_apply_is_refused_unless_ignoring_is_named, crates/xrce-agent/src/daemon/config.rs::tests::unsupported_qos_is_refused_unless_ignoring_is_named
Status: done — eine QoS, die der Agent nicht anwenden kann (WRITER_DATA_LIFECYCLE mit autodispose aus, READER_DATA_LIFECYCLE mit Autopurge-Verzögerung, ein Element eines Herstellerdialekts), macht das CREATE zu STATUS_ERR_INCOMPATIBLE; nichts wird gespeichert. unsupported_qos: ignore legt das Objekt ohne sie an und meldet, was fehlt (SessionEvent::RepresentationNotApplied). Eine Policy ohne Bedeutung für die Art des Endpunkts (TIME_BASED_FILTER eines Writers) gehört nicht zu dessen QoS und wird nicht gemeldet. 3906abf91b8.
§7.2 XRCE Client
§7.2 Gründe für ein eigenes Objektmodell
Spec: §7.2, S. 18 — drei Gründe: (1) “These clients expect a simplified interface with no callbacks, and use parameters encoded in text.” (2) “The DDS-XRCE DDS Object Model must overcome intermittent connectivity by introducing a ‘session,’ which can exist across repeated sleep-wakeup cycles by a device.” (3) “it is desirable to have an access control model that authenticates each client application/principal”.
Repo: —
Tests: —
Status: n/a (informative) — Begründung. Die Sitzung steht in den Items zu
§8.2.2 und §7.8.2.1, die Zugriffskontrolle im Item zu §7.4 AccessController.
§7.2 Arten von Clients
Spec: §7.2, S. 19 — einfache Geräte ohne Discovery, Geräte, die “data push” aktivieren und deaktivieren, Clients, die Objekte selbst anlegen, und Clients, die Sequenznummern und Zeitstempel nutzen.
Repo: —
Tests: —
Status: n/a (informative) — Beschreibung; das Ein- und Ausschalten der
Lieferung steht im Item zu Table 9 max_samples.
§7.3 XRCE Agent
§7.3 Präsenz des Client im DDS-Datenraum
Spec: §7.3, S. 19 — “The purpose of the DDS-XRCE Agent (XRCE Agent) is to establish and maintain the presence of the XRCE Client in the DDS data-space.”
Repo: crates/xrce-agent/src/daemon/session.rs (SessionEngine,
apply_dds_create); crates/xrce-agent/src/daemon/dcps_bridge.rs
(RealDdsPort::create_writer, create_reader)
Tests: crates/xrce-agent/tests/e2e_udp_loopback.rs::e2e_udp_loopback_keyed_dispose_reliable_besteffort_and_fragments
Status: done
§7.3 Vorkonfigurierte und vom Client angelegte Ressourcen
Spec: §7.3, S. 19 — “Resources may be preconfigured with well-known names, or dynamically created by an XRCE Client.”
Repo: crates/xrce-agent/src/daemon/profiles.rs
(AgentProfiles::predefined_objects);
crates/xrce-agent/src/daemon/definitions.rs (SystemDefinitions);
crates/xrce-agent/src/daemon/session.rs (SessionEngine::ensure_predefined,
make_client_applications); crates/xrce-agent/src/daemon/config.rs (Schlüssel
xml_profile_files, client_applications)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::references_resolve_against_the_profile_files,
crates/xrce-agent/src/daemon/session.rs::tests::a_client_writes_through_a_preconfigured_data_writer_without_a_create,
crates/xrce-agent/src/daemon/session.rs::tests::a_create_client_makes_the_objects_configured_for_the_client,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_reference_is_read_like_the_profile_it_names
Status: done — vom Client angelegte Ressourcen: CREATE. Konfigurierte
Ressourcen: die Dateien nach §9.3 (<types>, <qos_library>,
<domain_library>, <domain_participant_library>, <application_library>) aus
xml_profile_files: werden unter der ObjectId aus dem MD5 ihres Namens
bereitgestellt (468aa0940da, 452ffeb7f84, 9d5c64dc398, 2ba972cd270).
§7.3 Schreiben über eine vorkonfigurierte Ressource ohne CREATE
Spec: §7.3, S. 19 — “a Client that has access to this resource can write data using this resource simply by referring to the existing ‘MySquareWriter’. The Client does not have to create a resource.”
Repo: crates/xrce-agent/src/daemon/session.rs
(SessionEngine::ensure_predefined, aufgerufen von handle_write_data,
handle_read_data, handle_get_info und handle_create)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_client_writes_through_a_preconfigured_data_writer_without_a_create,
crates/xrce-agent/src/daemon/session.rs::tests::a_client_reads_through_a_preconfigured_data_reader_without_a_create,
crates/xrce-agent/src/daemon/session.rs::tests::a_preconfigured_object_is_made_only_for_a_client_allowed_to_create_it
Status: done — WRITE_DATA auf die ObjectId eines konfigurierten DataWriter
legt den DomainParticipant mit allem darin für den Client an (2ba972cd270); die
Zugriffsregeln gelten dabei. Eine ObjectId ohne Konfiguration ergibt
STATUS_ERR_UNKNOWN_REFERENCE.
§7.3 Abfrage durch den Client
Spec: §7.3, S. 19 — “This specification enables Clients to be in charge of when data is received, and to request the XRCE Agent to return data that matches a set of constraints. […] an XRCE Client queries the XRCE Agent when it wakes up.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_read_data,
pump_read); crates/xrce-agent/src/lib.rs (XrceAgent::pull_sample)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::read_data_elapsed_time_is_measured_from_the_real_request_time,
crates/xrce-agent/src/lib.rs::tests::after_submit_pull_returns_sample_in_fifo_order
Status: done
§7.3 DDS-RTPS zu den übrigen Participants
Spec: §7.3, S. 20 — “the standard interactions occurring with the XRCE Client use the DDS-XRCE protocol, while interactions with other DDS domain participants use the DDS-RTPS protocol.”
Repo: crates/xrce-agent/src/daemon/dcps_bridge.rs (RealDdsPort)
Tests: crates/xrce-agent/tests/e2e_udp_loopback.rs::e2e_udp_loopback_keyed_dispose_reliable_besteffort_and_fragments
Status: done
§7.3 Geteilte oder eigene DDS-Entitäten
Spec: §7.3, S. 19 — “a resource ‘MySquareWriter’ may be associated with a DDS DataWriter shared by many DDS-XRCE clients, or an XRCE Client may have its own dedicated ‘MySquareWriter’”.
Repo: —
Tests: —
Status: n/a (informative) — Freiheit der Implementierung; die Pflicht zum
Verhalten „als ob“ steht im Item zu §10.3.
§7.4 Model Overview
§7.4 Root als Singleton und Fabrik
Spec: §7.4, S. 21 — “The Root singleton is the entry point for the service. It functions as a factory for all the Objects managed by the XRCE Agent.”
Repo: crates/xrce-agent/src/daemon/session.rs (SessionEngine);
crates/xrce-agent/src/lib.rs (XrceAgent)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::create_client_happy_path_registers_and_replies_ok
Status: done
§7.4 ProxyClient
Spec: §7.4, S. 21 — “The ProxyClient class models the XRCE Client application that interacts with the XRCE Agent using the XRCE protocol.”
Repo: crates/xrce-agent/src/lib.rs (XrceAgent::register_client, ein
ObjectStore je ClientKey)
Tests: crates/xrce-agent/src/lib.rs::tests::multiple_clients_isolated
Status: done
§7.4 Application gehört zu einem ProxyClient
Spec: §7.4, S. 21 — “Each Application object is associated with a single XRCE ProxyClient and gets its access rights from those assigned to the XRCE Client.”
Repo: crates/xrce-agent/src/lib.rs (XrceAgent::create_object);
crates/xrce-agent/src/daemon/access.rs (AccessController::permits, Regeln je
ClientKey, ObjectKind application); crates/xrce-agent/src/daemon/session.rs
(SessionEngine::permit)
Tests: crates/xrce-agent/src/lib.rs::tests::create_application_object_via_objk_application,
crates/xrce-agent/src/lib.rs::tests::multiple_clients_isolated,
crates/xrce-agent/src/daemon/session.rs::tests::create_without_permission_is_denied_and_stores_nothing
Status: done — eine Application liegt im Objektspeicher ihres Client; ihre
Rechte sind die Regeln des Client im AccessController (1c430db8a67,
5f7a8652d95). Aus dem Code gelesen: die Prüfung nimmt den ClientKey und den
ObjectKind des Objekts; ein Test mit einer Application als verweigertem Objekt
gibt es nicht.
§7.4 Application mit DomainParticipants
Spec: §7.4, S. 21 — “The Application class models a software application that connects with the XRCE Client and manages the DDS objects needed to publish and subscribe data on one or more DDS Domains. An XRCE Application can be associated with zero of more DomainParticipant objects.”
Repo: crates/xrce-agent/src/daemon/session.rs (plan_dds_create gibt
DdsCreate::Application zurück, create_nested legt die DomainParticipants an,
je unter der ObjectId ihres Namens);
crates/xrce-agent/src/daemon/definitions.rs (ApplicationDef,
ParticipantDef)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_create_client_makes_the_objects_configured_for_the_client,
crates/xrce-agent/src/daemon/session.rs::tests::what_a_configuration_client_defines_is_referenced_by_another_client,
crates/xrce-agent/src/daemon/session.rs::tests::a_participant_definition_creates_the_objects_inside_it
Status: done — eine Application aus <application_library> legt ihre
DomainParticipants mit allem darin an, auch für einen Client, dem sie in
client_applications: zugeordnet ist (9d5c64dc398, 2ba972cd270).
§7.4 AccessController
Spec: §7.4, S. 21 — “The AccessController is responsible for making decisions regarding the resources and operations a particular XRCE ProxyClient is allowed to perform. It contains rules that associate a Client with privileges, which determine which DDS domain an application executing on behalf of a client may join, which DDS Topics the application can read and write, and so on.”
Repo: crates/xrce-agent/src/daemon/access.rs (AccessController, Rule,
Subject, Operation); crates/xrce-agent/src/daemon/session.rs
(SessionEngine::permit, permits, deny_create_client);
crates/xrce-agent/src/daemon/config.rs (Schlüssel authorized_client_keys,
required_client_properties, access_rules)
Tests: crates/xrce-agent/src/daemon/access.rs::tests::a_controller_without_rules_restricts_nothing,
crates/xrce-agent/src/daemon/access.rs::tests::the_first_matching_rule_decides_and_no_match_denies,
crates/xrce-agent/src/daemon/access.rs::tests::domains_kinds_and_topic_prefixes_narrow_a_rule,
crates/xrce-agent/src/daemon/access.rs::tests::only_configured_client_keys_are_authorized,
crates/xrce-agent/src/daemon/session.rs::tests::a_client_key_not_configured_in_the_agent_is_denied,
crates/xrce-agent/src/daemon/session.rs::tests::create_without_permission_is_denied_and_stores_nothing,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_and_delete_without_permission_are_denied,
crates/xrce-agent/src/daemon/session.rs::tests::write_and_read_without_permission_are_denied,
crates/xrce-agent/src/daemon/session.rs::tests::a_rule_can_limit_the_domains_a_client_joins
Status: done — Regeln je Client für Operation, ObjectKind, DDS-Domain und
Topic; eine Operation ohne passende Regel wird mit STATUS_ERR_DENIED
beantwortet, sobald eine Regel existiert, ohne Regeln beschränkt der Controller
nichts (1c430db8a67, 5f7a8652d95).
§7.4 DomainParticipant als Proxy
Spec: §7.4, S. 21 — “The DDS-XRCE DomainParticipant is a proxy for a DDS DomainParticipant and models the association with a DDS domain and the capability of the Application to publish and subscribe to Topics on that domain.”
Repo: crates/xrce-agent/src/daemon/dcps_bridge.rs
(RealDdsPort::create_participant_with, runtime_for)
Tests: crates/xrce-agent/src/daemon/dcps_bridge.rs::tests::full_chain_against_a_real_leased_domain,
crates/xrce-agent/src/daemon/dcps_bridge.rs::tests::two_large_samples_reach_a_default_reader_on_the_same_agent
Status: done — alle XRCE-DomainParticipants einer Domain teilen einen
DcpsRuntime, ausgenommen ein Participant mit USER_DATA (eigener Runtime je
Domain und Wert); §10.3 erlaubt das, solange sich das Verhalten so zeigt, als
hätte jeder Client eigene Entitäten.
§7.5 XRCE DDS Proxy Objects
§7.5 Proxy-Objekte delegieren an DDS-Objekte
Spec: §7.5, S. 22 — “These proxy objects allow the client application to participate as first-class citizens on the DDS network by delegating the actual DDS behavior and DDS-RTPS protocol implementation to the proxy DDS objects.” Figure 5: DomainParticipant, Publisher, Subscriber, DataWriter, DataReader, Topic, QosProfile und Qos als Werte.
Repo: crates/xrce-agent/src/daemon/session.rs (apply_dds_create);
crates/xrce-agent/src/daemon/dcps_bridge.rs
(RealDdsPort::create_participant_with, create_publisher,
create_subscriber, create_writer, create_reader)
Tests: crates/xrce-agent/tests/replay_foreign_session.rs::replay_creates_the_dds_entities_the_real_clients_describe,
crates/xrce-agent/tests/e2e_udp_loopback.rs::e2e_udp_loopback_keyed_dispose_reliable_besteffort_and_fragments,
crates/xrce-agent/src/daemon/dcps_bridge.rs::tests::a_publisher_is_a_dds_entity_of_its_participants_domain
Status: done — DataWriter und DataReader sind DDS-Endpunkte im
DcpsRuntime, Publisher und Subscriber haben je eine eigene DDS-Entität im
Participant (505c2e56d24), das Topic liegt als Name und Typ im Zustand des
RealDdsPort, QosProfile und Qos gehen als Werte ein.
§7.5 Publisher und Subscriber als DDS-Entität
Spec: §7.5, S. 22 — wie oben.
Repo: crates/xrce-agent/src/daemon/dds_port.rs
(DdsPort::create_publisher, create_subscriber, ContainerSpec);
crates/xrce-agent/src/daemon/dcps_bridge.rs (RealDdsPort::create_container,
container_for); crates/xrce-agent/src/daemon/session.rs
(DdsCreate::Container)
Tests: crates/xrce-agent/src/daemon/dcps_bridge.rs::tests::a_publisher_is_a_dds_entity_of_its_participants_domain,
crates/xrce-agent/src/daemon/session.rs::tests::a_publisher_and_a_subscriber_get_a_dds_entity_with_their_policies,
crates/xrce-agent/src/daemon/session.rs::tests::a_publisher_or_subscriber_needs_an_existing_participant,
crates/xrce-agent/src/daemon/dds_port.rs::tests::publisher_and_subscriber_need_their_participant_and_endpoints_need_them,
crates/xrce-agent/src/daemon/dds_port.rs::tests::a_publisher_that_does_not_autoenable_refuses_its_writers
Status: done — Publisher und Subscriber sind eine Gruppen-Entität im
Participant ihrer Domain; PRESENTATION und ENTITY_FACTORY aus den XML-Formen
wirken (ENTITY_FACTORY autoenable_created_entities: false verweigert die
Endpunkte darunter), PARTITION und GROUP_DATA erreichen die Endpunkte über deren
EndpointQos. Ein Participant, der nicht existiert, ergibt
STATUS_ERR_UNKNOWN_REFERENCE (505c2e56d24). GROUP_DATA wird mit dem Endpunkt
angekündigt, nicht mit einer eigenen Ankündigung des Publisher.
§7.6 XRCE Object Identification
§7.6 ObjectId eindeutig je Agent und ClientKey
Spec: §7.6, S. 22 — “This implies that the ObjectId shall be unique within the scope of an Agent and a ClientKey.”
Repo: crates/xrce/src/object_store.rs (ObjectStore);
crates/xrce-agent/src/lib.rs (XrceAgent::register_client, ein Objektspeicher
je ClientKey)
Tests: crates/xrce/src/object_store.rs::tests::create_strict_on_existing_returns_conflict,
crates/xrce-agent/src/lib.rs::tests::multiple_clients_isolated
Status: done
§7.6 ObjectId im Agent konfiguriert oder vom Client gewählt
Spec: §7.6, S. 22 — “The value of the ObjectId for a particular object shall be configured on the XRCE Agent or specified by the XRCE Client at the time the object is created.”
Repo: crates/xrce/src/object_id.rs (ObjectId::from_reference);
crates/xrce-agent/src/daemon/session.rs (handle_create, ensure_predefined)
Tests: crates/xrce/src/object_id.rs::tests::from_reference_matches_the_examples_of_the_spec,
crates/xrce-agent/src/daemon/session.rs::tests::a_client_writes_through_a_preconfigured_data_writer_without_a_create,
crates/xrce-agent/src/daemon/session.rs::tests::the_object_id_is_the_prefix_and_the_kind_of_the_representation,
crates/xrce-agent/tests/replay_foreign_session.rs::replay_matches_the_real_agents_create_client_create_and_delete_replies
Status: done — die vom Client gewählte ObjectId wird übernommen; die im
Agent konfigurierte ObjectId ist die aus dem MD5 des Namens nach §9.3 und
Table 16 (468aa0940da, 2ba972cd270).
§7.6 OBJECTID_INVALID {0x00, 0x00}
Spec: §7.6, S. 23 — “The value {0x00, 0x00} is referred as OBJECTID_INVALID and represents an invalid object.”
Repo: crates/xrce/src/object_id.rs (OBJECTID_INVALID = 0x0000,
OBJECTID_SESSION = 0xFFFF); crates/xrce/src/object_store.rs
(ObjectStore::create weist OBJECTID_INVALID ab)
Tests: crates/xrce/src/object_id.rs::tests::invalid_object_id_is_all_zeros,
crates/xrce/src/object_id.rs::tests::reserved_object_ids_per_spec_7_6_and_annex_a,
crates/xrce/src/object_store.rs::tests::create_invalid_object_id_rejected
Status: done — OBJECTID_INVALID ist {0x00, 0x00}, 0xFFFF ist
OBJECTID_SESSION aus Annex A (daf2a618f74); die Konstanten der SDKs in
endpoints/ folgen (6f674508b96).
§7.6 OBJECTID_CLIENT {0xFF, 0xFE}
Spec: §7.6, S. 23 — “The value {0xFF, 0xFE} is referred as OBJECTID_CLIENT and represents the XRCE ProxyClient object.”
Repo: crates/xrce/src/object_id.rs (OBJECTID_CLIENT);
crates/xrce-agent/src/daemon/session.rs (handle_delete)
Tests: crates/xrce/src/object_id.rs::tests::client_singleton_has_kind_client,
crates/xrce-client/src/lib.rs::tests::disconnect_sends_delete_client_and_clears_state
Status: done
§7.6 Zwei reservierte Werte
Spec: §7.6, S. 23 — “There are two reserved values for ObjectId.”
Repo: —
Tests: —
Status: n/a (informative) — Annex A (S. 103) nennt vier Werte
(OBJECTID_INVALID, OBJECTID_AGENT, OBJECTID_CLIENT, OBJECTID_SESSION);
die beiden zusätzlichen sind als Items zu Annex A geführt.
§7.6 Name der Ressource statt ObjectId
Spec: §7.6, S. 23 — “Alternatively, objects may also be identified by a string resourceName. The format of this name depends on the resource and provides a way to refer to a resource configured on the agent using a configuration file or similar means.”
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (referenced);
crates/xrce-agent/src/daemon/profiles.rs (AgentProfiles);
crates/xrce-agent/src/daemon/definitions.rs (SystemDefinitions)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::references_resolve_against_the_profile_files,
crates/xrce-agent/src/daemon/session.rs::tests::a_topic_is_created_by_name_or_by_register_type_ref,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_reference_is_read_like_the_profile_it_names
Status: done — ein Name löst sich gegen die Dateien des Agent auf:
profile_name einer Profildatei und die Namen nach DDS-XML (Library::Element,
Table 15) der Bibliotheken von §9.3 (452ffeb7f84, 9d5c64dc398).
§7.7 Data types used to model operations on XRCE Objects
§7.7 IDL nach Annex A, Kodierung XCDR2
Spec: §7.7, S. 23 — “The IDL definitions for the data types shall be as specified in Annex A IDL Types. When serializing these types into a binary representation the encoding shall follow the rules defined in in [DDS-XTYPES] for XCDR version 2 encoding.”
Repo: crates/xrce/src/ (Codecs je Typ, siehe die folgenden Items;
encoding.rs: UnannotatedTypes, RepresentationTimestamps);
crates/xrce-agent/src/daemon/binary_forms.rs (XCDR2-Leser der Binärformen)
Tests: crates/xrce/tests/foreign_frames.rs::every_client_datagram_decodes_and_writes_back,
crates/xrce/tests/foreign_frames.rs::every_agent_datagram_decodes_and_writes_back,
crates/xrce/tests/unannotated_types.rs::the_default_is_appendable_with_a_dheader
Status: done — die Payloads der Submessages und die Typen von Annex A
werden nach XCDR2 gelesen und geschrieben. Typen ohne @extensibility sind
APPENDABLE mit DHEADER; die FINAL-Form der Referenzimplementierung ist die
Einstellung unannotated_types: final (7f85e76debd). Erweiterungen über Annex A
hinaus stehen in den Items der einzelnen Typen, darunter requested_mtu hinter
properties der CLIENT_Representation. Die klassische CDR-Form der Binärobjekte
des eProsima-Client bleibt als Rückfall (entity_repr.rs, Cdr).
§7.7 Ausrichtung, DHEADER und Byte-Reihenfolge der Annex-A-Typen
Spec: §7.7, S. 23 — wie oben.
Repo: crates/xrce/src/handshake.rs (encode_properties,
decode_properties); crates/xrce/src/transport_locator.rs;
crates/xrce/src/submessages/read_data.rs; crates/xrce/src/object_info.rs;
crates/xrce-agent/src/daemon/binary_forms.rs
Tests: crates/xrce/src/handshake.rs::tests::padding_counts_from_the_start_of_the_payload,
crates/xrce/src/handshake.rs::tests::a_big_endian_client_representation_with_properties_reads_back,
crates/xrce/src/transport_locator.rs::tests::padding_is_counted_from_the_start_of_the_payload,
crates/xrce/src/transport_locator.rs::tests::by_default_the_union_and_its_case_have_a_dheader,
crates/xrce/src/submessages/read_data.rs::tests::the_content_filter_is_a_string_with_a_nul_and_an_aligned_length,
crates/xrce/src/submessages/read_data.rs::tests::annex_b_4_2_read_data_with_filter_and_delivery_control,
crates/xrce/src/object_info.rs::tests::agent_activity_info_has_a_dheader_and_a_locator_sequence,
crates/xrce/src/object_info.rs::tests::object_info_puts_the_activity_before_the_config,
crates/xrce-agent/src/daemon/binary_forms.rs::tests::annex_a_topic_has_a_dheader,
crates/xrce/tests/unannotated_types.rs::both_forms_are_read_in_either_setting
Status: done — die Abweichungen sind behoben: PropertySeq mit auf 4
ausgerichteten Längen (ca0cf7e08bf); TransportLocator mit Ausrichtung, DHEADER
und numerischen Ports (299b3a41398); content_filter_expression als
XCDR2-String und DataDeliveryControl mit DHEADER (b589558e671);
AGENT_ActivityInfo, DATAREADER_ActivityInfo, DATAWRITER_ActivityInfo,
ObjectInfo und ActivityInfoVariant nach Annex A (ca0cf7e08bf); die
Binärformen von Annex A als XCDR2 mit DHEADER (f548fee2522);
CLIENT_Representation, AGENT_Representation, ObjectInfo und die Locatoren
in der Byte-Reihenfolge des E-Flag (b9255734bfb).
§7.7.1 Data and Samples
§7.7.1 Fünf Formate und die Werte von DataFormat
Spec: §7.7.1, S. 23 — “The five possible representation are: SampleData, Sample, SampleDataSeq, SampleSeq, and SamplePackedData. They respectively correspond to the DataFormat values FORMAT_DATA, FORMAT_DATA_SEQ, FORMAT_SAMPLE, FORMAT_SAMPLE_SEQ, and FORMAT_PACKED.”
Repo: crates/xrce/src/submessages/write_data.rs (DataFormat,
AnyWriteData); crates/xrce/src/submessages/data.rs (AnyData)
Tests: crates/xrce/src/submessages/write_data.rs::tests::any_write_data_dispatches_every_format,
crates/xrce/src/submessages/data.rs::tests::any_data_dispatches_every_format,
crates/xrce/src/submessages/read_data.rs::tests::the_data_format_octet_has_the_values_of_annex_a
Status: done — der Code ordnet wie Table 1 und Annex A zu (SampleDataSeq
zu FORMAT_DATA_SEQ, Sample zu FORMAT_SAMPLE; Werte 0x00, 0x02, 0x08, 0x0A,
0x0E). Die Aufzählung „respectively“ dieses Satzes ordnet Sample
FORMAT_DATA_SEQ zu und nennt SamplePackedData und FORMAT_PACKED, die es in
Annex A nicht gibt.
§7.7.1 SampleData
Spec: §7.7.1, S. 23 — “@extensibility(FINAL) struct SampleData { XCDRSerializedBuffer serialized_data; }; In this structure the XCDRSerializedBuffer represents the bytes resulting from serializing the application-specific data type that is being sent using the XCDR version 2 rules defined in clause 7.4 of [DDS-XTYPES].”
Repo: crates/xrce/src/submessages/write_data.rs
(WriteDataPayload::encode_body, try_from_submessage);
crates/xrce/src/submessages/data.rs (DataPayload)
Tests: crates/xrce/src/submessages/write_data.rs::tests::write_data_matches_the_annex_b_example,
crates/xrce/src/submessages/data.rs::tests::data_base_object_request_precedes_the_sample
Status: done — serialized_data läuft ohne eigene Länge bis zum Ende der
Submessage, wie in Annex B.3.1 (submessageLength = 6). Annex A definiert
XCDRSerializedBuffer nicht.
§7.7.1 SampleInfoFlags
Spec: §7.7.1, S. 23 — “@bit_bound(8) bitmask SampleInfoFlags { @position(0) INSTANCE_STATE_UNREGISTERED, @position(1) INSTANCE_STATE_DISPOSED, @position(2) VIEW_STATE_NEW, @position(3) SAMPLE_STATE_READ, };”
Repo: crates/xrce/src/sample_info.rs (SampleInfoFlags)
Tests: crates/xrce/src/sample_info.rs::tests::sample_info_flags_bit_positions,
crates/xrce/src/sample_info.rs::tests::sample_info_flags_all_four_bits_independent
Status: done
§7.7.1 SampleInfo mit sequence_number und session_time_offset
Spec: §7.7.1, S. 24 — “@extensibility(FINAL) struct SampleInfo { SampleInfoFlags state; unsigned long sequence_number; unsigned long session_time_offset; // milliseconds up to 53 days };”
Repo: crates/xrce/src/sample_info.rs (SampleInfo,
WIRE_SIZE = 12)
Tests: crates/xrce/src/sample_info.rs::tests::sample_info_matches_annex_b_5_3_layout,
crates/xrce/src/sample_info.rs::tests::sample_info_roundtrip_be
Status: done — state, 3 Byte Füllung, zwei unsigned long. Annex A
(S. 115) definiert SampleInfo anders; das ist ein eigenes Item zu Annex A.
§7.7.1 Sample
Spec: §7.7.1, S. 24 — “@extensibility(FINAL) struct Sample { SampleInfo info; SampleData data; };”
Repo: crates/xrce/src/submessages/write_data.rs
(WriteDataPayloadSample); crates/xrce/src/submessages/data.rs
(DataPayloadSample)
Tests: crates/xrce/src/submessages/write_data.rs::tests::write_data_sample_matches_annex_b_5_3_layout,
crates/xrce/src/submessages/data.rs::tests::data_sample_matches_annex_b_5_3_layout
Status: done
§7.7.1 DeciSecond und SampleInfoDelta
Spec: §7.7.1, S. 24 — “typedef unsigned short DeciSecond; // 10e-1 seconds @extensibility(FINAL) struct SampleInfoDelta { SampleInfoFlags state; octet seq_number_delta; DeciSecond timestamp_delta; // In 1/10 of seconds };”
Repo: crates/xrce/src/sample_info.rs (SampleInfoDelta,
WIRE_SIZE = 4)
Tests: crates/xrce/src/sample_info.rs::tests::sample_info_delta_roundtrip,
crates/xrce/src/sample_info.rs::tests::sample_info_delta_decode_short_is_eof
Status: done
§7.7.1 SampleDelta
Spec: §7.7.1, S. 24 — “@extensibility(FINAL) struct SampleDelta { SampleInfoDelta info_delta; SampleData data; };”
Repo: crates/xrce/src/submessages/write_data.rs
(WriteDataPayloadPackedSamples::elements); crates/xrce/src/sample_info.rs
(SampleInfoDelta::decode); crates/xrce-agent/src/daemon/session.rs
(SessionEngine::split_write_items, SessionEngine::data_submessages)
Tests: crates/xrce/src/submessages/write_data.rs::tests::write_data_packed_samples_matches_annex_b_5_5_layout,
crates/xrce-agent/src/daemon/session.rs::tests::packed_samples_resolve_their_deltas_against_the_base
Status: done — das Layout je Element ist abgebildet; im Codec bleiben die Elemente
ein Block (elements), weil SampleData keine Länge trägt. Der Agent trennt
sie beim WRITE_DATA nach dem Typ des Topic (split_write_items, f40bd568ad1)
und schreibt sie beim READ_DATA (data_submessages, fd5253ca805).
§7.7.1 PackedSamples
Spec: §7.7.1, S. 24 — “@extensibility(FINAL) struct PackedSamples {
SampleInfo info_base; sequence
Repo: crates/xrce/src/submessages/write_data.rs
(WriteDataPayloadPackedSamples); crates/xrce/src/submessages/data.rs
(DataPayloadPackedSamples)
Tests: crates/xrce/src/submessages/data.rs::tests::data_packed_samples_matches_annex_b_5_5_layout,
crates/xrce-agent/src/daemon/session.rs::tests::a_read_for_packed_samples_is_answered_with_one_packed_samples,
crates/xrce-agent/src/daemon/session.rs::tests::packed_samples_resolve_their_deltas_against_the_base
Status: done — der Agent liest die Form beim WRITE_DATA (f40bd568ad1) und schreibt sie beim READ_DATA (fd5253ca805).
§7.7.2 DataRepresentation
§7.7.2 DataRepresentation als Union über DataFormat
Spec: §7.7.2, S. 24 und S. 26 — “The DataRepresentation is defined as a union discriminated by a DataFormat. Depending on the discriminator it selects one of the formats defined in clause 7.7.1.” “union DataRepresentation switch(DataFormat) { case FORMAT_DATA: SampleData data; case FORMAT_SAMPLE: Sample sample; case FORMAT_DATA_SEQ: SampleDataSeq data_seq; case FORMAT_SAMPLE_SEQ: SampleSeq sample_seq; case FORMAT_PACKED_SAMPLES: PackedSamples packed_samples; };”
Repo: crates/xrce/src/submessages/write_data.rs (AnyWriteData,
Diskriminator aus den Flags über DataFormat::from_flag_bits)
Tests: crates/xrce/src/submessages/write_data.rs::tests::any_write_data_dispatches_every_format
Status: done — der Diskriminator steht in den Flags der Submessage (§8.3.5.8.1), nicht im Payload.
§7.7.2 Table 1 FORMAT_DATA
Spec: §7.7.2, Table 1, S. 25 — “FORMAT_DATA struct SampleData […] Contains the data for a single sample without additional sample information.”
Repo: crates/xrce/src/submessages/write_data.rs (WriteDataPayload)
Tests: crates/xrce/src/submessages/write_data.rs::tests::write_data_roundtrip_format_data
Status: done
§7.7.2 Table 1 FORMAT_DATA_SEQ
Spec: §7.7.2, Table 1, S. 25 — “FORMAT_DATA_SEQ struct SampleDataSeq […] Contains a sequence of data samples.”
Repo: crates/xrce/src/submessages/write_data.rs
(WriteDataPayloadDataSeq); crates/xrce-agent/src/daemon/session.rs
(SessionEngine::split_write_items, SessionEngine::data_submessages)
Tests: crates/xrce/src/submessages/write_data.rs::tests::write_data_data_seq_matches_annex_b_5_2_layout,
crates/xrce-agent/src/daemon/session.rs::tests::a_data_seq_is_split_by_the_type_and_written_sample_by_sample,
crates/xrce-agent/src/daemon/session.rs::tests::a_read_for_data_seq_is_answered_with_one_data_seq,
crates/xrce-agent/src/daemon/session.rs::tests::the_sequence_formats_split_at_the_size_of_a_submessage
Status: done — Zahl der Elemente und die Elemente als ein Block. Der Agent trennt die Elemente beim WRITE_DATA nach dem Typ des Topic und schreibt jedes einzeln (f40bd568ad1); beim READ_DATA schreibt er eine DATA_SEQ je Submessage (fd5253ca805). Annahme, nicht gemessen: die Elemente stehen ohne Füllung hintereinander, jedes ab Ausrichtungsursprung 0 gelesen (Annex B.5.2 zeigt nur Elemente von 4 Byte).
§7.7.2 Table 1 FORMAT_SAMPLE mit Zeitstempel relativ zur Sitzung
Spec: §7.7.2, Table 1, S. 25 — “The SampleInfo holds the DDS InstanceState, SampleState, and ViewState of the corresponding DDS Sample. It also contains the sample sequence number and timestamp. The timestamp is represented as an offset relative to the session timestamp established when the session was created. The session timestamp corresponds to the client_timestamp attribute in CLIENT_Representation”.
Repo: crates/xrce-agent/src/daemon/session.rs (data_submessages, source_offset_ms, handle_write_data); crates/xrce/src/sample_info.rs (SampleInfo)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::the_sample_info_is_what_the_datareader_gave, crates/xrce-agent/src/daemon/session.rs::tests::the_client_timestamp_is_the_session_timestamp
Status: done — Zustand, Sequenznummer und Versatz werden übertragen. Beim WRITE_DATA ist der Versatz die Zeit nach dem Beginn der Sitzung und wird zum Quellzeitstempel (f40bd568ad1). Beim READ_DATA sendet der Agent FORMAT_SAMPLE mit dem Quellzeitstempel des Writers als Versatz und dem Zustand des DataReaders (5c2466a4563). Der Beginn der Sitzung ist das client_timestamp des CREATE_CLIENT (8b73c291192).
### §7.7.2 Inhalt der SampleInfo und Bezugspunkt des Zeitstempels
Spec: §7.7.2, Table 1, S. 25 — wie oben.
Repo: crates/xrce-agent/src/daemon/dds_port.rs (PolledSample, DdsPort::poll_samples); crates/xrce-agent/src/daemon/dcps_bridge.rs (spawn_reader_pump, ReaderQueue::push); crates/xrce-agent/src/daemon/session.rs (data_submessages, session_start); crates/xrce-client/src/lib.rs (session_time_offset_ms)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::the_sample_info_is_what_the_datareader_gave, crates/xrce-agent/src/daemon/session.rs::tests::the_client_timestamp_is_the_session_timestamp
Status: done — DdsPort::poll_samples liefert PolledSample (Nutzdaten, SampleInfoFlags, Quellzeitstempel): VIEW_STATE_NEW für das erste Sample einer Instanz, INSTANCE_STATE_DISPOSED/_UNREGISTERED für ein dispose oder unregister, das der DataReader meldet (ein Sample ohne Daten), SAMPLE_STATE_READ nie (ein Sample wird einmal übergeben). FORMAT_DATA und FORMAT_DATA_SEQ haben keine SampleInfo und senden keine Marker. Bezugspunkt ist das client_timestamp (representation_timestamps: present) oder die Uhr des Agent; der Client schreibt die Millisekunden seit connect als Versatz. 5c2466a4563, 8b73c291192.
### §7.7.2 Table 1 FORMAT_SAMPLE_SEQ
Spec: §7.7.2, Table 1, S. 25 — “FORMAT_SAMPLE_SEQ struct SampleSeq […] Contains a sequence of samples, each containing both the data and the additional sample information.”
Repo: crates/xrce/src/submessages/write_data.rs
(WriteDataPayloadSampleSeq); crates/xrce-agent/src/daemon/session.rs
(SessionEngine::split_write_items, SessionEngine::data_submessages)
Tests: crates/xrce/src/submessages/write_data.rs::tests::write_data_sample_seq_matches_annex_b_5_4_layout,
crates/xrce-agent/src/daemon/session.rs::tests::a_sample_seq_carries_state_and_time_per_sample,
crates/xrce-agent/src/daemon/session.rs::tests::a_read_for_sample_seq_is_answered_with_one_sample_seq
Status: done — der Agent liest die Form beim WRITE_DATA (Zustand und Zeit je Sample,
f40bd568ad1) und schreibt sie beim READ_DATA (fd5253ca805). Was die
SampleInfo beim Lesen enthält, steht im open-Item zu §7.7.2.
§7.7.2 Table 1 FORMAT_PACKED_SAMPLES und resulting_info
Spec: §7.7.2, Table 1, S. 25 — “This representation is limited to samples that are close in sequence number (no more than 256 apart) and timestamp (100 minutes). […] resulting_info.state := info_delta.state resulting_info.sequence_number := info_base.sequence_number + info_delta.seq_number_delta resulting_info. session_time_offset := info_base. session_time_offset + info_delta.timestamp_delta”
Repo: crates/xrce/src/sample_info.rs (SampleInfoDelta::resolve);
crates/xrce-agent/src/daemon/session.rs (SessionEngine::data_submessages)
Tests: crates/xrce/src/sample_info.rs::tests::sample_info_delta_resolve_adds_to_base,
crates/xrce/src/sample_info.rs::tests::sample_info_delta_resolve_wraps_on_overflow,
crates/xrce-agent/src/daemon/session.rs::tests::packed_samples_resolve_their_deltas_against_the_base,
crates/xrce-agent/src/daemon/session.rs::tests::a_read_for_packed_samples_is_answered_with_one_packed_samples
Status: done — resolve rechnet timestamp_delta (Zehntelsekunden) mit 100 in
Millisekunden um; die Formel der Spec addiert Größen in Millisekunden und
Zehntelsekunden ohne Umrechnung. Der Agent liest die Form beim WRITE_DATA und
schreibt sie beim READ_DATA mit höchstens 256 Elementen je Submessage (Bereich
von seq_number_delta, ein octet); timestamp_delta und state schreibt er
als 0 (f40bd568ad1, fd5253ca805).
§7.7.3 ObjectVariant
§7.7.3 ObjectVariant als Union über ObjectKind
Spec: §7.7.3, S. 26 — “The ObjectVariant type is defined as a union discriminated by ObjectKind. Each value of the discriminator selects an appropriate object representation for that kind.”
Repo: crates/xrce/src/object_repr.rs (ObjectVariant::encode_for_kind, decode_for_kind, ObjectVariantExtra)
Tests: crates/xrce/src/object_repr.rs::tests::encode_for_kind_round_trips_every_objk_kind_with_its_own_trailing_field,
crates/xrce/src/object_repr.rs::tests::participant_representation_matches_the_captured_create_bytes,
crates/xrce/src/object_repr.rs::tests::subscriber_representation_matches_the_captured_create_bytes
Status: done — ObjectKind als Oktett, danach die Repräsentation der Art
und ihr nachgestelltes Feld (domain_id oder die ObjectId des Containers).
§7.7.3 Mehrere Formate je Art
Spec: §7.7.3, S. 26 — “For a given ObjectKind the, ObjectVariant type also supports multiple representation formats. Each format is identified by a value of the RepresentationFormat.”
Repo: crates/xrce/src/object_repr.rs (ObjectVariant,
encode_with_pad, decode_with_pad)
Tests: crates/xrce/src/object_repr.rs::tests::by_reference_roundtrip_le,
crates/xrce/src/object_repr.rs::tests::by_xml_string_roundtrip_be,
crates/xrce/src/object_repr.rs::tests::in_binary_roundtrip
Status: done
§7.7.3.1 Object Representation Formats
§7.7.3.1 Drei Werte von RepresentationFormat
Spec: §7.7.3.1, S. 26 — “There are three RepresentationFormat values: REPRESENTATION_BY_REFERENCE, REPRESENTATION_AS_XML_STRING, and REPRESENTATION_IN_BINARY.” Annex A, S. 106: 0x01, 0x02, 0x03.
Repo: crates/xrce/src/object_repr.rs (repr_disc)
Tests: crates/xrce/src/object_repr.rs::tests::discriminator_returns_correct_byte,
crates/xrce/src/object_repr.rs::tests::unknown_discriminator_rejected
Status: done
§7.7.3.1 Drei oder zwei Formate je Art
Spec: §7.7.3.1, S. 26 — “Some object kinds support all three formats; in this case the corresponding representation extends the type struct OBJK_Representation3_Base. Other object kinds support only two formats, and therefore, extend the type struct OBJK_RepresentationRefAndXML_Base or the type OBJK_RepresentationBinAndXML_Base.”
Repo: crates/xrce/src/object_repr.rs (decode_for_kind); crates/xrce-agent/src/daemon/session.rs
(format_is_allowed)
Tests: crates/xrce/src/object_repr.rs::tests::encode_for_kind_round_trips_every_objk_kind_with_its_own_trailing_field,
crates/xrce-agent/src/daemon/session.rs::tests::the_formats_of_each_kind_are_enforced
Status: done — decode_for_kind liest alle drei Diskriminatoren; der Agent lässt je
Art nur die Formate der Spec zu: Participant und Topic alle drei, Type,
QosProfile und Application Referenz und XML, Publisher, Subscriber, DataWriter
und DataReader Binär und XML. Ein anderes Format ist STATUS_ERR_INVALID_DATA
(0429eab4fb2). Die Einstellung steht im Item „Erlaubte Formate je Art“.
§7.7.3.1 Erlaubte Formate je Art
Spec: §7.7.3.1, S. 26 — wie oben.
Repo: crates/xrce-agent/src/daemon/session.rs (format_is_allowed, Prüfung in SessionEngine::handle_create);
crates/xrce-agent/src/daemon/config.rs (Schlüssel representation_formats)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::the_formats_of_each_kind_are_enforced,
crates/xrce-agent/src/daemon/session.rs::tests::references_resolve_against_the_profile_files,
crates/xrce-agent/src/daemon/config.rs::tests::the_representation_formats_can_be_widened
Status: done — normative Lesart (§7.7.3.1, Annex A) als Vorgabe: ein CREATE in einem
Format, das die Union der Art nicht hat, ist STATUS_ERR_INVALID_DATA mit einem
Ereignis CreateRefused. Die andere Lesart ist die Einstellung
representation_formats: spec | any (Vorgabe spec); any lässt alle Formate
zu, etwa für den Micro-XRCE-DDS-Client, der Publisher, Subscriber, DataWriter
und DataReader per *_ref anlegt (nicht gemessen, der Mitschnitt hat nur XML
und Binär). Beide Lesarten sind getestet (0429eab4fb2).
§7.7.3.1 OBJK_Representation3Formats
Spec: §7.7.3.1, S. 26–27 — “union OBJK_Representation3Formats
switch(RepresentationFormat) { case REPRESENTATION_BY_REFERENCE :
string
Repo: crates/xrce/src/object_repr.rs (ObjectVariant,
encode_with_pad: Länge, Zeichen und NUL für die Zeichenketten, Länge
und Oktette für die Sequenz)
Tests: crates/xrce/src/object_repr.rs::tests::topic_representation_matches_the_captured_create_bytes,
crates/xrce/src/object_repr.rs::tests::in_binary_roundtrip
Status: done — die Grenze REFERENCE_MAX_LEN ist ein eigenes Item.
§7.7.3.1 OBJK_RepresentationRefAndXMLFormats
Spec: §7.7.3.1, S. 27 — “union OBJK_RepresentationRefAndXMLFormats
switch(RepresentationFormat) { case REPRESENTATION_BY_REFERENCE :
string
Repo: crates/xrce/src/object_repr.rs (ObjectVariant::ByReference,
ByXmlString)
Tests: crates/xrce/src/object_repr.rs::tests::object_variant_xml_form_supports_topic_qosprofile_application
Status: done — die Kodierung der beiden Fälle; dass IN_BINARY hier nicht
vorkommen darf, steht im open-Item „Erlaubte Formate je Art nicht geprüft“.
§7.7.3.1 OBJK_RepresentationBinAndXMLFormats
Spec: §7.7.3.1, S. 27 — “union OBJK_RepresentationBinAndXMLFormats
switch(RepresentationFormat) { case REPRESENTATION_IN_BINARY :
sequence
Repo: crates/xrce/src/object_repr.rs (ObjectVariant::InBinary,
ByXmlString)
Tests: crates/xrce/src/object_repr.rs::tests::subscriber_representation_matches_the_captured_create_bytes
Status: done — wie oben für BY_REFERENCE.
§7.7.3.1 Basistypen mit dem Member representation
Spec: §7.7.3.1, S. 27 — “struct OBJK_RepresentationRefAndXML_Base { OBJK_RepresentationRefAndXMLFormats representation; }; struct OBJK_RepresentationBinAndXML_Base { OBJK_RepresentationBinAndXMLFormats representation; }; struct OBJK_Representation3_Base { OBJK_Representation3Formats representation; };”
Repo: crates/xrce/src/object_repr.rs (encode_for_kind)
Tests: crates/xrce/src/object_repr.rs::tests::encode_for_kind_round_trips_every_objk_kind_with_its_own_trailing_field
Status: done
§7.7.3.1 REFERENCE_MAX_LEN = 128
Spec: §7.7.3.1, S. 26 — “const long REFERENCE_MAX_LEN = 128;” mit
string<REFERENCE_MAX_LEN> object_reference.
Repo: crates/xrce/src/object_repr.rs (REFERENCE_MAX_LEN, Prüfung in
ObjectVariant::encode_with_pad und decode_with_pad)
Tests: crates/xrce/src/object_repr.rs::tests::a_reference_longer_than_reference_max_len_is_refused
Status: done — Lesen und Schreiben weisen eine Referenz mit mehr als 128 Zeichen ab; 128 Zeichen sind erlaubt (58aad3ce5d7).
§7.7.3.1 Weitere Formate wie JSON
Spec: §7.7.3.1, S. 27–28 — “It is expected that additional representations may be added after they are defined in other OMG specifications.”
Repo: —
Tests: —
Status: n/a (informative) — Ausblick.
§7.7.3.1.1 Referenz auf eine im Agent bekannte Beschreibung
Spec: §7.7.3.1.1, S. 28 — “The REPRESENTATION_BY_REFERENCE represents the object using an object_reference encoded in a string. The string shall refer by name to a description already known to the XRCE Agent.”
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (referenced, participant,
participant_definition, application_definition); crates/xrce-agent/src/daemon/profiles.rs
(AgentProfiles::entity, AgentProfiles::qos_profile); crates/xrce-agent/src/daemon/definitions.rs
(SystemDefinitions); crates/xrce-agent/src/daemon/session.rs (plan_dds_create)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::references_resolve_against_the_profile_files,
crates/xrce-agent/src/daemon/session.rs::tests::what_a_configuration_client_defines_is_referenced_by_another_client,
crates/xrce-agent/src/daemon/session.rs::tests::a_client_writes_through_a_preconfigured_data_writer_without_a_create,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_reference_is_read_like_the_profile_it_names
Status: done — Participant, Topic, Publisher, Subscriber, DataWriter und DataReader
lösen sich gegen profile_name einer Profildatei im Format von Fast DDS auf;
QosProfile (Lib::Profile), Application (Lib::App) und DomainParticipant
(Lib::Participant) gegen die Bibliotheken der Dateien und gegen die
Definitionen anderer Clients (452ffeb7f84, 9d5c64dc398, 2ba972cd270). Eine
unbekannte Referenz ist STATUS_ERR_UNKNOWN_REFERENCE. Publisher, Subscriber,
DataWriter und DataReader per Referenz gibt es nur mit
representation_formats: any. Typ und Domain stehen in den Items zu
§7.7.3.3.1 und §7.7.3.4.1.
§7.7.3.1.1 object_reference nach elementNameReference von DDS-XML
Spec: §7.7.3.1.1, S. 28 — “The object_reference shall be a string formatted as defined by the XSD simpleType elementNameReference defined in the [DDS-XML] specification file dds-xml_domain_definitions_nonamespace.xsd.”
Repo: crates/xrce/src/object_repr.rs (element_name_reference); crates/xrce-agent/src/daemon/session.rs (handle_create)
Tests: crates/xrce/src/object_repr.rs::tests::element_name_references_follow_the_xsd_pattern, crates/xrce-agent/src/daemon/session.rs::tests::an_object_reference_must_be_an_element_name_reference
Status: done — der Agent prüft den object_reference eines CREATE nach dem XSD-Typ elementNameReference (dds-xml_qos_definitions_nonamespace.xsd): whiteSpace collapse, dann das Muster ((::)?[a-zA-Z0-9_.])+. Eine Zeichenkette anderer Form ist STATUS_ERR_INVALID_DATA, eine wohlgeformte, die der Agent nicht kennt, STATUS_ERR_UNKNOWN_REFERENCE; Referenzen der Form Library::Name werden gegen die Bibliotheken von DDS-XML aufgelöst (9d5c64dc398, 452ffeb7f84). 1b9eed094c3.
### §7.7.3.1.1 Vorkonfiguration offline oder über das Protokoll
Spec: §7.7.3.1.1, S. 28 — “The pre-configuration may be done off-line prior to starting the XRCE Agent or may be done on-line using the DDS-XRCE protocol in combination with the REPRESENTATION_AS_XML_STRING.”
Repo: crates/xrce-agent/src/daemon/profiles.rs (AgentProfiles::load, AgentProfiles::add_profiles);
crates/xrce-agent/src/daemon/session.rs (SessionEngine::definition_to_register, rebuild_profiles)
Tests: crates/xrce-agent/src/daemon/profiles.rs::tests::the_eprosima_refs_file_indexes_every_entity_profile,
crates/xrce-agent/src/daemon/profiles.rs::tests::types_and_qos_libraries_in_a_dds_document_are_read,
crates/xrce-agent/src/daemon/session.rs::tests::what_a_configuration_client_defines_is_referenced_by_another_client
Status: done — offline über xml_profile_files: (<types>, <qos_library>,
<domain_library>, <domain_participant_library>, <application_library>;
452ffeb7f84). Über das Protokoll: ein CREATE mit XML von QosProfile, Type,
Application oder DomainParticipant legt eine Definition an, die andere Clients
per Referenz nutzen, solange das Objekt des anlegenden Clients besteht
(9d5c64dc398).
§7.7.3.1.1 Beispiel einer Referenz
Spec: §7.7.3.1.1, S. 28 — “The following string is an example of an object_reference used to represent an XRCE QosProfile: ‘MyQosLibrary::MyQosProfile’.”
Repo: —
Tests: —
Status: n/a (informative) — Beispiel.
§7.7.3.1.1 Arten mit Referenz
Spec: §7.7.3.1.1, S. 28 — “This format is available for the XRCE Object kinds that can be configured as libraries in the XRCE Agent. These are XRCE Type, QosProfile, Domain, DomainParticipan, and Application.”
Repo: crates/xrce-agent/src/daemon/session.rs (format_is_allowed); crates/xrce-agent/src/daemon/config.rs (Schlüssel
representation_formats)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::the_formats_of_each_kind_are_enforced,
crates/xrce-agent/src/daemon/session.rs::tests::references_resolve_against_the_profile_files,
crates/xrce-agent/src/daemon/config.rs::tests::the_representation_formats_can_be_widened
Status: done — Vorgabe ist die Lesart von Annex A: Referenz für Participant und Topic
(OBJK_Representation3_Base) sowie Type, QosProfile und Application
(OBJK_RepresentationRefAndXML_Base); Publisher, Subscriber, DataWriter und
DataReader haben nur Binär und XML. Die Spec widerspricht sich: OBJK_TOPIC_Representation
hat eine Referenz (§7.7.3.7.1, S. 33), §8.4.10 und §8.4.11 (S. 82–83) nennen sie
auch für DataWriter und DataReader. Die andere Lesart ist die Einstellung
representation_formats: any (0429eab4fb2); beide sind getestet.
§7.7.3.1.2 XML nach DDS-XML
Spec: §7.7.3.1.2, S. 28–29 — “The string shall contain an XML element formatted according to the [DDS-XML] specification. The format of the string is defined for each Object kind in clauses 7.7.3.2 to 7.7.3.11.”
Repo: crates/xrce-agent/src/daemon/entity_repr.rs; crates/xrce-agent/src/daemon/definitions.rs
Tests: crates/xrce-agent/tests/spec_items_session.rs::a_type_by_reference_names_a_known_type_by_its_fully_qualified_name, crates/xrce-agent/tests/spec_items_session.rs::a_subscriber_in_xml_has_its_qos_and_its_nested_data_reader
Status: done — Type, QosProfile, Application, DomainParticipant (mit den enthaltenen Objekten), Topic, Publisher, Subscriber, DataWriter und DataReader werden nach DDS-XML gelesen (9d5c64dc398, b97657ef4ec). Ein <types> darf auf bereits bekannte Typen verweisen (Item zu §7.7.3.3.2). Eine Domain mit CREATE anzulegen definiert die Spec nicht (§7.7.3.4).
### §7.7.3.1.2 Formen von DDS-XML für Entitäten
Spec: §7.7.3.1.2, S. 28–29 — wie oben.
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (endpoint_from_xml, container_from_xml, topic_from_xml, apply_qos_profile); crates/xrce-agent/src/daemon/definitions.rs
Tests: crates/xrce-agent/tests/spec_items_session.rs::a_subscriber_in_xml_has_its_qos_and_its_nested_data_reader, crates/xrce-agent/tests/spec_items_session.rs::a_data_reader_in_xml_has_its_qos_and_its_content_filter, crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_qos_of_a_topic_is_the_default_of_its_endpoints
Status: done — gelesen und getestet: register_type_ref, topic_ref als Name des Topic, <datawriter_qos>/<datareader_qos> mit base_name, qos_profile_ref, <publisher_qos>, <subscriber_qos>, <topic_qos>, <domain_participant_qos>, <content_filter> und die Bibliotheken <qos_library>, <domain_library>, <domain_participant_library>, <application_library> (9d5c64dc398, b97657ef4ec, 3906abf91b8, 02c704651e4).
### §7.7.3.1.2 XML für die Konfiguration aus der Ferne
Spec: §7.7.3.1.2, S. 29 — “This format is intended for remotely configuring the agent. Typically it will not be used by the XRCE Clients except in deployments where the client-to-agent connection has sufficient bandwidth.”
Repo: —
Tests: —
Status: n/a (informative) — Hinweis. Das Beispiel darunter (S. 29) hat
falsch geschlossene Elemente (<reliability>, <data_reader_qos>,
<qos_library>).
§7.7.3.1.3 Binär als XCDR2 der Struktur der Art
Spec: §7.7.3.1.3, S. 28 — “The REPRESENTATION_IN_BINARY represents objects using a binary_representation octet sequence. The octet sequence is the result of serializing an IDL-defined data-structure that depends on the kind of object using the XCDR version 2 format defined in [DDS-XTYPES].”
Repo: crates/xrce-agent/src/daemon/binary_forms.rs (participant, topic, container, endpoint:
XCDR2-Leser); crates/xrce-agent/src/daemon/entity_repr.rs (Cdr: die Strukturen des
eProsima-Micro-XRCE-DDS-Client 3.0.1 als weitere Lesart)
Tests: crates/xrce-agent/src/daemon/binary_forms.rs::tests::annex_a_topic_has_a_dheader,
crates/xrce-agent/src/daemon/binary_forms.rs::tests::the_36_octet_example_of_the_clause_is_a_topic,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_captured_binary_topic_names_its_topic_and_type,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_big_endian_binary_topic_reads_back,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_blob_of_no_form_is_refused_naming_each_reading
Status: done — die sequence<octet> wird als XCDR2 der Struktur der Art gelesen, in
beiden Formen der Spec (Annex A mit DHEADER, die Abschnitte als FINAL); ein
Blob, der keine der Formen ist, wird mit Nennung jeder Lesart abgewiesen. Die
Strukturen von eProsima (klassisches CDR) bleiben als weitere Lesart
(f548fee2522).
§7.7.3.1.3 Binärformen nach §7.7.3 und Annex A
Spec: §7.7.3.1.3, S. 28 — wie oben.
Repo: crates/xrce-agent/src/daemon/binary_forms.rs (participant, topic, container,
endpoint); crates/xrce-agent/src/daemon/entity_repr.rs (participant, topic, container,
endpoint)
Tests: crates/xrce-agent/src/daemon/binary_forms.rs::tests::participant_binary_in_both_forms,
crates/xrce-agent/src/daemon/binary_forms.rs::tests::annex_a_topic_has_a_dheader,
crates/xrce-agent/src/daemon/binary_forms.rs::tests::publisher_binary_of_annex_a,
crates/xrce-agent/src/daemon/binary_forms.rs::tests::writer_binary_of_annex_a_with_qos,
crates/xrce-agent/src/daemon/binary_forms.rs::tests::reader_binary_of_the_clause,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::an_annex_a_binary_writer_names_its_topic_and_qos,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_clause_binary_reader_names_its_topic_and_qos,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_spec_binary_participant_is_read
Status: done — Participant, Topic, Publisher, Subscriber, DataWriter und DataReader
werden in der Form von Annex A (DHEADER) und der Form der Abschnitte gelesen:
string topic_name bei DataWriter und DataReader, TypeIdentifier und
type_reference beim Topic, die Binärform des Participant (f548fee2522).
§7.7.3.1.3 Beispiel OBJK_Topic_Binary mit 36 Byte
Spec: §7.7.3.1.3, S. 29 — Topic “Square”, type_reference
“MyTypes::ShapeType”, 36 Byte little-endian.
Repo: crates/xrce-agent/src/daemon/binary_forms.rs (topic); crates/xrce-agent/src/daemon/entity_repr.rs (topic)
Tests: crates/xrce-agent/src/daemon/binary_forms.rs::tests::the_36_octet_example_of_the_clause_is_a_topic,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_spec_binary_topic_names_its_topic_and_type
Status: done — der Test dekodiert die 36 Byte des Beispiels als Topic mit
type_reference „MyTypes::ShapeType“. Die Zeichen des Beispiels lauten
‘S’,‘q’,‘u’,‘e’,‘r’,‘e’; binary_forms liest sie so (743676fca9f), der Text der
Spec nennt das Topic „Square“. Zusätzlich liest entity_repr dieselbe Struktur
mit „Square“ als 36-Byte-Blob (f548fee2522).
§7.7.3.2 XRCE QosProfile
§7.7.3.2 OBJK_QOSPROFILE_Representation
Spec: §7.7.3.2, S. 29 — “struct OBJK_QOSPROFILE_Representation : OBJK_RepresentationRefAndXML_Base { };”
Repo: crates/xrce/src/object_repr.rs (decode_for_kind, kein
nachgestelltes Feld für ObjectKind::QosProfile)
Tests: crates/xrce/src/object_repr.rs::tests::encode_for_kind_round_trips_every_objk_kind_with_its_own_trailing_field
Status: done — Kodierung; die Wirkung steht in den folgenden Items.
§7.7.3.2.1 Referenz auf ein QosProfile „Lib::Profile“
Spec: §7.7.3.2.1, S. 29 — “the object_reference field shall contain the fully qualified name of a QosProfile known to the XRCE Agent. The fully qualified name is composed of the name of the Qos library and the name of the QosProfile within the library.”
Repo: crates/xrce-agent/src/daemon/session.rs (plan_dds_create, Zweig OBJK_QOSPROFILE); crates/xrce-agent/src/daemon/profiles.rs
(AgentProfiles::qos_profile)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::what_a_configuration_client_defines_is_referenced_by_another_client
Status: done — CREATE(OBJK_QOSPROFILE) mit REPRESENTATION_BY_REFERENCE löst „Lib::Profile“
gegen die QoS-Bibliotheken der Dateien und der Definitionen anderer Clients
auf; ein Name in keiner Bibliothek ist STATUS_ERR_UNKNOWN_REFERENCE
(9d5c64dc398).
§7.7.3.2.2 XML mit einer qos_library und einem qos_profile
Spec: §7.7.3.2.2, S. 29 — “the string_representation field shall contain a
single
Repo: crates/xrce-agent/src/daemon/session.rs (SessionEngine::definition_to_register)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::type_and_qos_profile_xml_follow_their_clauses
Status: done — die <qos_library> mit genau einem <qos_profile> wird gelesen und als
Definition gespeichert; eine Bibliothek mit zwei Profilen ist
STATUS_ERR_INVALID_DATA (b97657ef4ec).
§7.7.3.2.2 Verweis auf andere QosProfiles
Spec: §7.7.3.2.2, S. 29–30 — “The REPRESENTATION_AS_XML_STRING
representation may reference other QoS profiles already known to the Agent.
[…]
Repo: crates/xrce-agent/src/daemon/session.rs (SessionEngine::definition_to_register); crates/xrce-agent/src/daemon/profiles.rs
(AgentProfiles::qos_profile)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::type_and_qos_profile_xml_follow_their_clauses
Status: done — base_name mit einem Doppelpunkt („Q:One“) wird wie „Q::One“ gelesen;
das Profil erbt vom Profil, das der Agent kennt (b97657ef4ec). Das Beispiel
schreibt base_name mit einem Doppelpunkt, §7.7.3.2.1 verlangt „::“.
§7.7.3.3 XRCE Type
§7.7.3.3 OBJK_TYPE_Representation
Spec: §7.7.3.3, S. 30 — “struct OBJK_TYPE_Representation : OBJK_RepresentationRefAndXML_Base { };”
Repo: crates/xrce/src/object_repr.rs (decode_for_kind)
Tests: crates/xrce/src/object_repr.rs::tests::encode_for_kind_round_trips_every_objk_kind_with_its_own_trailing_field,
crates/xrce-agent/src/daemon/session.rs::tests::the_formats_of_each_kind_are_enforced,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_binary_complete_type_object_is_named_by_its_own_type_name
Status: done — Kodierung. REPRESENTATION_IN_BINARY für OBJK_TYPE ist mit der
Vorgabe representation_formats: spec STATUS_ERR_INVALID_DATA (Item „Erlaubte
Formate je Art“); mit any liest entity_repr::types einen
TypeObject.
§7.7.3.3.1 Referenz auf einen Typ mit Modulen
Spec: §7.7.3.3.1, S. 30 — “the object_reference field shall contain the fully qualified name of an XRCE Type known to the XRCE Agent. The fully qualified name is composed of the name of the type prepended by the names of the enclosing modules.”
Repo: crates/xrce-agent/src/daemon/session.rs (plan_dds_create, find_type_definition)
Tests: crates/xrce-agent/tests/spec_items_session.rs::a_type_by_reference_names_a_known_type_by_its_fully_qualified_name
Status: done — CREATE(OBJK_TYPE) mit REPRESENTATION_BY_REFERENCE löst den Namen (MyModule::ShapeType) gegen die Typen des Clients, der Dateien (<types>), der Definitionen anderer Clients und von type_files: auf; ein unbekannter Name, auch ohne Modul, ist STATUS_ERR_UNKNOWN_REFERENCE (9d5c64dc398, 02c704651e4).
### §7.7.3.3.2 XML mit types, ein Typ mit nested=false
Spec: §7.7.3.3.2, S. 30 — “the string_representation field shall contain a
single
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (types, nested_flags);
crates/xrce-agent/src/daemon/session.rs (DdsCreate::Types)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::type_and_qos_profile_xml_follow_their_clauses,
crates/xrce-agent/src/daemon/session.rs::tests::a_topic_gets_the_type_its_type_name_names,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::an_xml_type_library_compiles_to_named_complete_types
Status: done — <types> wird nach DDS-XML gelesen und übersetzt; alle benannten Typen
werden registriert. Bei mehreren Typen muss genau einer nested nicht tragen,
sonst STATUS_ERR_INVALID_DATA (b97657ef4ec). Ein Topic findet seinen Typ über
den Namen (SessionEngine::resolve_type).
§7.7.3.3.2 Annotation nested
Spec: §7.7.3.3.2, S. 30 — wie oben.
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (types, nested_flags)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::type_and_qos_profile_xml_follow_their_clauses
Status: done — nested_flags liest die Annotation je Typ (auch in Modulen); zwei Typen
ohne nested="true" sind STATUS_ERR_INVALID_DATA, ein Typ ohne und einer mit
nested="true" ist STATUS_OK (b97657ef4ec).
§7.7.3.3.2 Verweis auf bekannte Typen
Spec: §7.7.3.3.2, S. 30 — “The string_representation may reference other Types already known to the Agent.”
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (types); crates/xrce-agent/src/daemon/session.rs (plan_dds_create, ObjectKind::Type); crates/xml/src/typeobject_bridge.rs (bridge_library_complete_with_known)
Tests: crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_types_string_may_reference_types_the_agent_knows, crates/xrce-agent/src/daemon/session.rs::tests::a_types_string_references_a_type_created_before
Status: done — types übergibt zerodds_xml::bridge_library_complete_with_known(lib, known) die dem Agenten bekannten Typen: die vom selben Client angelegten, die aus type_files: und die der Profildateien. Ein Verweis auf einen von ihnen wird zu dessen EquivalenceHashComplete, der bekannte Typ wird nicht noch einmal definiert. Ein Name, der weder in der Zeichenkette steht noch bekannt ist, ist STATUS_ERR_UNKNOWN_REFERENCE. Nicht geprüft: ob ein Verweis auf einen Typ gelingt, den ein anderer Client binär (nicht als XML <types>) angelegt hat; die Typen aus XML-<types> gehören den Definitionen des Agenten (§9.2).
§7.7.3.4 XRCE Domain
§7.7.3.4 OBJK_DOMAIN_Representation
Spec: §7.7.3.4, S. 30–31 — “struct OBJK_DOMAIN_Representation : OBJK_RepresentationRefAndXML_Base { };”
Repo: —
Tests: —
Status: n/a (informative) — Die Spec gibt Domain keinen Wert von ObjectKind und keinen Fall in ObjectVariant (§7.7.5, S. 39; Annex A, S. 103 und S. 111): ein CREATE kann keine Domain benennen, es gibt nichts, was erfüllt werden kann. Kind 0x0F ist OBJK_OTHER (daf2a618f74). Domains kommen aus <domain_library> der Dateien und sind als Library::Domain referenzierbar (domain_ref, domain_reference).
### §7.7.3.4.1 Referenz auf eine Domain „Lib::Domain“
Spec: §7.7.3.4.1, S. 31 — “the object_reference field shall contain the
fully qualified name of an XRCE Domain definition known to the Agent.”
Repo: crates/xrce-agent/src/daemon/definitions.rs (domain, domain_scope); crates/xrce-agent/src/daemon/entity_repr.rs (participant)
Tests: crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_domain_reference_is_resolved_against_the_domain_libraries
Status: done — eine Domain ist als „Lib::Domain“ referenzierbar: domain_ref des DomainParticipant in XML und domain_reference der Binärform werden gegen die <domain_library> der Dateien aufgelöst (452ffeb7f84, 0b67c04800c). Als object_reference eines CREATE kann sie nicht stehen, weil die Spec der Domain keine ObjectKind gibt (§7.7.3.4).
### §7.7.3.4.2 XML mit domain_library und einer domain
Spec: §7.7.3.4.2, S. 31 — “The XML shall contain a single
Repo: crates/xrce-agent/src/daemon/definitions.rs (add_domain_library)
Tests: crates/xrce-agent/src/daemon/definitions.rs::tests::a_participant_library_and_inheritance
Status: done — die <domain_library> mit ihren <domain> wird aus den Dateien gelesen (auch als Wurzel; base_name, register_type, topic; 452ffeb7f84). Eine Domain als Inhalt eines CREATE definiert die Spec nicht (§7.7.3.4).
§7.7.3.5 XRCE Application
§7.7.3.5 OBJK_APPLICATION_Representation
Spec: §7.7.3.5, S. 31 — “The OBJK_TYPE_Representation supports the REPRESENTATION_BY_REFERENCE and REPRESENTATION_AS_XML_STRING formats. […] struct OBJK_APPLICATION_Representation : OBJK_RepresentationRefAndXML_Base { };”
Repo: crates/xrce/src/object_repr.rs (decode_for_kind);
crates/xrce-agent/src/lib.rs (XrceAgent::create_object)
Tests: crates/xrce-agent/src/lib.rs::tests::create_application_object_via_objk_application,
crates/xrce-agent/src/daemon/session.rs::tests::the_formats_of_each_kind_are_enforced
Status: done — Kodierung und Speicherung. Der Satz nennt OBJK_TYPE_Representation
statt OBJK_APPLICATION_Representation. Ein CREATE in Binär ist
STATUS_ERR_INVALID_DATA (Item „Erlaubte Formate je Art“).
§7.7.3.5.1 Referenz auf eine Application „Lib::App“
Spec: §7.7.3.5.1, S. 31 — “the object_reference field shall contain the fully qualified name of an XRCE Application definition known to the Agent.”
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (application_definition); crates/xrce-agent/src/daemon/definitions.rs
(SystemDefinitions::application)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::what_a_configuration_client_defines_is_referenced_by_another_client,
crates/xrce-agent/src/daemon/session.rs::tests::a_create_client_makes_the_objects_configured_for_the_client
Status: done — „Lib::App“ wird gegen die <application_library> der Dateien und der
Definitionen anderer Clients aufgelöst; das CREATE legt den DomainParticipant
der Application mit allem darin an. Eine unbekannte Application ist
STATUS_ERR_UNKNOWN_REFERENCE (9d5c64dc398, 2ba972cd270).
§7.7.3.5.2 XML mit application_library und einer application
Spec: §7.7.3.5.2, S. 31–32 — “The XML shall contain a single
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (application_definition); crates/xrce-agent/src/daemon/definitions.rs
(SystemDefinitions::add_application_library)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::what_a_configuration_client_defines_is_referenced_by_another_client,
crates/xrce-agent/src/daemon/definitions.rs::tests::the_example_file_defines_the_objects_of_table_16,
crates/xrce-agent/src/daemon/definitions.rs::tests::what_cannot_be_planned_is_refused
Status: done — die <application_library> mit einer <application> wird gelesen; ihre
Participants verweisen auf Typen, QoS-Profile, Domains und DomainParticipants
der Definitionen (9d5c64dc398). Das Beispiel (S. 32) legt im Subscriber ein
<data_writer name="MyReader" topic_ref="Circle"> an, obwohl nur „Square“
definiert ist; der Code weist ein topic_ref auf ein Topic, das der
Participant nicht hat, ab.
§7.7.3.6 XRCE DomainParticipant
§7.7.3.6 OBJK_PARTICIPANT_Representation mit domain_id
Spec: §7.7.3.6, S. 32 — “struct OBJK_PARTICIPANT_Representation : OBJK_Representation3_Base { short domain_id; };”
Repo: crates/xrce/src/object_repr.rs (encode_for_kind:
Ausrichtung auf 2 vor domain_id)
Tests: crates/xrce/src/object_repr.rs::tests::participant_representation_matches_the_captured_create_bytes
Status: done
§7.7.3.6.1 Referenz auf einen DomainParticipant
Spec: §7.7.3.6.1, S. 32 — “the object_reference field shall contain the fully qualified name of an XRCE DomainParticipant definition known to the Agent. The fully qualified name is composed of the name of the DomainParticipant library and the name of the DomainParticipant within the library.”
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (participant, participant_definition); crates/xrce-agent/src/daemon/definitions.rs
(SystemDefinitions::participant)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_client_writes_through_a_preconfigured_data_writer_without_a_create,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_reference_is_read_like_the_profile_it_names
Status: done — die Referenz löst sich gegen <participant profile_name> einer
Profildatei und gegen die <domain_participant_library> auf („Lib::Participant“,
bei einer Application „Lib::App::Participant“); die Domain kommt aus der
Definition (domain_id oder domain_ref) oder aus dem Profil
(9d5c64dc398, 2ba972cd270).
§7.7.3.6.2 XML mit domain_participant_library
Spec: §7.7.3.6.2, S. 32 — “the string_representation field shall contain a
single
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (participant_definition, participant_source);
crates/xrce-agent/src/daemon/definitions.rs (SystemDefinitions::add_participant_library, plan_participant)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_participant_definition_creates_the_objects_inside_it,
crates/xrce-agent/src/daemon/session.rs::tests::a_participant_definition_with_a_broken_part_creates_nothing,
crates/xrce-agent/src/daemon/definitions.rs::tests::a_participant_library_and_inheritance
Status: done — die <domain_participant_library> mit einem <domain_participant> wird
gelesen; das CREATE legt die enthaltenen Topics, Publisher, Subscriber und
Endpunkte mit an (ObjectId aus dem Namen) und aktiviert sie mit dem Participant.
Schlägt ein Teil fehl, bleibt nichts zurück (9d5c64dc398).
§7.7.3.6.3 OBJK_DomainParticipant_Binary
Spec: §7.7.3.6.3, S. 33 — “struct OBJK_DomainParticipant_Binary { long domain_id; @optional string<128> domain_reference; @optional string<128> qos_profile_reference; };”
Repo: crates/xrce-agent/src/daemon/binary_forms.rs (participant); crates/xrce-agent/src/daemon/entity_repr.rs (participant)
Tests: crates/xrce-agent/src/daemon/binary_forms.rs::tests::participant_binary_in_both_forms,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_spec_binary_participant_is_read
Status: done — drei Lesarten des Blobs: Annex A (DHEADER, ohne domain_id), die Form
der Abschnitte (long domain_id zuerst, FINAL) und die zwei Oktette 00 00 des
eProsima-Client. domain_id der Binärform und die der Repräsentation (short)
müssen übereinstimmen, sonst STATUS_ERR_INVALID_DATA (f548fee2522).
§7.7.3.6.3 domain_reference
Spec: §7.7.3.6.3, S. 33 — “Any XRCE Topic and Type definitions contained in the referenced domain are considered defined within the scope of the XRCE DomainParticipant and become available as references to construct XRCE objects contained by the DomainParticipant.”
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (participant); crates/xrce-agent/src/daemon/definitions.rs (domain_scope)
Tests: crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_domain_reference_is_resolved_against_the_domain_libraries
Status: done — domain_reference wird gegen die Domains der <domain_library> aufgelöst; die domain_id der Domain gilt für den Participant und muss mit long domain_id der Binärform übereinstimmen; ein Name in keiner Bibliothek ist STATUS_ERR_UNKNOWN_REFERENCE (0b67c04800c). Topics und Typen der Domain stehen im Geltungsbereich des Participant (f59909a7f2b, siehe das nächste Item).
### §7.7.3.6.3 Topics und Typen der Domain bei der Binärform
Spec: §7.7.3.6.3, S. 33 — wie oben.
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (ParticipantDescription::scope); crates/xrce-agent/src/daemon/session.rs (participant_scopes); crates/xrce-agent/src/daemon/definitions.rs (SystemDefinitions::domain_scope)
Tests: crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_domain_reference_is_resolved_against_the_domain_libraries
Status: done — bei der Binärform mit domain_reference stehen die register_type und Topics der Domain im Geltungsbereich des Participant wie beim XML-Participant mit domain_ref; ein Topic des Participant findet sie über den Namen (f59909a7f2b).
### §7.7.3.6.3 qos_profile_reference
Spec: §7.7.3.6.3, S. 33 — “If specified, the corresponding DDS DomainPaticipant shall be created using that Qos. Otherwise, the DomainPaticipant shall be created using the DDS default Qos.”
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (participant, participant_qos_of); crates/xrce-agent/src/daemon/dds_port.rs
(DdsPort::create_participant_with)
Tests: crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_participant_qos_profile_reference_is_applied
Status: done — das Participant-QoS des Profils (<domain_participant_qos>) gilt je
Participant: ENTITY_FACTORY beim Participant (bei autoenable_created_entities
false bleiben seine Publisher, Subscriber und Topics deaktiviert), USER_DATA über
eine eigene DCPS-Laufzeit je Domain und Wert. Eine andere Policy im Participant-QoS
steht nicht im XSD von DDS-XML 1.0: crates/xml weist die Datei beim Lesen ab
(Test a_participant_policy_outside_the_schema_is_refused); trägt ein aufgelöstes
Profil sie trotzdem, ist es STATUS_ERR_INCOMPATIBLE. Es gibt keine Policy, die das
Schema im Participant-QoS erlaubt und die der Agent nicht anwenden kann (USER_DATA
und ENTITY_FACTORY werden beide angewendet). Ein Profil ohne Participant-QoS wendet nichts an;
ohne Referenz gilt das DDS-Default-QoS (0b67c04800c).
§7.7.3.7 XRCE Topic
§7.7.3.7 OBJK_TOPIC_Representation mit participant_id
Spec: §7.7.3.7, S. 33 — “struct OBJK_TOPIC_Representation : OBJK_Representation3_Base { ObjectId participant_id; };”
Repo: crates/xrce/src/object_repr.rs (ObjectVariant::decode_for_kind_at,
ObjectVariantExtra::parent: ObjectId ohne Ausrichtung hinter der Variante)
Tests: crates/xrce/src/object_repr.rs::tests::topic_representation_matches_the_captured_create_bytes,
crates/xrce/src/object_repr.rs::tests::encode_for_kind_round_trips_every_objk_kind_with_its_own_trailing_field
Status: done
§7.7.3.7 Topic gehört zum DomainParticipant
Spec: §7.7.3.7, S. 33 — “Independent of the representation format, the field participant_id shall contain the ObjectId of an XRCE DomainParticipant object. The referenced or created Topic will belong to the specified DomainParticipant.”
Repo: crates/xrce-agent/src/daemon/session.rs (SessionEngine::plan_dds_create,
Zweig ObjectKind::Topic; participant_of_create)
Tests: crates/xrce-agent/tests/replay_foreign_session.rs::replay_creates_the_dds_entities_the_real_clients_describe,
crates/xrce-agent/src/daemon/session.rs::tests::a_topic_is_created_by_name_or_by_register_type_ref,
crates/xrce-agent/src/daemon/dds_port.rs::tests::null_port_rejects_topic_before_participant
Status: done — Art und Existenz des Participant werden geprüft (falsche Art: STATUS_ERR_INVALID_DATA, fehlender Participant: STATUS_ERR_UNKNOWN_REFERENCE), das Topic wird mit ihm angelegt. Getestet sind das Anlegen unter dem Participant und die Reihenfolge auf Port-Ebene; einen Test des Fehlerwegs eines Topic auf Sitzungsebene gibt es nicht (505c2e56d24).
§7.7.3.7.1 Referenz auf den Namen eines Topic im Participant
Spec: §7.7.3.7.1, S. 33 — “the object_reference field shall contain the bare name of an XRCE Topic defined in XRCE DomainParticipant identified by the participant_id. The Topic could be defined directly on the XRCE DomainParticipant, or else in the XRCE Domain associated with the DomainParticipant.”
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (topic, Zweig BY_REFERENCE:
ParticipantScope::topic, danach <topic profile_name> der Profildateien);
crates/xrce-agent/src/daemon/definitions.rs (SystemDefinitions::scope_of:
Topics des Participant und seiner Domain)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_topic_is_created_by_name_or_by_register_type_ref,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_reference_is_read_like_the_profile_it_names,
crates/xrce-agent/src/daemon/definitions.rs::tests::a_participant_library_and_inheritance
Status: done — der Name wird gegen die Topics des Participant und seiner
Domain aufgelöst; ein Name, den beide und die Profildateien nicht haben, ergibt
STATUS_ERR_UNKNOWN_REFERENCE. Der CREATE-Test nennt ein Topic des Participant;
die Topics der Domain prüft der Test von definitions.rs an der Planung eines
Participant (9d5c64dc398).
§7.7.3.7.2 XML mit einem topic
Spec: §7.7.3.7.2, S. 34 — “the string_representation field shall contain a
single
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (topic_from_xml)
Tests: crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_qos_of_a_topic_is_the_default_of_its_endpoints
Status: done — <topic name=… register_type_ref=…/> (das Beispiel der Spec) wird gelesen: die Registrierung wird im Participant und in seiner Domain gesucht, ihr Typ unter den dem Agent bekannten Typen; eine Registrierung, die der Participant nicht hat, ergibt STATUS_ERR_UNKNOWN_REFERENCE. Die Attributform (type_name) und <dataType> von Fast DDS bleiben lesbar. QoS und QosProfile-Verweise des Topic werden angewandt (nächstes Item). 9d5c64dc398.
### §7.7.3.7.2 QoS eines Topic und QosProfile-Verweise
Spec: §7.7.3.7.2, S. 34 — “The string_representation may reference XRCE Types or
QosProfiles already known to the XRCE Agent.”
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (TopicQos, topic_from_xml, endpoint_for_topic); crates/xrce-agent/src/daemon/session.rs (plan_dds_create)
Tests: crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_qos_of_a_topic_is_the_default_of_its_endpoints
Status: done — <topic_qos base_name=…> und qos_profile/qos_profile_ref des <topic> werden gelesen; was das Topic sagt, ist die Vorgabe der Endpunkte, die für es angelegt werden (DDS 1.4 §2.2.2.3.1), die Darstellung des Endpunkts selbst hat Vorrang; TOPIC_DATA gehört dazu. 3906abf91b8.
### §7.7.3.7.3 OBJK_Topic_Binary
Spec: §7.7.3.7.3, S. 34 — “struct OBJK_Topic_Binary { string<256> topic_name; @optional string<256> type_reference; @optional DDS:XTypes::TypeIdentifier type_identifier; };”
Repo: crates/xrce-agent/src/daemon/binary_forms.rs (topic, TopicBinary);
crates/xrce-agent/src/daemon/entity_repr.rs (topic, Zweig InBinary)
Tests: crates/xrce-agent/src/daemon/binary_forms.rs::tests::the_36_octet_example_of_the_clause_is_a_topic,
crates/xrce-agent/src/daemon/binary_forms.rs::tests::annex_a_topic_has_a_dheader,
crates/xrce-agent/src/daemon/binary_forms.rs::tests::string_bounds_are_checked,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_spec_binary_topic_names_its_topic_and_type,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_captured_binary_topic_names_its_topic_and_type,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_big_endian_binary_topic_reads_back
Status: done — XCDR2 nach §7.7.3.1.3: topic_name, optionales
type_reference, optionales type_identifier (TypeIdentifier), string<256>
geprüft. Die Spec gibt die Struktur doppelt an: Annex A als APPENDABLE mit
DHEADER, die Klausel als FINAL ohne. Beide Fassungen werden gelesen (Annex A
zuerst, die Form des Blobs entscheidet, kein Schalter), danach die Struktur des
eProsima-Client. Die 36 Oktette des Beispiels der Klausel schreiben „Squere“
(der Text: „Square“); der Test erwartet die Oktette. f548fee2522, 743676fca9f.
§7.7.3.7.3 type_identifier
Spec: §7.7.3.7.3, S. 34 — “The type_identifier, if present, shall contain the DDS-XTYPES TypeIdentifier for the data-type. See clause 7.3.2 of [DDS-XTYPES].”
Repo: crates/xrce-agent/src/daemon/binary_forms.rs (topic:
TypeIdentifier::decode_from); crates/xrce-agent/src/daemon/session.rs
(type_name_of, plan_dds_create, Zweig Topic)
Tests: crates/xrce-agent/src/daemon/binary_forms.rs::tests::a_topic_with_a_type_identifier_reads_it_and_one_without_a_type_is_refused,
crates/xrce-agent/src/daemon/binary_forms.rs::tests::string_bounds_are_checked,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_spec_binary_topic_may_name_its_type_by_identifier,
crates/xrce-agent/src/daemon/session.rs::tests::a_topic_can_name_its_type_by_type_identifier
Status: done — ein vorhandenes type_identifier wird als
XTypes-TypeIdentifier gelesen und mit den COMPLETE-Identifiern der dem Agent
bekannten Typen (OBJK_TYPE des Client, type_files:) verglichen; ein
Identifier ohne Treffer ergibt STATUS_ERR_UNKNOWN_REFERENCE. Die Grenzen
string<256> werden geprüft. f548fee2522.
§7.7.3.7.3 Nicht beide fehlen, type_identifier hat Vorrang
Spec: §7.7.3.7.3, S. 34 — “Either type_reference or type_identifier may be used to identify the XRCE Type associated with the Topic. Either member may be omitted, but not both. If both are present the type_identifier shall take precedence.”
Repo: crates/xrce-agent/src/daemon/session.rs (plan_dds_create); crates/xrce-agent/src/daemon/binary_forms.rs (topic)
Tests: crates/xrce-agent/tests/spec_items_session.rs::a_binary_topic_takes_its_type_from_the_type_identifier_and_needs_one_of_the_two
Status: done — fehlen beide Member, ergibt das STATUS_ERR_INVALID_DATA (dc2fb4c0cf5, f548fee2522); mit type_identifier allein wird der Typ gefunden; sind beide da, hat der Identifier Vorrang (02c704651e4).
### §7.7.3.7.3 type_reference auf einen bekannten Typ
Spec: §7.7.3.7.3, S. 34 — “The type_reference, if present, shall contain the fully qualified name of the type […]. The referenced type shall be known to the XRCE Agent either via pre-configuration, or as a result of a prior create operation executed on the XRCE ProxyClient; see 7.8.3.1.”
Repo: crates/xrce-agent/src/daemon/session.rs (SessionEngine::resolve_type,
find_type_definition, apply_dds_create, Zweig Topic)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_topic_gets_the_type_its_type_name_names,
crates/xrce-agent/src/daemon/session.rs::tests::a_configured_type_is_known_to_every_client,
crates/xrce-agent/src/daemon/session.rs::tests::a_topic_of_an_unknown_type_is_refused_when_the_agent_is_told_to
Status: done — der Typ wird zuerst unter den OBJK_TYPE des Client
(früheres CREATE), dann unter type_files: (Vorkonfiguration) gesucht; ein
Topic erhält die Definition des Typs, den sein Name nennt (Test mit zwei Typen
des Client). Ein unbekannter Typ ergibt STATUS_ERR_UNKNOWN_REFERENCE (Item
unten). 70963ac46ec.
§7.7.3.7.3 Topic mit unbekanntem Typ
Spec: §7.7.3.7.3, S. 34 — wie oben.
Repo: crates/xrce-agent/src/daemon/session.rs (apply_dds_create, Zweig Topic;
SessionEngineConfig::forward_unknown_topic_types);
crates/xrce-agent/src/daemon/config.rs (Schlüssel unknown_topic_types)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_topic_of_an_unknown_type_is_refused_when_the_agent_is_told_to,
crates/xrce-agent/src/daemon/config.rs::tests::unknown_topic_types_are_refused_unless_forwarding_is_named
Status: done — Standard ist die Spec: ein Topic, dessen Typ der Agent nicht
kennt, ergibt STATUS_ERR_UNKNOWN_REFERENCE, nichts wird abgelegt. Benannte
Einstellung: Agent-Schlüssel unknown_topic_types: forward legt das Topic an
und meldet SessionEvent::UnknownTypeForwarding; Samples gehen dann ohne
Schlüssel und ohne TypeInformation hinaus (der eProsima-Client nennt Typen,
die der Agent nicht hält). 70963ac46ec, 969c784c93b.
§7.7.3.8 XRCE Publisher
§7.7.3.8 OBJK_PUBLISHER_Representation mit participant_id
Spec: §7.7.3.8, S. 34 — “struct OBJK_PUBLISHER_Representation : OBJK_RepresentationBinAndXML_Base { ObjectId participant_id; };”
Repo: crates/xrce/src/object_repr.rs (ObjectVariant::decode_for_kind_at,
ObjectVariantExtra::parent)
Tests: crates/xrce/src/object_repr.rs::tests::encode_for_kind_round_trips_every_objk_kind_with_its_own_trailing_field
Status: done — Kodierung; die Prüfung steht im nächsten Item.
§7.7.3.8 Publisher gehört zum DomainParticipant
Spec: §7.7.3.8, S. 34 — “the member participant_id shall contain the ObjectId of an XRCE DomainParticipant object. The referenced or created Publisher shall belong to the specified DomainParticipant.”
Repo: crates/xrce-agent/src/daemon/session.rs (plan_dds_create, Zweig
Publisher/Subscriber; participant_of_create; apply_dds_create:
DdsPort::create_publisher)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_publisher_or_subscriber_needs_an_existing_participant,
crates/xrce-agent/src/daemon/session.rs::tests::a_publisher_and_a_subscriber_get_a_dds_entity_with_their_policies
Status: done — Art und Existenz des Participant werden geprüft (fehlender Participant: STATUS_ERR_UNKNOWN_REFERENCE, andere Art: STATUS_ERR_INVALID_DATA, nichts wird abgelegt); der Publisher wird als DDS-Publisher unter dem Participant angelegt. 505c2e56d24.
§7.7.3.8.1 XML mit einem publisher
Spec: §7.7.3.8.1, S. 34–35 — “the string_representation field shall
contain a single
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (container,
container_from_xml: <publisher_qos>, <qos>, eingebettete <data_writer>);
crates/xrce-agent/src/daemon/session.rs (create_embedded)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_publisher_with_nested_data_writers_creates_them,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::an_empty_container_xml_is_a_default_container,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_container_reads_presentation_and_entity_factory
Status: done — <publisher> mit <publisher_qos base_name=…> (PARTITION,
GROUP_DATA, PRESENTATION, ENTITY_FACTORY werden angewandt) und <qos> von Fast
DDS; Richtlinien, die ein Publisher nicht hat, werden in not_applied benannt.
Das Beispiel (S. 35) schließt <publisher name="MyPublisher"/> vor seinen
Kindelementen. 9d5c64dc398, b97657ef4ec.
§7.7.3.8.1 publisher_qos und eingebettete DataWriter
Spec: §7.7.3.8.1, S. 35 — wie oben.
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (container_from_xml:
ContainerDescription::embedded); crates/xrce-agent/src/daemon/session.rs
(create_embedded)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_publisher_with_nested_data_writers_creates_them
Status: done — eingebettete <data_writer> werden mit der ObjectId ihres
Namens (§9.3) unter dem Publisher angelegt; scheitert einer (im Test: ein Topic,
das der Participant nicht hat, STATUS_ERR_UNKNOWN_REFERENCE), scheitert das
CREATE des Publisher und es bleibt nichts zurück. b97657ef4ec.
§7.7.3.8.2 OBJK_Publisher_Binary
Spec: §7.7.3.8.2, S. 35 — “struct OBJK_PUBLISHER_QosBinary { @optional
sequence
Repo: crates/xrce-agent/src/daemon/binary_forms.rs (container);
crates/xrce-agent/src/daemon/entity_repr.rs (container, Zweig InBinary)
Tests: crates/xrce-agent/src/daemon/binary_forms.rs::tests::publisher_binary_of_annex_a,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::an_annex_a_binary_publisher_gives_its_partitions,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_captured_binary_publisher_has_default_qos
Status: done — partitions und group_data werden angewandt,
publisher_name wird gelesen und nicht verwendet. Annex A (APPENDABLE, DHEADER)
wird zuerst gelesen, danach die Fassung der Klausel ohne DHEADER, die auch der
eProsima-Client sendet. f548fee2522.
§7.7.3.9 XRCE Subscriber
§7.7.3.9 OBJK_SUBSCRIBER_Representation mit participant_id
Spec: §7.7.3.9, S. 35 — “struct OBJK_SUBSCRIBER_Representation : OBJK_RepresentationBinAndXML_Base { ObjectId participant_id; };”
Repo: crates/xrce/src/object_repr.rs (ObjectVariant::decode_for_kind_at)
Tests: crates/xrce/src/object_repr.rs::tests::subscriber_representation_matches_the_captured_create_bytes
Status: done — Kodierung.
§7.7.3.9 Subscriber gehört zum DomainParticipant
Spec: §7.7.3.9, S. 35 — “the member participant_id shall contain the ObjectId of an XRCE DomainParticipant object. The referenced or created Subscriber shall belong to the specified DomainParticipant.”
Repo: crates/xrce-agent/src/daemon/session.rs (plan_dds_create, Zweig
Publisher/Subscriber; participant_of_create; apply_dds_create:
DdsPort::create_subscriber)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_publisher_or_subscriber_needs_an_existing_participant,
crates/xrce-agent/src/daemon/session.rs::tests::a_publisher_and_a_subscriber_get_a_dds_entity_with_their_policies
Status: done — wie beim Publisher (derselbe Zweig, beide Arten in den Tests). 505c2e56d24.
§7.7.3.9.1 XML mit einem subscriber
Spec: §7.7.3.9.1, S. 35–36 — “the string_representation field shall
contain a single
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (container_from_xml); crates/xrce-agent/src/daemon/session.rs (create_embedded)
Tests: crates/xrce-agent/tests/spec_items_session.rs::a_subscriber_in_xml_has_its_qos_and_its_nested_data_reader
Status: done — der Code liest <subscriber> in denselben Zweigen wie <publisher> (9d5c64dc398); der Test legt ein <subscriber> mit <subscriber_qos> und Inhalt an (02c704651e4).
### §7.7.3.9.1 subscriber_qos und eingebettete DataReader
Spec: §7.7.3.9.1, S. 36 — wie oben.
Repo: crates/xrce-agent/src/daemon/session.rs (create_embedded); crates/xrce-agent/src/daemon/entity_repr.rs (container_from_xml)
Tests: crates/xrce-agent/tests/spec_items_session.rs::a_subscriber_in_xml_has_its_qos_and_its_nested_data_reader
Status: done — der Code legt die <data_reader> eines <subscriber> wie die <data_writer> eines <publisher> an (b97657ef4ec); der Test legt ein Subscriber mit eingebettetem <data_reader> per CREATE an und prüft Partition und Reader (02c704651e4).
### §7.7.3.9.2 OBJK_Subscriber_Binary
Spec: §7.7.3.9.2, S. 36 — “struct OBJK_SUBSCRIBER_QosBinary { @optional
sequence
Repo: crates/xrce-agent/src/daemon/binary_forms.rs (container);
crates/xrce-agent/src/daemon/entity_repr.rs (container, dieselbe
Leseroutine wie für den Publisher)
Tests: crates/xrce-agent/src/daemon/binary_forms.rs::tests::publisher_binary_of_annex_a,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::an_annex_a_binary_publisher_gives_its_partitions,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_captured_binary_publisher_has_default_qos
Status: done — die Tests lesen die Form des Publisher, die Leseroutine ist dieselbe. f548fee2522.
§7.7.3.10 XRCE DataWriter
§7.7.3.10 DATAWRITER_Representation mit publisher_id
Spec: §7.7.3.10, S. 36 — “struct DATAWRITER_Representation : OBJK_RepresentationBinAndXML_Base { ObjectId publisher_id; };”
Repo: crates/xrce/src/object_repr.rs (ObjectVariant::decode_for_kind_at)
Tests: crates/xrce/src/object_repr.rs::tests::encode_for_kind_round_trips_every_objk_kind_with_its_own_trailing_field,
crates/xrce/src/object_repr.rs::tests::annex_b_2_3_writer_variant_reads_as_the_blob_and_its_publisher
Status: done — Kodierung.
§7.7.3.10 DataWriter gehört zum Publisher
Spec: §7.7.3.10, S. 36 — “the member publisher_id shall contain the ObjectId of an XRCE Publisher object. The referenced or created DataWriter shall belong to the specified Publisher.”
Repo: crates/xrce-agent/src/daemon/session.rs (plan_dds_create, Zweig
DataWriter/DataReader)
Tests: crates/xrce-agent/tests/replay_foreign_session.rs::replay_creates_the_dds_entities_the_real_clients_describe,
crates/xrce-agent/src/daemon/session.rs::tests::an_endpoint_and_its_topic_belong_to_one_participant,
crates/xrce-agent/src/daemon/session.rs::tests::a_publisher_with_nested_data_writers_creates_them
Status: done — Art und Existenz des Publisher werden geprüft (fehlender Publisher: STATUS_ERR_UNKNOWN_REFERENCE), DataWriter und Topic müssen zu einem Participant gehören; der DataWriter erbt PARTITION und GROUP_DATA des Publisher.
§7.7.3.10.1 XML mit einem data_writer
Spec: §7.7.3.10.1, S. 36–37 — “the string_representation field shall
contain a single
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (endpoint,
endpoint_from_xml: Attributform, Form von Fast DDS, topic_ref als Name,
<datawriter_qos> / <data_writer_qos>)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_publisher_with_nested_data_writers_creates_them,
crates/xrce-agent/src/daemon/session.rs::tests::a_data_writer_states_its_qos_over_a_profile,
crates/xrce-agent/src/daemon/session.rs::tests::the_formats_of_each_kind_are_enforced,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_attribute_form_still_reads,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_eprosima_element_form_names_topic_type_and_kind,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_qos_profile_reference_applies_the_profile
Status: done — gelesen werden die Form von DDS-XML (<data_writer name=… topic_ref=…>, <datawriter_qos base_name=…>), die Attributform (topic_ref
als ObjectId in Hex, qos_profile, reliability) und die Form von Fast DDS.
Eine BY_REFERENCE-Darstellung hat ein DataWriter nach §7.7.3.1 nicht; der
Agent-Schlüssel representation_formats: any lässt sie zu (der eProsima-Client
benutzt sie). 9d5c64dc398, 0429eab4fb2.
§7.7.3.10.1 topic_ref als Name und data_writer_qos
Spec: §7.7.3.10.1, S. 36–37 — wie oben.
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (endpoint_from_xml: topic_ref,
datawriter_qos / data_writer_qos); crates/xrce-agent/src/daemon/session.rs
(resolve_topic)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_publisher_with_nested_data_writers_creates_them,
crates/xrce-agent/src/daemon/session.rs::tests::a_data_writer_states_its_qos_over_a_profile
Status: done — topic_ref="Square" wird als Name eines Topic des
Participant aufgelöst (0x… bleibt die ObjectId); <datawriter_qos base_name=…> wendet das Profil an, Richtlinien des Elements gehen darüber. Die
Schreibweise <data_writer_qos> der Klausel liest der Code ebenfalls; die Tests
benutzen <datawriter_qos>. Das Beispiel (S. 36) nennt den Container „XRCE
Susbcriber“. 9d5c64dc398.
§7.7.3.10.2 OBJK_DataWriter_Binary
Spec: §7.7.3.10.2, S. 37 — “struct OBJK_DataWriter_Binary { string topic_name; OBJK_Endpoint_QosBinary endpoint_qos; @optional unsigned long ownership_strength; };”
Repo: crates/xrce-agent/src/daemon/binary_forms.rs (endpoint, endpoint_qos);
crates/xrce-agent/src/daemon/entity_repr.rs (endpoint, Zweig InBinary,
apply_endpoint_binary)
Tests: crates/xrce-agent/src/daemon/binary_forms.rs::tests::writer_binary_of_annex_a_with_qos,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::an_annex_a_binary_writer_names_its_topic_and_qos,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_annex_b_binary_examples_read_as_their_qos,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_captured_binary_writer_is_reliable_keep_last_transient_local,
crates/xrce-agent/src/daemon/session.rs::tests::annex_b_2_3_create_of_a_binary_data_writer,
crates/xrce-agent/src/daemon/session.rs::tests::annex_b_2_4_create_of_a_binary_data_writer_with_qos
Status: done — topic_name, endpoint_qos und ownership_strength
(unsigned long). Annex A (APPENDABLE, qos optional) und die Klausel (FINAL,
endpoint_qos Pflicht) werden beide gelesen, Annex A zuerst, die Form des Blobs
entscheidet (kein Schalter); danach die Struktur des eProsima-Client (ObjectId topic_id, ownership_strength mit 64 Bit). Die Beispiele Annex B.2.3 und B.2.4
sind Byte für Byte getestet. Die Fassung der Klausel ist für den DataWriter
nicht eigens getestet, für den DataReader (Item unten) schon. f548fee2522,
b91241aebb1.
§7.7.3.10.2 EndpointQosFlags
Spec: §7.7.3.10.2, S. 37 — “@bit_bound(16) bitmask EndpointQosFlags { @position(0) is_reliable, @position(1) is_history_keep_last, @position(2) is_ownership_exclusive, @position(3) is_durability_transient_local, @position(4) is_durability_transient, @position(5) is_durability_persistent, };”
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (spec_flags,
apply_endpoint_binary; flags, endpoint_qos_from_binary)
Tests: crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_captured_binary_writer_is_reliable_keep_last_transient_local,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_binary_writer_with_every_optional_member_reads_back,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::an_annex_a_binary_writer_names_its_topic_and_qos,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_clause_binary_reader_names_its_topic_and_qos
Status: done — Bit 1 ist je Fassung is_history_keep_last (Klausel,
eProsima-Client) oder is_history_keep_all (Annex A, S. 110); die Fassung des
Blobs entscheidet (EndpointBinary::bit1_is_keep_all). Die Tests prüfen beide
Lesarten. f548fee2522.
§7.7.3.10.2 OBJK_Endpoint_QosBinary
Spec: §7.7.3.10.2, S. 37 — “struct OBJK_Endpoint_QosBinary {
EndpointQosFlags qos_flags; @optional unsigned short history_depth; @optional
unsigned long deadline_msec; @optional unsigned long lifespan_msec; @optional
sequence
Repo: crates/xrce-agent/src/daemon/binary_forms.rs (endpoint_qos);
crates/xrce-agent/src/daemon/entity_repr.rs (apply_endpoint_binary,
endpoint_qos_from_binary)
Tests: crates/xrce-agent/src/daemon/binary_forms.rs::tests::writer_binary_of_annex_a_with_qos,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_binary_writer_with_every_optional_member_reads_back,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_binary_endpoint_without_qos_gets_the_role_defaults,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_annex_b_binary_examples_read_as_their_qos
Status: done — qos_flags, history_depth, deadline_msec,
lifespan_msec und user_data (alle außer den Flags optional). f548fee2522.
§7.7.3.11 XRCE DataReader
§7.7.3.11 DATAREADER_Representation mit subscriber_id
Spec: §7.7.3.11, S. 38 — “struct DATAREADER_Representation : OBJK_RepresentationBinAndXML_Base { ObjectId subscriber_id; };”
Repo: crates/xrce/src/object_repr.rs (ObjectVariant::decode_for_kind_at)
Tests: crates/xrce/src/object_repr.rs::tests::encode_for_kind_round_trips_every_objk_kind_with_its_own_trailing_field,
crates/xrce/src/object_repr.rs::tests::annex_b_2_6_reader_with_default_qos
Status: done — Kodierung.
§7.7.3.11 DataReader gehört zum Subscriber
Spec: §7.7.3.11, S. 38 — “the member subscriber_id shall contain the ObjectId of an XRCE Subscriber object. The referenced or created DataReader will belong to the specified Subscriber.”
Repo: crates/xrce-agent/src/daemon/session.rs (plan_dds_create, Zweig
DataWriter/DataReader)
Tests: crates/xrce-agent/tests/replay_foreign_session.rs::replay_creates_the_dds_entities_the_real_clients_describe,
crates/xrce-agent/src/daemon/session.rs::tests::a_client_reads_through_a_preconfigured_data_reader_without_a_create
Status: done — Art und Existenz des Subscriber werden geprüft; der DataReader erbt PARTITION und GROUP_DATA des Subscriber.
§7.7.3.11.1 XML mit einem data_reader und Filtern
Spec: §7.7.3.11.1, S. 38 — “the string_representation field shall contain
a single
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (endpoint_from_xml)
Tests: crates/xrce-agent/tests/spec_items_session.rs::a_data_reader_in_xml_has_its_qos_and_its_content_filter
Status: done — getestet sind die Attributform, die Form von Fast DDS mit timeBasedFilter, ein <data_reader topic_ref=…> aus der Konfigurationsdatei und <data_reader_qos> mit <content_filter> (02c704651e4). Eine BY_REFERENCE-Darstellung hat ein DataReader nach §7.7.3.1 nicht; representation_formats: any lässt sie zu.
### §7.7.3.11.1 data_reader_qos und content_filter
Spec: §7.7.3.11.1, S. 38 — “
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (endpoint_from_xml, apply_qos_profile)
Tests: crates/xrce-agent/tests/spec_items_session.rs::a_data_reader_in_xml_has_its_qos_and_its_content_filter
Status: done — <content_filter><expression> setzt den Filter des Reader (das Attribut name wird nicht verwendet), <datareader_qos>/<data_reader_qos> wenden Profil und eigene Richtlinien an; der Test liest beide aus XML und prüft QoS und Filter am DDS-Port (02c704651e4, 9d5c64dc398).
### §7.7.3.11.2 OBJK_DataReader_Binary
Spec: §7.7.3.11.2, S. 38–39 — “struct OBJK_DataReader_Binary { string topic_name; OBJK_Endpoint_QosBinary endpoint_qos; @optional unsigned long timebasedfilter_msec; @optional string contentbased_filter; };”
Repo: crates/xrce-agent/src/daemon/binary_forms.rs (endpoint, endpoint_qos);
crates/xrce-agent/src/daemon/entity_repr.rs (endpoint, Zweig InBinary,
apply_endpoint_binary)
Tests: crates/xrce-agent/src/daemon/binary_forms.rs::tests::reader_binary_of_the_clause,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_clause_binary_reader_names_its_topic_and_qos,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_annex_b_binary_examples_read_as_their_qos,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_captured_binary_reader_is_reliable_keep_last_transient_local
Status: done — topic_name, endpoint_qos, timebasedfilter_msec und
contentbased_filter (als Filter des Reader angewandt). Fassung der Klausel und
Annex A werden wie beim DataWriter gelesen; Annex B.2.6 und B.2.7 sind Byte für
Byte getestet. Im Beispiel B.2.7 nennt der Text fünf Minuten, die Tabelle 180000
ms; gelesen werden die Oktette. f548fee2522, b91241aebb1.
§7.7.4 ObjectId
§7.7.4 ObjectId als octet[2] je Client und Agent
Spec: §7.7.4, S. 39 — “Each ObjectId is scoped to an XRCE Client and Agent pair. […] typedef octet ObjectId [2];”
Repo: crates/xrce/src/object_id.rs (ObjectId::to_bytes, ObjectId::from_bytes)
Tests: crates/xrce/src/object_id.rs::tests::bytes_are_big_endian,
crates/xrce/src/object_info.rs::tests::base_object_request_roundtrip
Status: done — die beiden Oktette in Reihenfolge, unabhängig vom E-Flag.
§7.7.5 ObjectKind
§7.7.5 Werte von ObjectKind
Spec: §7.7.5, S. 39 — “XRCE objects are classified into 14 kinds. […] typedef octet ObjectKind; const ObjectKind OBJK_INVALID = 0x00; […] OBJK_PARTICIPANT = 0x01; OBJK_TOPIC = 0x02; OBJK_PUBLISHER = 0x03; OBJK_SUBSCRIBER = 0x04; OBJK_DATAWRITER = 0x05; OBJK_DATAREADER = 0x06; OBJK_TYPE = 0x0A; OBJK_QOSPROFILE = 0x0B; OBJK_APPLICATION = 0x0C; OBJK_AGENT = 0x0D; OBJK_CLIENT = 0x0E;”
Repo: crates/xrce/src/object_kind.rs (Konstanten OBJK_*, ObjectKind::from_u8)
Tests: crates/xrce/src/object_kind.rs::tests::all_spec_kinds_roundtrip,
crates/xrce/src/object_kind.rs::tests::raw_const_values_match_spec,
crates/xrce/src/object_kind.rs::tests::unknown_byte_rejected
Status: done — 13 Werte: die zwölf des Textes und OBJK_OTHER = 0x0F (Annex
A). Der Text nennt 14 Arten und listet 12. daf2a618f74.
§7.7.6 ObjectIdPrefix
§7.7.6 ObjectId aus Präfix und ObjectKind
Spec: §7.7.6, S. 39 — “The ObjectId of an object is composed combining 12 bits from the ObjectIdPrefix and four bits from the ObjectKind. […] typedef octet ObjectIdPrefix [2]; […] object_id[0] = objectid_prefix[0] object_id[1] = (objectid_prefix[1]&0xF0) + object_kind”
Repo: crates/xrce/src/object_id.rs (ObjectId::new, ObjectId::kind,
ObjectId::from_reference)
Tests: crates/xrce/src/object_id.rs::tests::new_packs_kind_into_lower_4_bits,
crates/xrce/src/object_id.rs::tests::bytes_are_big_endian,
crates/xrce/src/object_id.rs::tests::from_reference_matches_the_examples_of_the_spec
Status: done — der Präfix ist im Code die 12-Bit-Zahl raw_id; ein Typ
ObjectIdPrefix fehlt. ObjectId::from_reference bildet den Präfix aus den
ersten 12 Bit des MD5 (§9.3, 468aa0940da). ObjectId::new_with_mask und
kind_mask deuten Bit 15 als „vom Client vergeben“; das steht nicht in der Spec
und wird von der Sitzung nicht benutzt.
§7.7.7 ResultStatus
§7.7.7 StatusValue
Spec: §7.7.7, S. 40 — “@bit_bound(8) enum StatusValue { @value(0x00) STATUS_OK, @value(0x01) STATUS_OK_MATCHED, @value(0x80) STATUS_ERR_DDS_ERROR, @value(0x81) STATUS_ERR_MISMATCH, @value(0x82) STATUS_ERR_ALREADY_EXISTS, @value(0x83) STATUS_ERR_DENIED, @value(0x84) STATUS_ERR_UNKNOWN_REFERENCE, @value(0x85) STATUS_ERR_INVALID_DATA, @value(0x86) STATUS_ERR_INCOMPATIBLE, @value(0x87) STATUS_ERR_RESOURCES };”
Repo: crates/xrce/src/object_info.rs (ResultStatusCode)
Tests: crates/xrce/src/object_info.rs::tests::result_status_code_all_ten_spec_values_roundtrip,
crates/xrce/src/object_info.rs::tests::result_status_code_unknown_byte_rejected
Status: done
§7.7.7 ResultStatus
Spec: §7.7.7, S. 40 — “struct ResultStatus { StatusValue status; octet implementation_status; };”
Repo: crates/xrce/src/object_info.rs (ResultStatus, encode_into, decode_at);
crates/xrce/src/encoding.rs (UnannotatedTypes)
Tests: crates/xrce/src/object_info.rs::tests::result_status_roundtrip,
crates/xrce/src/object_info.rs::tests::result_status_decode_short_returns_eof,
crates/xrce/tests/unannotated_types.rs::the_default_is_appendable_with_a_dheader,
crates/xrce/tests/unannotated_types.rs::the_final_setting_writes_the_reference_implementations_octets,
crates/xrce/tests/unannotated_types.rs::both_forms_are_read_in_either_setting
Status: done — Annex A gibt ResultStatus kein @extensibility: Standard
ist APPENDABLE mit DHEADER nach DDS-XTypes 1.3 §7.3.1.2.1.8 (6 Oktette, im
BaseObjectReply 10). Die Oktette der Referenzimplementierung (2 und 6, ohne
DHEADER) schreibt die Einstellung encoding::UnannotatedTypes::Final
(Agent-Schlüssel unannotated_types: final); beide Fassungen werden in jeder
Einstellung gelesen. 7f85e76debd, 220857a1e90.
§7.7.7 Table 2 STATUS_OK
Spec: §7.7.7, Table 2, S. 41 — “Indicates a successful execution of the operation”.
Repo: crates/xrce-agent/src/daemon/session.rs (status_reply, agent_status_reply)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::create_client_happy_path_registers_and_replies_ok,
crates/xrce-agent/src/daemon/session.rs::tests::a_successful_write_is_answered_with_status_ok,
crates/xrce-agent/tests/replay_foreign_session.rs::replay_matches_the_real_agents_create_client_create_and_delete_replies
Status: done — auch ein erfolgreiches WRITE_DATA wird mit STATUS_OK beantwortet (869304e6b63); der eProsima-Agent antwortet darauf nicht.
§7.7.7 Table 2 STATUS_OK_MATCHED
Spec: §7.7.7, Table 2, S. 41 — “Indicates a successful execution of a create or update operation on a resource when the resource already existed on the Agent and the resource state already matched the one requested by the operation.”
Repo: crates/xrce/src/object_store.rs (CreateOutcome::Reused);
crates/xrce-agent/src/daemon/session.rs (handle_create)
Tests: crates/xrce/src/object_store.rs::tests::create_reuse_returns_equal_marker,
crates/xrce-agent/src/daemon/session.rs::tests::a_create_with_reuse_and_replace_updates_the_object
Status: done — eine Darstellung, die der des vorhandenen Objekts gleicht,
ergibt bei reuse STATUS_OK_MATCHED und ändert nichts. Table 5 schreibt
STATUS_OK_MATCHES, StatusValue in Annex A und im Code heißt STATUS_OK_MATCHED
(nur der Name). 3b066516f69.
§7.7.7 Table 2 STATUS_ERR_DDS_ERROR
Spec: §7.7.7, Table 2, S. 41 — “Indicates a failure in the execution of the operation caused by an error when creating or operating on the DDS resource related to the operation.”
Repo: crates/xrce-agent/src/daemon/session.rs (dds_port_error_status,
apply_dds_create); crates/xrce-agent/src/daemon/dds_port.rs
(DdsPortError::DdsError, DdsPort::enable)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_dds_entity_is_enabled_when_the_creation_has_succeeded
Status: done — kann die DDS-Seite eines CREATE nicht freigegeben (enable)
oder angelegt werden, ist die Antwort STATUS_ERR_DDS_ERROR, nichts wird abgelegt
und die DDS-Seite gelöscht. 70963ac46ec.
§7.7.7 Table 2 STATUS_ERR_MISMATCH
Spec: §7.7.7, Table 2, S. 41 — “Indicates a failure in the execution of a create or update operation on a resource when the resource already existed on the Agent, the state did not match the one requested by the operation, and it was not possible to change the state of the resource.”
Repo: crates/xrce/src/object_store.rs (CreateOutcome::Reused { equal: false });
crates/xrce-agent/src/daemon/session.rs (handle_create)
Tests: crates/xrce/src/object_store.rs::tests::create_reuse_returns_equal_marker,
crates/xrce-agent/src/daemon/session.rs::tests::a_create_with_reuse_and_replace_updates_the_object
Status: done — reuse ohne replace und eine ungleiche Darstellung ergeben
STATUS_ERR_MISMATCH; mit replace wird das Objekt ersetzt (Table 5).
3b066516f69.
§7.7.7 Table 2 STATUS_ERR_ALREADY_EXISTS
Spec: §7.7.7, Table 2, S. 41 — “Indicates a failure in the execution of a create operation due to the fact that the resource already existed.”
Repo: crates/xrce/src/object_store.rs (CreateOutcome::Conflict)
Tests: crates/xrce/src/object_store.rs::tests::create_strict_on_existing_returns_conflict
Status: done
§7.7.7 Table 2 STATUS_ERR_DENIED
Spec: §7.7.7, Table 2, S. 41 — “Indicates a failure in the execution of an operation due to lack of permissions.”
Repo: crates/xrce-agent/src/daemon/access.rs (AccessController);
crates/xrce-agent/src/daemon/session.rs (Prüfung vor CREATE, DELETE,
GET_INFO, WRITE_DATA, READ_DATA)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_client_key_not_configured_in_the_agent_is_denied,
crates/xrce-agent/src/daemon/session.rs::tests::create_without_permission_is_denied_and_stores_nothing,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_and_delete_without_permission_are_denied,
crates/xrce-agent/src/daemon/session.rs::tests::write_and_read_without_permission_are_denied,
crates/xrce-agent/src/daemon/session.rs::tests::client_properties_are_checked_against_what_the_agent_requires,
crates/xrce-agent/src/daemon/session.rs::tests::an_update_needs_the_permission_to_update
Status: done — ein ClientKey, der nicht in authorized_client_keys steht,
eine fehlende Client-Property und eine Operation ohne Recht ergeben
STATUS_ERR_DENIED; nichts wird abgelegt. 1c430db8a67, 5f7a8652d95.
§7.7.7 Table 2 STATUS_ERR_UNKNOWN_REFERENCE
Spec: §7.7.7, Table 2, S. 41 — “Indicates a failure in the execution of an operation due to the fact that the referenced resource is not known to the Agent.”
Repo: crates/xrce-agent/src/daemon/session.rs (dds_port_error_status,
handle_delete, handle_get_info, participant_of_create)
Tests: crates/xrce-agent/src/daemon/dcps_bridge.rs::tests::full_chain_against_a_real_leased_domain,
crates/xrce-agent/src/daemon/dds_port.rs::tests::null_port_rejects_topic_before_participant,
crates/xrce-agent/src/daemon/session.rs::tests::a_publisher_or_subscriber_needs_an_existing_participant,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_a_missing_object_is_an_info_with_unknown_reference,
crates/xrce-agent/src/daemon/session.rs::tests::delete_client_needs_a_proxy_client
Status: done — die Tests prüfen DdsPortError::UnknownReference, einen
fehlenden Participant, ein fehlendes Objekt in GET_INFO und das Löschen des
Client ohne ProxyClient; dds_port_error_status bildet den Port-Fehler auf den
Wert ab.
§7.7.7 Table 2 STATUS_ERR_INVALID_DATA
Spec: §7.7.7, Table 2, S. 41 — “Indicates a failure in the execution due to wrong on invalid input parameter data.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create,
handle_read_data, refuse_unreadable)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::read_data_with_an_unhonorable_content_filter_is_rejected_not_silently_unfiltered,
crates/xrce-agent/src/daemon/session.rs::tests::a_request_that_cannot_be_read_is_answered_invalid_data,
crates/xrce-agent/src/daemon/session.rs::tests::a_create_without_a_base_object_request_is_answered,
crates/xrce-agent/src/daemon/session.rs::tests::the_formats_of_each_kind_are_enforced
Status: done — ein nicht lesbarer Body von CREATE, READ_DATA, WRITE_DATA, DELETE und GET_INFO, eine Darstellung in einem Format, das die Art nicht hat, und ein nicht erfüllbarer Filter ergeben STATUS_ERR_INVALID_DATA. 97de94f63e4, 0429eab4fb2.
§7.7.7 Table 2 STATUS_ERR_INCOMPATIBLE
Spec: §7.7.7, Table 2, S. 41 — “Indicates a failure in the execution of an operation due to an incompatibility between the Client and the Agent.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create_client,
handle_get_info: Version in client_info)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::create_client_rejects_wrong_major_version,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_the_agent_checks_the_version_in_client_info
Status: done
§7.7.7 Table 2 STATUS_ERR_RESOURCES
Spec: §7.7.7, Table 2, S. 41 — “Indicates a failure in the execution of an operation due to a resource error on the Agent.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create_client, create_core, handle_message, emit_possibly_fragmented, data_submessages)
Tests: crates/xrce-agent/tests/spec_items_session.rs::create_client_over_max_clients_is_a_resource_error, crates/xrce-agent/tests/spec_items_session.rs::create_over_max_objects_per_client_is_a_resource_error, crates/xrce-agent/tests/spec_items_session.rs::a_full_reorder_buffer_of_a_reliable_stream_is_a_resource_error, crates/xrce-agent/tests/spec_items_session.rs::a_fragment_run_over_its_limit_is_a_resource_error, crates/xrce-agent/src/daemon/session.rs::tests::a_sample_too_large_for_data_is_reported
Status: done — der Agent sendet den Wert bei max_clients, max_objects_per_client, vollem Puffer des Empfängers, einer FRAGMENT-Zusammensetzung über der Grenze und einem Sample, das nicht in ein DATA passt; jeder dieser Wege hat einen Test (8bcb1d00161, 02c704651e4). Ein INFO, das nicht kodiert werden kann, hat keinen Test.
§7.7.8 BaseObjectRequest
§7.7.8 BaseObjectRequest
Spec: §7.7.8, S. 41 — “@extensibility(FINAL) struct BaseObjectRequest { RequestId request_id; ObjectId object_id; };”
Repo: crates/xrce/src/object_info.rs (BaseObjectRequest)
Tests: crates/xrce/src/object_info.rs::tests::base_object_request_roundtrip,
crates/xrce/src/object_info.rs::tests::base_object_request_decode_short_returns_eof
Status: done — FINAL, 4 Oktette ohne DHEADER.
§7.7.8 request_id verknüpft Antwort und Anfrage
Spec: §7.7.8, S. 41–42 — “request_id (RequestId) identifies each request. It is used to correlate a reply with the related request. It is scoped to each XRCE Client and Agent pair. Note that it is possible to reuse a value of the request_id for future requests as long as the previous request with that value is known by Client and Agent to no longer be active.”
Repo: crates/xrce-client/src/lib.rs (allocate_request_id, request_id_octets);
crates/xrce-agent/src/daemon/session.rs (status_reply)
Tests: crates/xrce-client/src/lib.rs::tests::full_lifecycle_creates_unique_request_ids_and_real_submessages,
crates/xrce-agent/tests/replay_foreign_session.rs::replay_matches_the_real_agents_create_client_create_and_delete_replies
Status: done
§7.7.8 object_id als Ziel und Präfix
Spec: §7.7.8, S. 42 — “object_id (ObjectId) the ObjectId that is the target of the request. For requests that create objects, the object_id conveys the ObjectIdPrefix for the created object.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create: ObjectId aus
Präfix der Anfrage und Art der Darstellung)
Tests: crates/xrce-agent/tests/replay_foreign_session.rs::replay_matches_the_real_agents_create_client_create_and_delete_replies,
crates/xrce-agent/src/daemon/session.rs::tests::the_object_id_is_the_prefix_and_the_kind_of_the_representation
Status: done — für die Bildung der ObjectId beim CREATE siehe das Item zu
§7.8.3.1 „input_objectid“. 70963ac46ec.
§7.7.9 BaseObjectReply
§7.7.9 BaseObjectReply
Spec: §7.7.9, S. 42 — “@extensibility(FINAL) struct BaseObjectReply { BaseObjectRequest related_request; ResultStatus result; };”
Repo: crates/xrce/src/object_info.rs (BaseObjectReply)
Tests: crates/xrce/src/object_info.rs::tests::base_object_reply_roundtrip,
crates/xrce/tests/unannotated_types.rs::both_forms_are_read_in_either_setting
Status: done — FINAL: related_request (4 Oktette) und result; das
ResultStatus darin trägt seinen DHEADER (Item ResultStatus).
§7.7.9 related_request
Spec: §7.7.9, S. 42 — “related_request contains the request_id and object_id of the request that caused the reply to be sent […]. For requests that create objects, the object_id conveys the desired ObjectId for the created object.”
Repo: crates/xrce-agent/src/daemon/session.rs (status_reply)
Tests: crates/xrce-agent/tests/replay_foreign_session.rs::replay_matches_the_real_agents_create_client_create_and_delete_replies
Status: done
§7.7.9 status bei Erfolg und Fehler
Spec: §7.7.9, S. 42 — “If the operation succeeded the StatusValue shall be set to STATUS_OK or STATUS_OK_MATCHED. If it failed it shall be set to the value that corresponds to the type of error encountered.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create: Abbildung von
CreateOutcome auf den Status)
Tests: crates/xrce-agent/tests/replay_foreign_session.rs::replay_matches_the_real_agents_create_client_create_and_delete_replies,
crates/xrce-agent/src/daemon/session.rs::tests::a_create_with_reuse_and_replace_updates_the_object
Status: done — der Text nennt die Member status und
implementation_status; die Struktur hat result.
§7.7.9 implementation_status
Spec: §7.7.9, S. 42 — “implementation_status (octet) provides an implementation-specific (vendor-specific) return status. The value is scoped by the XrceVendorId of the Agent. It shall only be interpreted by clients that understand the implementation status values of the XrceVendorId of the Agent that returned it.”
Repo: crates/xrce-agent/src/daemon/session.rs (status_reply: Wert 0);
crates/xrce-client/src/lib.rs (handle_status wertet ihn nicht aus)
Tests: crates/xrce/src/object_info.rs::tests::result_status_roundtrip
Status: done
§7.7.10 RelatedObjectRequest
§7.7.10 RelatedObjectRequest als typedef
Spec: §7.7.10, S. 42 — “typedef RelatedObjectRequest BaseObjectRequest; The interpretation is the same as for the related_request that appears in the BaseObjectReply”.
Repo: crates/xrce/src/object_info.rs (RelatedObjectRequest)
Tests: crates/xrce/src/object_info.rs::tests::related_object_request_is_base_object_request
Status: done — die Spec schreibt den typedef in umgekehrter Reihenfolge;
gemeint ist typedef BaseObjectRequest RelatedObjectRequest.
§7.7.11 CreationMode
§7.7.11 CreationMode
Spec: §7.7.11, S. 43 — “struct CreationMode { boolean reuse; boolean replace; };”
Repo: crates/xrce/src/object_store.rs (CreationMode);
crates/xrce/src/submessages/create.rs (CREATE_FLAG_REUSE,
CREATE_FLAG_REPLACE)
Tests: crates/xrce/src/submessages/create.rs::tests::create_roundtrip_carries_reuse_replace_flags,
crates/xrce-agent/src/daemon/session.rs::tests::a_create_with_reuse_and_replace_updates_the_object
Status: done — auf der Leitung als Flags von CREATE (§8.3.5.2.1); reuse
und replace wirken nach Table 5 (3b066516f69).
§7.7.12 ActivityInfoVariant
§7.7.12 InfoMask
Spec: §7.7.12, S. 43 — “bitmask InfoMask { @position(0) INFO_CONFIGURATION, @position(1) INFO_ACTIVITY };”
Repo: crates/xrce/src/object_info.rs (InfoMask);
crates/xrce-agent/src/daemon/session.rs (handle_get_info, object_info:
Configuration und Activity nach der Maske)
Tests: crates/xrce/src/object_info.rs::tests::info_mask_bits_and_wire_form,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_an_object_returns_the_object_variant_it_was_created_with,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_a_data_writer_reports_its_activity,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_without_an_info_mask_is_invalid_data
Status: done — InfoMask ist eine 32-Bit-Bitmaske (INFO_CONFIGURATION Bit
0, INFO_ACTIVITY Bit 1, ohne @bit_bound nach XTypes 32 Bit) und wird aus dem
GET_INFO gelesen; ein GET_INFO ohne Maske ergibt STATUS_ERR_INVALID_DATA.
ca0cf7e08bf.
§7.7.12 AGENT_ActivityInfo
Spec: §7.7.12, S. 43 — “@extensibility(APPENDABLE) struct AGENT_ActivityInfo { short availability; TransportLocatorSeq address_seq; };”
Repo: crates/xrce/src/object_info.rs (ActivityInfoVariant::Agent);
crates/xrce-agent/src/daemon/session.rs (agent_object_info)
Tests: crates/xrce/src/object_info.rs::tests::agent_activity_info_has_a_dheader_and_a_locator_sequence,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_the_agent_in_a_session_returns_activity_and_representation,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_without_a_session_is_answered_for_the_agent_only
Status: done — @extensibility(APPENDABLE): Diskriminator OBJK_AGENT
(0x0D; Annex A schreibt OBJECTID_AGENT, einen ObjectId mit zwei Oktetten und
keinen Wert von ObjectKind), DHEADER, short availability und
TransportLocatorSeq aus den Listenern des Agent. ca0cf7e08bf, 299b3a41398.
§7.7.12 DATAREADER_ActivityInfo
Spec: §7.7.12, S. 43 — “@extensibility(APPENDABLE) struct DATAREADER_ActivityInfo { short highest_acked_num; };”
Repo: crates/xrce/src/object_info.rs (ActivityInfoVariant::DataReader
Z. 524, encode_into Z. 574, decode_at Z. 633);
crates/xrce-agent/src/daemon/session.rs (object_info Z. 3002)
Tests: crates/xrce/src/object_info.rs::tests::data_reader_activity_info_is_a_dheader_and_a_short,
crates/xrce/src/object_info.rs::tests::appended_members_of_an_activity_are_skipped,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_a_data_reader_reports_its_activity
Status: done — DHEADER und short highest_acked_num; Member, die eine
neuere Fassung anhängt, überspringt der Leser über das DHEADER. Der Agent sendet
die Aktivität im INFO auf ein GET_INFO eines DataReader: highest_acked_num ist
die höchste vom Client bestätigte Sequenznummer des Reliable Streams, auf dem
das READ_DATA liefert, sonst 0. Die Spec definiert den Wert nicht; gegen keinen
anderen Agent gemessen. Commit ca0cf7e08bf.
§7.7.12 DATAWRITER_ActivityInfo
Spec: §7.7.12, S. 43 — “@extensibility(APPENDABLE) struct DATAWRITER_ActivityInfo { unsigned long long sample_seq_num; short stream_seq_num; };”
Repo: crates/xrce/src/object_info.rs (ActivityInfoVariant::DataWriter
Z. 529, encode_into Z. 574, decode_at Z. 633);
crates/xrce-agent/src/daemon/session.rs (object_info Z. 3002,
dds_write_and_report Z. 3282)
Tests: crates/xrce/src/object_info.rs::tests::data_writer_activity_info_is_a_dheader_a_long_long_and_a_short,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_a_data_writer_reports_its_activity
Status: done — DHEADER, unsigned long long sample_seq_num (auf 4
ausgerichtet) und short stream_seq_num. Der Agent zählt je DataWriter die
geschriebenen Samples (sample_seq_num) und merkt sich die Sequenznummer im
Header der letzten WRITE_DATA-Nachricht (stream_seq_num). Die Spec definiert
beide Werte nicht; gegen keinen anderen Agent gemessen. Commit ca0cf7e08bf.
§7.7.12 ActivityInfoVariant als Union
Spec: §7.7.12, S. 43–44 — “union ActivityInfoVariant (ObjectKind) { case OBJK_DATAWRITER : DATAWRITER_ActivityInfo data_writer; case OBJK_DATAREADER : DATAREADER_ActivityInfo data_reader; };”
Repo: crates/xrce/src/object_info.rs (ActivityInfoVariant Z. 512,
discriminator Z. 540, encode_into Z. 574, decode_at Z. 633)
Tests: crates/xrce/src/object_info.rs::tests::agent_activity_info_has_a_dheader_and_a_locator_sequence,
crates/xrce/src/object_info.rs::tests::activity_info_decode_unknown_discriminator_rejected,
crates/xrce/src/object_info.rs::tests::activity_info_decode_truncated_rejected,
crates/xrce/src/object_info.rs::tests::appended_members_of_an_activity_are_skipped
Status: done — der Diskriminator ist das Oktett der ObjectKind
(OBJK_DATAWRITER 0x05, OBJK_DATAREADER 0x06); die Member tragen das DHEADER; ein
unbekannter Diskriminator ist ein Fehler. Annex A (S. 113) hat zusätzlich den
Fall des Agent und schreibt OBJECTID_AGENT, eine ObjectId aus zwei Oktetten
und kein Wert von ObjectKind; der Code nimmt OBJK_AGENT (0x0D) als
Diskriminator von AGENT_ActivityInfo. Der IDL der Klausel fehlt das Wort
switch. Commit ca0cf7e08bf.
§7.7.13 ObjectInfo
§7.7.13 ObjectInfo mit activity und config
Spec: §7.7.13, S. 44 — “@extensibility(FINAL) struct ObjectInfo { @optional ActivityInfoVariant activity; @optional ObjectVariant config; };”
Repo: crates/xrce/src/object_info.rs (ObjectInfo Z. 760, encode_into
Z. 794, decode_at Z. 834, ObjectConfig Z. 690);
crates/xrce-agent/src/daemon/session.rs (object_info Z. 3002, answer_info
Z. 2962)
Tests: crates/xrce/src/object_info.rs::tests::object_info_puts_the_activity_before_the_config,
crates/xrce/src/object_info.rs::tests::the_config_of_a_topic_is_the_object_variant_it_was_created_with,
crates/xrce/src/object_info.rs::tests::the_config_of_the_agent_is_its_agent_representation,
crates/xrce/src/object_info.rs::tests::an_empty_object_info_is_two_presence_octets,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_an_object_returns_the_object_variant_it_was_created_with
Status: done — activity vor config, je ein Merker-Oktett für die
beiden @optional; config ist ein ObjectVariant mit seiner ObjectKind
(beim Agent die AGENT_Representation, bei einem Objekt die Repräsentation, mit
der es angelegt wurde). Die Ausrichtung zählt ab dem Beginn der Payload, die
Byte-Reihenfolge folgt dem E-Flag. Commits ca0cf7e08bf, b9255734bfb.
§7.7.14 ReadSpecification
§7.7.14 DataDeliveryControl
Spec: §7.7.14, S. 44 — “@extensibility(APPENDABLE) struct DataDeliveryControl { unsigned short max_samples; unsigned short max_elapsed_time; unsigned short max_bytes_per_second; unsigned short min_pace_period; // milliseconds };”
Repo: crates/xrce/src/submessages/read_data.rs (DataDeliveryControl
Z. 60, encode_into Z. 79, decode Z. 93, DeliveryControlForm Z. 127);
crates/xrce-client/src/lib.rs (XrceClient::set_delivery_control_form Z. 372)
Tests: crates/xrce/src/submessages/read_data.rs::tests::read_data_matches_the_captured_read_data_example,
crates/xrce/src/submessages/read_data.rs::tests::annex_b_4_2_read_data_with_filter_and_delivery_control
Status: done — vier unsigned short in dieser Reihenfolge, mit DHEADER
(APPENDABLE). Die Form ohne DHEADER, die der Mitschnitt von eProsima zeigt, ist
die benannte Einstellung DeliveryControlForm::Bare
(XrceClient::set_delivery_control_form); der Leser nimmt beide Formen. Commit
b589558e671.
§7.7.14 DHEADER von DataDeliveryControl
Spec: §7.7.14, S. 44 — wie oben; Annex B.4.2, S. 151–152, zeigt das DHEADER.
Repo: crates/xrce/src/submessages/read_data.rs
(ReadSpecification::encode_into Z. 151, decode Z. 204)
Tests: crates/xrce/src/submessages/read_data.rs::tests::annex_b_4_2_read_data_with_filter_and_delivery_control,
crates/xrce/src/submessages/read_data.rs::tests::read_data_matches_the_captured_read_data_example
Status: done — geschrieben wird ein DHEADER mit der Länge 8, auf 4
ausgerichtet. Annex B.4.2 setzt im DHEADER zusätzlich das Bit 31 (0x80000008),
das XCDR2 im DHEADER nicht kennt; der Leser nimmt es nicht als Teil der Länge.
Gelesen wird mit und ohne DHEADER. Commit b589558e671.
§7.7.14 ReadSpecification
Spec: §7.7.14, S. 44 — “@extensibility(FINAL) struct ReadSpecification { StreamId preferred_stream_id; DataFormat data_format; @optional string content_filter_expression; @optional DataDeliveryControl delivery_control; };”
Repo: crates/xrce/src/submessages/read_data.rs (ReadSpecification
Z. 114, encode_into Z. 151, decode Z. 204, ReadDataPayload Z. 312)
Tests: crates/xrce/src/submessages/read_data.rs::tests::read_data_matches_the_captured_read_data_example,
crates/xrce/src/submessages/read_data.rs::tests::read_data_full_spec_roundtrip,
crates/xrce/src/submessages/read_data.rs::tests::annex_b_4_2_read_data_with_filter_and_delivery_control
Status: done — Reihenfolge der Felder, Merker der beiden @optional,
Werte von data_format nach Annex A und XCDR2-Zeichenkette (siehe die Items zu
data_format, content_filter_expression und DataDeliveryControl). Commit
b589558e671.
§7.7.14 Werte von data_format
Spec: §7.7.14, S. 44; Annex A, S. 113–114 — “const DataFormat FORMAT_DATA = 0x00; const DataFormat FORMAT_SAMPLE = 0x02; const DataFormat FORMAT_DATA_SEQ = 0x08; const DataFormat FORMAT_SAMPLE_SEQ = 0x0A; const DataFormat FORMAT_PACKED_SAMPLES = 0x0E;”
Repo: crates/xrce/src/submessages/write_data.rs (DataFormat Z. 52, raw
Z. 69, from_raw Z. 78); crates/xrce/src/submessages/read_data.rs
(ReadSpecification::encode_into Z. 151);
crates/xrce-agent/src/daemon/session.rs (data_submessages Z. 3581)
Tests: crates/xrce/src/submessages/read_data.rs::tests::the_data_format_octet_has_the_values_of_annex_a,
crates/xrce/src/submessages/read_data.rs::tests::read_spec_rejects_reserved_data_format,
crates/xrce/src/submessages/write_data.rs::tests::data_format_raw_roundtrip,
crates/xrce-agent/src/daemon/session.rs::tests::a_read_for_data_seq_is_answered_with_one_data_seq,
crates/xrce-agent/src/daemon/session.rs::tests::a_read_for_sample_is_answered_with_a_sample_each,
crates/xrce-agent/src/daemon/session.rs::tests::a_read_for_sample_seq_is_answered_with_one_sample_seq,
crates/xrce-agent/src/daemon/session.rs::tests::a_read_for_packed_samples_is_answered_with_one_packed_samples
Status: done — DataFormat::raw gibt 0x00, 0x02, 0x08, 0x0A und 0x0E;
from_raw liest dieselben Werte, Bits außerhalb von FORMAT_MASK (0x0E) und
reservierte Kombinationen sind ValueOutOfRange. Der Agent liefert DATA im
verlangten Format. Commits b589558e671, fd5253ca805.
§7.7.14 Kodierung von content_filter_expression
Spec: §7.7.14, S. 44 — “@optional string content_filter_expression;” (XCDR2 nach §7.7); Annex B.4.2, S. 151–152: Füllbyte 15, Länge 6 für “x>100”.
Repo: crates/xrce/src/submessages/read_data.rs
(ReadSpecification::encode_into Z. 151, decode Z. 204)
Tests: crates/xrce/src/submessages/read_data.rs::tests::the_content_filter_is_a_string_with_a_nul_and_an_aligned_length,
crates/xrce/src/submessages/read_data.rs::tests::annex_b_4_2_read_data_with_filter_and_delivery_control
Status: done — XCDR2-Zeichenkette: Länge als unsigned long, auf 4
ausgerichtet (ab Beginn der Payload), zählt das NUL mit; das NUL folgt den
Zeichen. Annex B.4.2 (Füllbyte 15, Länge 6 für “x>100”) ist durch einen Test mit
den Bytes festgehalten. Commit b589558e671.
§7.8.1 Use of the ClientKey
§7.8.1 ClientKey identifiziert den Client und trägt Rechte
Spec: §7.8.1, S. 44 — “The ClientKey is assigned to each client. The ClientKey uniquely identifies the client to a particular agent. The ClientKey is associated with a set of permissions for the client within the agent.”
Repo: crates/xrce-agent/src/lib.rs (XrceAgent::clients Z. 102);
crates/xrce-agent/src/daemon/transport.rs (PeerTable::resolve Z. 111);
crates/xrce-agent/src/daemon/access.rs (AccessController::permits Z. 212,
Rule Z. 125)
Tests: crates/xrce-agent/src/lib.rs::tests::multiple_clients_isolated,
crates/xrce-agent/src/daemon/transport.rs::tests::peer_table_resolves_header_client_key_directly,
crates/xrce-agent/src/daemon/access.rs::tests::a_controller_without_rules_restricts_nothing,
crates/xrce-agent/src/daemon/access.rs::tests::the_first_matching_rule_decides_and_no_match_denies,
crates/xrce-agent/src/daemon/session.rs::tests::create_without_permission_is_denied_and_stores_nothing,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_and_delete_without_permission_are_denied,
crates/xrce-agent/src/daemon/session.rs::tests::write_and_read_without_permission_are_denied
Status: done — der ClientKey identifiziert den Client. Die Rechte stehen
im AccessController (§7.4): Regeln je ClientKey für Operation, ObjectKind,
DDS-Domain und Topic (Konfigurationsschlüssel access_rules); die erste
passende Regel entscheidet, ohne Treffer wird verweigert, ohne Regelwerk ist
alles erlaubt. Eine Operation ohne Recht ergibt STATUS_ERR_DENIED. Die Regeln
werden beim Start gelesen; ein Neuladen mit SIGHUP ändert sie nicht. Commits
1c430db8a67, 5f7a8652d95.
§7.8.1 ClientKey ist geheim und in Client und Agent konfiguriert
Spec: §7.8.1, S. 45 — “The ClientKey shall be considered secret. It must be configured both on the Client and in the Agent. The creation and configuration are outside the scope of this specification.”
Repo: crates/xrce-agent/src/daemon/access.rs
(AccessController::client_authorized Z. 193, parse_client_key Z. 227);
crates/xrce-agent/src/daemon/config.rs (authorized_client_keys);
crates/xrce-agent/src/daemon/session.rs (handle_create_client Z. 1227)
Tests: crates/xrce-agent/src/daemon/access.rs::tests::only_configured_client_keys_are_authorized,
crates/xrce-agent/src/daemon/access.rs::tests::a_client_key_is_read_in_wire_order,
crates/xrce-agent/src/daemon/session.rs::tests::a_client_key_not_configured_in_the_agent_is_denied,
crates/xrce-agent/src/daemon/session.rs::tests::without_configured_client_keys_every_key_is_accepted
Status: done — Konfigurationsschlüssel authorized_client_keys (vier
Oktette in der Reihenfolge der Übertragung); ein ClientKey außerhalb der Liste
ergibt STATUS_ERR_DENIED und keine Sitzung, ohne Liste nimmt der Agent jeden
Schlüssel an. Der Client trägt seinen ClientKey ein (XrceClient::new). Der
Schutz des ClientKey auf dem Transport nach §8.3.2.4 sind die Listener kind: dtls und kind: tls. Commits 1c430db8a67, 5f7a8652d95, eb44fbbf575.
§7.8.1 ClientKey wird nicht interpretiert
Spec: §7.8.1, S. 45 — “The ClientKey shall not be interpreted.”
Repo: crates/xrce/src/header.rs (ClientKey Z. 110)
Tests: crates/xrce/src/handshake.rs::tests::client_representation_decodes_the_captured_create_client_prefix
Status: done
§7.8.1 Operationen nur mit bestehendem ProxyClient
Spec: §7.8.1, S. 45 — “With the exception of the operations create_client and get_info on the XRCE Root, all other operations expect that the ClientKey references an already exiting XRCE ProxyClient. If this is not the case, the operation shall fail.”
Repo: crates/xrce-agent/src/lib.rs (XrceAgent::create_object Z. 240,
pull_sample Z. 313: AgentError::UnknownClient);
crates/xrce-agent/src/daemon/session.rs (create_core Z. 1583,
handle_delete Z. 2733)
Tests: crates/xrce-agent/src/lib.rs::tests::create_object_for_unknown_client_rejected,
crates/xrce-agent/src/lib.rs::tests::pull_sample_unknown_client_rejected,
crates/xrce-agent/src/daemon/session.rs::tests::delete_client_needs_a_proxy_client
Status: done — ein Vorgang für einen ClientKey ohne ProxyClient wird nicht
ausgeführt; die Sitzung antwortet mit STATUS_ERR_UNKNOWN_REFERENCE.
§7.8.1 STATUS_ERR_NOCLIENT oder stilles Verwerfen
Spec: §7.8.1, S. 45 — “To avoid information leakage that could compromise security, the failure to locate a ClientKey may in some cases result in a returnValue having STATUS_ERR_NOCLIENT while in others it may silently drop the connection to the client.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_message, drops_for_unknown_client, SessionEvent::NoClient)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_message_to_an_unknown_client_key_is_dropped_and_counted
Status: done — §7.8.1 lässt zwei Wege: STATUS_ERR_NOCLIENT oder stilles Verwerfen. StatusValue (Annex A) hat den Wert nicht, der Agent verwirft die Nachricht ohne Antwort und meldet SessionEvent::NoClient; create_client und get_info sind ausgenommen, delete_client bekommt seine Antwort nach §7.8.2.3. 458b32f4346.
### §7.8.1 Zähler für STATUS_ERR_NOCLIENT und Schließen der Verbindung
Spec: §7.8.1, S. 45 — “The Agent shall maintain a counter on the number of
times the STATUS_ERR_NOCLIENT was sent on an established connection, and once
a certain threshold is crossed it shall close the connection. The Agent may
subsequently refuse or throttle new connections originating from the same
client transport endpoint that was previously closed.”
Repo: crates/xrce-agent/src/daemon/transport.rs (PeerTable::strike, PeerTable::is_blocked, apply_events); crates/xrce-agent/src/daemon/config.rs (no_client_threshold)
Tests: crates/xrce-agent/src/daemon/transport.rs::tests::messages_to_an_unknown_client_key_close_the_connection_at_the_threshold, crates/xrce-agent/src/daemon/config.rs::tests::the_no_client_threshold_can_be_set
Status: done — der Agent zählt die Nachrichten je Peer an einen unbekannten ClientKey; bei no_client_threshold (Vorgabe 16, 0 nie) wird die TCP-Verbindung geschlossen und ein UDP-Peer nicht mehr gelesen. 458b32f4346.
§7.8.2 XRCE Root
§7.8.2 Root authentifiziert und legt ProxyClients an
Spec: §7.8.2, S. 45 — “The XRCE Root object represents the Agent. An XRCE Agent is a singleton object that all agents shall instantiate. The XRCE Root is responsible for authenticating client applications and creating the XRCE ProxyClient object associated with each client.”
Repo: crates/xrce-agent/src/daemon/session.rs (SessionEngine,
handle_create_client Z. 1168; Prüfungen Z. 1227 und Z. 1240);
crates/xrce-agent/src/daemon/access.rs (AccessController)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::create_client_happy_path_registers_and_replies_ok,
crates/xrce-agent/src/daemon/session.rs::tests::a_client_key_not_configured_in_the_agent_is_denied,
crates/xrce-agent/src/daemon/session.rs::tests::client_properties_are_checked_against_what_the_agent_requires
Status: done — der ProxyClient wird angelegt. Authentifiziert wird durch
den AccessController: konfigurierte ClientKeys (authorized_client_keys) und
geforderte Properties mit Name und Wert (required_client_properties), sonst
STATUS_ERR_DENIED und keine Sitzung. Commits 1c430db8a67, 5f7a8652d95.
§7.8.2 Table 3 Operationen der Root
Spec: §7.8.2, Table 3, S. 45 — create_client, get_info,
delete_client.
Repo: —
Tests: —
Status: n/a (informative) — Übersicht; die Operationen stehen einzeln in
§7.8.2.1 bis §7.8.2.3.
§7.8.2.1 create_client: Ein- und Ausgaben
Spec: §7.8.2.1, S. 45–46 — “client_representation (CLIENT_Representation): a representation of the Client. […] returnValue (ResultStatus) […] agent_info (AGENT_Representation): a representation of the Agent.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create_client
Z. 1168, agent_status_reply Z. 4331)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::create_client_happy_path_registers_and_replies_ok
Status: done — STATUS_AGENT trägt ResultStatus und
AGENT_Representation (Item zu §8.3.5.5).
§7.8.2.1 CLIENT_Representation mit client_timestamp
Spec: §7.8.2.1, S. 46 — “struct CLIENT_Representation { XrceCookie xrce_cookie; XrceVersion xrce_version; XrceVendorId xrce_vendor_id; Time_t client_timestamp; ClientKey client_key; SessionId session_id; @optional PropertySeq properties; };”
Repo: crates/xrce/src/handshake.rs (ClientRepresentation Z. 328,
encode_form Z. 407, decode_form Z. 463); crates/xrce/src/encoding.rs
(RepresentationTimestamps Z. 214); crates/xrce-agent/src/daemon/config.rs
(representation_timestamps); crates/xrce-client/src/lib.rs
(XrceClient::set_representation_timestamps Z. 364)
Tests: crates/xrce/src/handshake.rs::tests::by_default_the_representations_have_no_timestamp,
crates/xrce/src/handshake.rs::tests::the_prose_form_has_a_time_t_after_the_vendor_id,
crates/xrce/src/handshake.rs::tests::client_representation_decodes_the_captured_create_client_prefix,
crates/xrce-client/src/lib.rs::tests::the_representation_timestamp_is_an_option_of_the_client,
crates/xrce-agent/src/daemon/config.rs::tests::the_form_of_the_representations_can_be_set
Status: done — die Spec widerspricht sich: der Text (§7.8.2.1, §8.3.5.1.2)
nennt Time_t client_timestamp nach xrce_vendor_id; das IDL von Annex A
(S. 105–106), die Bytes von Annex B.1 und der Mitschnitt von eProsima (16
Oktette) haben es nicht. Die Formen sind an den Bytes nicht zu unterscheiden.
Standard ist die Form des IDL; die Form mit Zeitstempel ist die benannte
Einstellung representation_timestamps: absent | present (Agent-Schlüssel),
encoding::RepresentationTimestamps (Rust-API),
XrceClient::set_representation_timestamps und die Option representation timestamps im XRCE-Client jedes SDK. Der Time_t folgt UnannotatedTypes (im
Standard ein DHEADER mit der Länge 8). Die Tests prüfen die Bytes beider Formen.
Commits f8bdf3cd878, 571ee6893d1.
§7.8.2.1 AGENT_Representation mit agent_timestamp
Spec: §7.8.2.1, S. 46 — “struct AGENT_Representation { XrceCookie xrce_cookie; XrceVersion xrce_version; XrceVendorId xrce_vendor_id; Time_t agent_timestamp; @optional PropertySeq properties; };”
Repo: crates/xrce/src/handshake.rs (AgentRepresentation Z. 356,
encode_form Z. 554, decode_form Z. 599); crates/xrce/src/encoding.rs
(RepresentationTimestamps Z. 214)
Tests: crates/xrce/src/handshake.rs::tests::the_agent_representation_follows_the_setting_the_same_way,
crates/xrce/src/handshake.rs::tests::agent_representation_decodes_the_captured_status_agent_body,
crates/xrce-client/src/lib.rs::tests::the_representation_timestamp_is_an_option_of_the_client
Status: done — wie beim Item zu client_timestamp: Standard ist die Form
von Annex A (S. 106) ohne agent_timestamp; die Form mit dem Zeitstempel ist
die Einstellung representation_timestamps: present. Der Agent liest die
Einstellung beim Start (server.rs, set_representation_timestamps). Commits
f8bdf3cd878, 571ee6893d1.
§7.8.2.1 Prüfung von xrce_cookie
Spec: §7.8.2.1, S. 46 — “Check the xrce_cookie to ensure it matches the predefined XRCE_COOKIE constant. If it does not match the creation shall fail and set the returnValue StatusValue to STATUS_ERR_INVALID_DATA.”
Repo: crates/xrce/src/handshake.rs (ClientRepresentation::decode_at
Z. 455); crates/xrce-agent/src/daemon/session.rs (handle_create_client
Z. 1175)
Tests: crates/xrce/src/submessages/create_client.rs::tests::refuses_a_payload_whose_cookie_is_not_xrce,
crates/xrce/src/handshake.rs::tests::client_representation_rejects_wrong_cookie,
crates/xrce-agent/src/daemon/session.rs::tests::a_wrong_cookie_is_answered_with_a_status_agent
Status: done — das Cookie wird geprüft; ein falsches ergibt ein
STATUS_AGENT mit STATUS_ERR_INVALID_DATA, es wird kein Client registriert.
Commit d7aec9c2d78.
§7.8.2.1 Antwort auf ein falsches Cookie als STATUS
Spec: §7.8.2.1, S. 46 — wie oben; §8.3.5.1, S. 63: “The XRCE Agent shall send a STATUS_AGENT message in response”.
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create_client
Z. 1175–1192, agent_status_reply Z. 4331)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_wrong_cookie_is_answered_with_a_status_agent,
crates/xrce-agent/src/daemon/session.rs::tests::an_unreadable_property_seq_is_refused_with_invalid_data
Status: done — die Antwort ist ein STATUS_AGENT (§8.3.5.1) mit dem
ClientKey des Headers, wenn der Header einen hat, sonst aus Nullen. Commit
d7aec9c2d78.
§7.8.2.1 Prüfung der Hauptversion
Spec: §7.8.2.1, S. 46 — “Check that the major version (xrce_version[0]) matches the XRCE_VERSION_MAJOR. If it does not match, the creation shall fail and set the returnValue StatusValue to STATUS_ERR_INCOMPATIBLE.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create_client
Z. 1212)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::create_client_rejects_wrong_major_version
Status: done
§7.8.2.1 client_key berechtigt
Spec: §7.8.2.1, S. 46 — “Check that the Client identified by the client_key is authorized to connect to the XRCE Agent. If this check fails the operation shall fail and set the returnValue StatusValue to STATUS_ERR_DENIED.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create_client
Z. 1227, deny_create_client Z. 1337); crates/xrce-agent/src/daemon/access.rs
(AccessController::client_authorized Z. 193)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_client_key_not_configured_in_the_agent_is_denied,
crates/xrce-agent/src/daemon/access.rs::tests::only_configured_client_keys_are_authorized
Status: done — ein ClientKey außerhalb von authorized_client_keys ergibt
STATUS_ERR_DENIED; es entsteht keine Sitzung. Commits 1c430db8a67, 5f7a8652d95.
§7.8.2.1 Prüfung der properties
Spec: §7.8.2.1, S. 46 — “Check the Client properties, if present. These may contain vendor-specific information that may prevent the Agent from accepting the connection from the Client. […] If this check fails the operation shall fail and set the returnValue StatusValue to the appropriate value.”
Repo: crates/xrce-agent/src/daemon/access.rs
(AccessController::properties_accepted Z. 201); crates/xrce/src/handshake.rs
(decode_properties Z. 266); crates/xrce-agent/src/daemon/session.rs
(handle_create_client Z. 1240)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::client_properties_are_checked_against_what_the_agent_requires,
crates/xrce-agent/src/daemon/session.rs::tests::an_unreadable_property_seq_is_refused_with_invalid_data,
crates/xrce-agent/src/daemon/session.rs::tests::a_big_endian_create_client_with_properties_is_read_right,
crates/xrce/src/handshake.rs::tests::a_malformed_property_seq_is_an_error_not_absent_properties
Status: done — verlangt der Agent Properties
(required_client_properties, Name und Wert), antwortet er ohne sie oder mit
anderem Wert mit STATUS_ERR_DENIED. Eine nicht lesbare PropertySeq ist ein
Fehler und wird mit STATUS_ERR_INVALID_DATA beantwortet; sie gilt nicht als
“keine Properties”. Commits 5f7a8652d95, ca0cf7e08bf.
§7.8.2.1 Bestehender ProxyClient mit gleicher session_id
Spec: §7.8.2.1, S. 47 — “If a ProxyClient exists and has the same session_id, then the operation shall not perform any action and shall set the returnValue StatusValue to STATUS_OK.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create_client
Z. 1274 same_session, Z. 1302–1332)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::create_client_same_session_id_reconnect_keeps_object_store,
crates/xrce-agent/src/daemon/session.rs::tests::a_create_client_for_the_same_session_leaves_the_streams_alone
Status: done — Objektspeicher und Streams bleiben, die Antwort ist
STATUS_OK. Die Variante, die die Streams zurücksetzt, ist die Einstellung des
folgenden Items. Commit d7aec9c2d78.
§7.8.2.1 Streams bei gleicher session_id
Spec: §7.8.2.1, S. 47 — wie oben.
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create_client
Z. 1290, SessionEngineConfig::restart_on_same_session);
crates/xrce-agent/src/daemon/config.rs (same_session_create_client)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_create_client_for_the_same_session_leaves_the_streams_alone,
crates/xrce-agent/src/daemon/session.rs::tests::a_create_client_for_the_same_session_can_restart_the_streams,
crates/xrce-agent/src/daemon/config.rs::tests::a_create_client_for_the_same_session_can_restart_the_streams,
crates/xrce-agent/tests/replay_foreign_session.rs::replay_matches_the_real_agents_create_client_create_and_delete_replies
Status: done — Standard keep (Spec): ein CREATE_CLIENT mit der
session_id des bestehenden ProxyClient “shall not perform any action”, die
Streams laufen weiter. Benannte Einstellung same_session_create_client: restart: der Agent verwirft die Zustände der Reliable Streams, der
Fragmentierung, den Rückstau und die Zähler der Best-Effort-Streams. Das
brauchen die Prozesse von eProsima, die ClientKey und session_id
wiederverwenden und bei der Sequenznummer 0 beginnen (Mitschnitt; der
Replay-Test setzt restart). Commit d7aec9c2d78.
§7.8.2.1 Bestehender ProxyClient mit anderer session_id
Spec: §7.8.2.1, S. 47 — “If a ProxyClient exists and has a different session_id then the operation shall delete the existing XRCE ProxyClient object and subsequently take the same actions as if there had not been a ProxyClient associated with the client_key.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create_client
Z. 1275)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::create_client_different_session_id_resets_object_store
Status: done
§7.8.2.1 Ausreichende Ressourcen
Spec: §7.8.2.1, S. 47 — “Check that there are sufficient internal resources to complete the create operation. If there are not, then the operation shall fail and set the returnValue StatusValue to STATUS_ERR_RESOURCES.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create_client)
Tests: crates/xrce-agent/tests/spec_items_session.rs::create_client_over_max_clients_is_a_resource_error
Status: done — handle_create_client prüft max_clients und antwortet mit STATUS_ERR_RESOURCES; ein erneutes CREATE_CLIENT eines vorhandenen Clients bleibt STATUS_OK (02c704651e4).
### §7.8.2.1 Löschen setzt den Zustand der Kommunikation zurück
Spec: §7.8.2.1, S. 47 — “deletion of an existing ProxyClient resets any prior communication state between the client and the agent. Any messages that were cached pending acknowledgments shall be discarded.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create_client
Z. 1275–1301, handle_delete Z. 2733)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::create_client_different_session_id_resets_object_store,
crates/xrce-agent/tests/replay_foreign_session.rs::replay_matches_the_real_agents_create_client_create_and_delete_replies
Status: done
§7.8.2.1 Neuer ProxyClient: session_id, Streams ab 0, STATUS_OK
Spec: §7.8.2.1, S. 47 — “If the Agent creates a ProxyClient object it shall: Initialize its state to have the specified session_id. Initialize the built-in streams with sequence number 0. Set the returnValue StatusValue to STATUS_OK. Return a representation of the XRCE Agent in the agent_info.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create_client
Z. 1302–1332); crates/xrce/src/reliable.rs (ReliableStreamState::new:
next_seq = 0)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::create_client_happy_path_registers_and_replies_ok,
crates/xrce-agent/src/daemon/session.rs::tests::reliable_outbound_messages_get_real_incrementing_sequence_numbers
Status: done
§7.8.2.1 Zeitstempel für die Synchronisation
Spec: §7.8.2.1, S. 47 — “The Agent and Client may use the client_timestamp and agent_timestamp to detect time-synchronization differences […]. The use of this information is left outside the scope of this specification.”
Repo: —
Tests: —
Status: n/a (informative) — außerhalb der Spec.
§7.8.2.1 XrceVersion und XrceVendorId zur Konfiguration
Spec: §7.8.2.1, S. 47 — “The Agent and Client may use the XrceVersion and XrceVendorId to further configure their protocol.”
Repo: —
Tests: —
Status: n/a (informative) — Erlaubnis.
§7.8.2.2 get_info der Root: Ein- und Ausgaben
Spec: §7.8.2.2, S. 47 — “info_mask (InfoMask): selects the kind of information to retrieve. client_info (ObjectInfo): a representation of the Client. […] returnValue (ResultStatus) […] agent_info (ObjectInfo): a representation of the Agent.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_get_info Z. 2838,
agent_object_info Z. 4242, client_info_status Z. 242);
crates/xrce/src/object_info.rs (InfoMask Z. 449);
crates/xrce-agent/src/daemon/discovery.rs (build_info_reply Z. 107);
crates/xrce/src/submessages/get_info.rs (GetInfoPayload::with_client_info
Z. 45)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_the_agent_in_a_session_returns_activity_and_representation,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_the_agent_checks_the_version_in_client_info,
crates/xrce-agent/src/daemon/discovery.rs::tests::discovery_responder_answers_get_info_on_agent,
crates/xrce-agent/src/daemon/discovery.rs::tests::the_info_mask_selects_activity_and_configuration,
crates/xrce/src/object_info.rs::tests::info_mask_bits_and_wire_form
Status: done — INFO mit ResultStatus und dem ObjectInfo des Agent.
info_mask ist ein 32-Bit-Merker (InfoMask), den der Agent aus dem GET_INFO
liest; er wählt activity und config. client_info: GET_INFO_Payload
(§8.3.5.3.2, Annex A) hat dafür kein Member, §7.8.2.2 und Figure 10 (§8.4.4)
nennen es. Standard ist die Payload von Annex A;
GetInfoPayload::with_client_info hängt client_info hinter die InfoMask, der
Agent liest es, wenn es da ist (Item zu client_info). Commits ca0cf7e08bf,
fd2e9a5bcfd.
§7.8.2.2 get_info vor create_client und über eine andere Verbindung
Spec: §7.8.2.2, S. 47 — “The operation get_info returns information on the XRCE Agent and may be used prior to establishing a Session with the XRCE Agent […]. The operation get_info may be used over a different transport or connection”.
Repo: crates/xrce-agent/src/daemon/discovery.rs (run_discovery_responder
Z. 43); crates/xrce-agent/src/daemon/session.rs (refusal Z. 936,
handle_submessage Z. 1141, handle_get_info Z. 2838)
Tests: crates/xrce-agent/src/daemon/discovery.rs::tests::discovery_responder_answers_get_info_on_agent,
crates/xrce-agent/src/daemon/transport.rs::tests::the_udp_listener_answers_get_info_before_a_session,
crates/xrce-agent/src/daemon/transport.rs::tests::the_tcp_listener_answers_get_info_before_a_session,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_without_a_session_is_answered_for_the_agent_only
Status: done — der Responder auf dem Port der Discovery und die
Sitzungs-Engine auf den Listenern für UDP und TCP beantworten
GET_INFO(OBJK_AGENT) ohne Sitzung; auch ein anderer Transport als der der
folgenden Sitzung ist möglich. Für den Listener der seriellen Leitung gibt es
keinen eigenen Test. Commits ca0cf7e08bf, a8f300b7bcf.
§7.8.2.2 GET_INFO ohne Sitzung an einem Listener
Spec: §7.8.2.2, S. 47 — wie oben.
Repo: crates/xrce-agent/src/daemon/session.rs (refusal Z. 936,
handle_submessage Z. 1141, handle_get_info Z. 2838)
Tests: crates/xrce-agent/src/daemon/transport.rs::tests::the_udp_listener_answers_get_info_before_a_session,
crates/xrce-agent/src/daemon/transport.rs::tests::the_tcp_listener_answers_get_info_before_a_session,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_without_a_session_is_answered_for_the_agent_only
Status: done — handle_submessage reicht ein GET_INFO ohne aufgelösten
Client oder mit Header ohne Sitzung an handle_get_info(None, ...);
GET_INFO(OBJK_AGENT) vor CREATE_CLIENT wird auf den Listenern für UDP und TCP
beantwortet, jede andere Art mit STATUS_ERR_UNKNOWN_REFERENCE. Commits
ca0cf7e08bf, a8f300b7bcf.
§7.8.2.2 client_info mit CLIENT_Representation und CLIENTKEY_INVALID
Spec: §7.8.2.2, S. 47–48 — “The ObjectVariant member within client_info shall contain a CLIENT_Representation, which provides information on the XRCE Client that makes the request. […] The client_key field of CLIENT_Representation shall be set to the value CLIENTKEY_INVALID”.
Repo: crates/xrce/src/submessages/get_info.rs
(GetInfoPayload::with_client_info Z. 45, client_info Z. 62);
crates/xrce-agent/src/daemon/session.rs (client_info_status Z. 242);
crates/xrce-client/src/discovery.rs (AgentDiscovery::with_client_info
Z. 113); crates/xrce-client/src/lib.rs (XrceClient::request_agent_info
Z. 622)
Tests: crates/xrce/src/submessages/get_info.rs::tests::client_info_follows_the_info_mask,
crates/xrce-client/src/discovery.rs::tests::client_info_names_the_version_and_hides_the_client_key,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_the_agent_checks_the_version_in_client_info,
crates/xrce-agent/src/daemon/discovery.rs::tests::a_client_of_another_major_version_is_answered_incompatible,
crates/xrce-client/src/lib.rs::tests::request_agent_info_works_before_the_session_and_sends_the_mask
Status: done — client_info ist ein ObjectInfo hinter der InfoMask,
dessen config eine CLIENT_Representation mit client_key CLIENTKEY_INVALID
(Nullen) ist. Annex A hat dafür kein Member in GET_INFO_Payload; ein
Empfänger, der es nicht liest, beantwortet das GET_INFO wie ohne. Der Agent
liest es: eine andere Hauptversion ergibt INFO mit STATUS_ERR_INCOMPATIBLE
(Figure 10), eine nicht lesbare oder keine CLIENT_Representation
STATUS_ERR_INVALID_DATA. Der Client sendet es nur auf
AgentDiscovery::with_client_info; XrceClient::request_agent_info sendet das
GET_INFO von Annex A. Commits ca0cf7e08bf, fd2e9a5bcfd.
§7.8.2.2 agent_info mit AGENT_Representation und AGENT_ActivityInfo
Spec: §7.8.2.2, S. 48 — “The ObjectVariant member within agent_info shall contain an AGENT_ActivityInfo […]. The ActivityInfoVariant member within agent_info shall contain an AGENT_Representation”.
Repo: crates/xrce-agent/src/daemon/session.rs (agent_object_info
Z. 4242); crates/xrce-agent/src/daemon/discovery.rs (build_info_reply
Z. 107)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_the_agent_in_a_session_returns_activity_and_representation,
crates/xrce-agent/src/daemon/discovery.rs::tests::discovery_responder_answers_get_info_on_agent,
crates/xrce-agent/src/daemon/discovery.rs::tests::the_info_mask_selects_activity_and_configuration
Status: done — activity trägt ActivityInfoVariant::Agent
(AGENT_ActivityInfo, Layout siehe §7.7.12), config die
AGENT_Representation. Der Text vertauscht die beiden Member: config ist
ObjectVariant, activity ActivityInfoVariant; der Code folgt Annex A.
Commit ca0cf7e08bf.
§7.8.2.2 AGENT_Representation in agent_info
Spec: §7.8.2.2, S. 48 — wie oben.
Repo: crates/xrce-agent/src/daemon/session.rs (agent_object_info
Z. 4242, handle_get_info Z. 2838); crates/xrce-agent/src/daemon/discovery.rs
(build_info_reply Z. 107)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_the_agent_in_a_session_returns_activity_and_representation,
crates/xrce-agent/src/daemon/discovery.rs::tests::discovery_responder_answers_get_info_on_agent,
crates/xrce-agent/src/daemon/discovery.rs::tests::the_info_mask_selects_activity_and_configuration
Status: done — config ist ObjectConfig::Agent(AgentRepresentation) mit
Version und Vendor des Agent, soweit die InfoMask config verlangt; damit wählt
ein Client nach §8.4.4 einen Agent aus. properties ist leer. Commit
ca0cf7e08bf.
§7.8.2.2 address_seq meldet die Adressen
Spec: §7.8.2.2, S. 48 — “ActivityInfoVariant member address_seq shall be used to inform the XRCE Client of the transport addresses over which it can be reached and can receive calls to create_client.”
Repo: crates/xrce-agent/src/daemon/server.rs (listener_locators)
Tests: crates/xrce-agent/src/daemon/server.rs::tests::listener_locators_maps_udp_tcp_and_ipv6, crates/xrce-agent/src/daemon/server.rs::tests::listener_locators_names_the_secured_and_the_serial_listeners
Status: done — address_seq trägt die Adressen der Listener: UDP und TCP mit IPv4 als ADDRESS_FORMAT_MEDIUM, mit IPv6 als ADDRESS_FORMAT_LARGE (§11.2.1, §11.3.1), als TransportLocatorSeq im AGENT_ActivityInfo mit DHEADER; DTLS, TLS und eine serielle Leitung als ADDRESS_FORMAT_STRING (nächstes Item). 299b3a41398, ca0cf7e08bf, 0ac394aa5bf.
### §7.8.2.2 address_seq nennt die Listener mit DTLS und TLS
Spec: §7.8.2.2, S. 48 — wie oben.
Repo: crates/xrce-agent/src/daemon/server.rs (listener_locators)
Tests: crates/xrce-agent/src/daemon/server.rs::tests::listener_locators_names_the_secured_and_the_serial_listeners
Status: done — die Listener kind: dtls und kind: tls werden als ADDRESS_FORMAT_STRING-Locator gemeldet (dtls://host:port, tls://host:port), eine serielle Leitung als serial://device?address=n: TransportLocatorFormat hat dafür keinen eigenen Wert, und ein einfacher Locator desselben Hosts brächte einen Client dazu, ohne den Schutz nach §8.3.2.4 zu verbinden. 0ac394aa5bf.
### §7.8.2.2 properties für eine Authentifizierung
Spec: §7.8.2.2, S. 48 — “The properties field of type PropertySeq […] may be used to implement an authentication protocol for the XRCE Agent. The specific mechanism is outside the scope of this specification.”
Repo: —
Tests: —
Status: n/a (informative) — außerhalb der Spec.
§7.8.2.3 delete_client löscht den ProxyClient
Spec: §7.8.2.3, S. 48 — “If the object is found it shall be delete and returnValue StatusValue shall be set to STATUS_OK.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_delete Z. 2733)
Tests: crates/xrce-client/src/lib.rs::tests::disconnect_sends_delete_client_and_clears_state,
crates/xrce-agent/src/daemon/session.rs::tests::delete_client_needs_a_proxy_client,
crates/xrce-agent/tests/replay_foreign_session.rs::replay_matches_the_real_agents_create_client_create_and_delete_replies
Status: done
§7.8.2.3 delete_client ohne ProxyClient
Spec: §7.8.2.3, S. 48 — “The XRCE Agent shall check the ClientKey to locate an existing XRCE: ProxyClient. If the object is not found the operation shall fail and returnValue StatusValue shall be set to STATUS_ERR_UNKNOWN_REFERENCE.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_delete Z. 2733:
deletes_client, deleted_clients)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::delete_client_needs_a_proxy_client
Status: done — DELETE(OBJECTID_CLIENT) für einen ClientKey ohne
ProxyClient ergibt STATUS_ERR_UNKNOWN_REFERENCE. Dieselbe Anfrage noch einmal,
die die Sitzung beendet hat, ist eine Wiederholung und bekommt STATUS_OK.
Commits d7aec9c2d78, 09a995c86f4.
§7.8.3 XRCE ProxyClient
§7.8.3 ProxyClient über den ClientKey
Spec: §7.8.3, S. 48 — “The XRCE ProxyClient object represents a specific XRCE Client inside a concrete XRCE Agent. The ProxyClient object is identified by the ClientKey.”
Repo: crates/xrce-agent/src/lib.rs (XrceAgent::clients Z. 102)
Tests: crates/xrce-agent/src/lib.rs::tests::register_client_idempotent
Status: done
§7.8.3 Table 4 Operationen des ProxyClient
Spec: §7.8.3, Table 4, S. 48–49 — create, update, get_info,
delete.
Repo: —
Tests: —
Status: n/a (informative) — Übersicht; die Operationen stehen einzeln in
§7.8.3.1 bis §7.8.3.4.
§7.8.3.1 create: Ein- und Ausgaben
Spec: §7.8.3.1, S. 49 — “creation_mode (CreationMode) […] objectid_prefix (ObjectIdPrefix) […] object_representation (ObjectVariant) […] The object_id in the returnValue shall be derived from the object_prefix input parameter.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create Z. 1452,
create_core Z. 1583, status_reply Z. 4293)
Tests: crates/xrce-agent/tests/replay_foreign_session.rs::replay_matches_the_real_agents_create_client_create_and_delete_replies
Status: done
§7.8.3.1 input_objectkind und input_objectid
Spec: §7.8.3.1, S. 49 — “We will refer to this ObjectKind as the ‘input_objectkind’. […] The combination of the objectid_prefix and the ObjectKind contained in the object_representation discriminator shall be used to construct the ‘input’ ObjectId.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create Z. 1531:
ObjectId::new(request.object_id.raw_id_12(), kind))
Tests: crates/xrce-agent/src/daemon/session.rs::tests::the_object_id_is_the_prefix_and_the_kind_of_the_representation,
crates/xrce-agent/tests/replay_foreign_session.rs::replay_matches_the_real_agents_create_client_create_and_delete_replies
Status: done — die ObjectId besteht aus dem Präfix des Requests (12 Bit)
und der Art des Diskriminators der Repräsentation; das STATUS nennt sie. Commit
70963ac46ec.
§7.8.3.1 object_id mit anderem Halbbyte
Spec: §7.8.3.1, S. 49 — wie oben.
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create
Z. 1531–1544)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::the_object_id_is_the_prefix_and_the_kind_of_the_representation
Status: done — das untere Halbbyte der object_id des Requests wird nicht
gelesen: auch mit einer anderen Art darin legt handle_create das Objekt der
Art des Diskriminators unter demselben Präfix an (im Test ein Participant unter
der object_id einer Publisher-Art). Commit 70963ac46ec.
§7.8.3.1 Table 5: Objekt existiert nicht
Spec: §7.8.3.1, Table 5, S. 50 — “Don’t care / Don’t care / NO — Create object according to Table 6.”
Repo: crates/xrce/src/object_store.rs (ObjectStore::create Z. 152,
CreateOutcome::Created Z. 175)
Tests: crates/xrce/src/object_store.rs::tests::create_inserts_new_object
Status: done
§7.8.3.1 Table 5: reuse=FALSE, replace=FALSE, existiert
Spec: §7.8.3.1, Table 5, S. 50 — “FALSE / FALSE / YES — No action taken. Set the StatusValue within returnValue to: STATUS_ERR_ALREADY_EXISTS.”
Repo: crates/xrce/src/object_store.rs (CreateOutcome::Conflict Z. 208);
crates/xrce-agent/src/daemon/session.rs (create_core Z. 1692)
Tests: crates/xrce/src/object_store.rs::tests::create_strict_on_existing_returns_conflict
Status: done
§7.8.3.1 Table 5: reuse=FALSE, replace=TRUE, existiert
Spec: §7.8.3.1, Table 5, S. 50 — “FALSE / TRUE / YES — Delete existing object as specified by the delete operation. Create object according to Table 6. Set the StatusValue within returnValue to: STATUS_OK.”
Repo: crates/xrce/src/object_store.rs (CreateOutcome::Replaced Z. 206);
crates/xrce-agent/src/daemon/session.rs (create_core Z. 1700)
Tests: crates/xrce/src/object_store.rs::tests::create_replace_increments_version,
crates/xrce-agent/src/daemon/session.rs::tests::a_replace_that_fails_returns_the_object_to_its_previous_configuration
Status: done — dazu gehört, dass ein fehlschlagendes Ersetzen das Objekt
in die vorige Konfiguration zurückführt (§7.8.3.2). Commit 70963ac46ec.
§7.8.3.1 Table 5: reuse=TRUE, replace=FALSE, existiert
Spec: §7.8.3.1, Table 5, S. 50 — “TRUE / FALSE / YES — Check if object_representation matches the existing Object: If it matches no action is taken […] STATUS_OK_MATCHES. If it does not match no action is taken […] STATUS_ERR_MISMATCH.”
Repo: crates/xrce/src/object_store.rs (CreateOutcome::Reused Z. 180);
crates/xrce-agent/src/daemon/session.rs (create_core Z. 1688–1693)
Tests: crates/xrce/src/object_store.rs::tests::create_reuse_returns_equal_marker,
crates/xrce-agent/src/daemon/session.rs::tests::reuse_compares_the_container_of_the_representation
Status: done — gleich: STATUS_OK_MATCHED, ungleich:
STATUS_ERR_MISMATCH, in beiden Fällen ohne Änderung. Table 5 schreibt
STATUS_OK_MATCHES; StatusValue in Annex A und ResultStatusCode::OkMatched
(0x01) heißen STATUS_OK_MATCHED. Verglichen werden Repräsentation, Container
und Domain (Item unten). Commit 70963ac46ec.
§7.8.3.1 Vergleich mit participant_id, publisher_id, domain_id
Spec: §7.8.3.1, Table 5, S. 50 — wie oben.
Repo: crates/xrce-agent/src/daemon/session.rs (create_core Z. 1671:
same_extra, ObjectVariantExtra); crates/xrce/src/object_store.rs
(ObjectStore::create Z. 152)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::reuse_compares_the_container_of_the_representation
Status: done — der Vergleich bei reuse schließt den Container
(participant_id, publisher_id, subscriber_id) und die domain_id ein, die der
Objektspeicher nicht hält (ObjectVariantExtra je Objekt in der Sitzung).
Dieselbe XML-Zeichenkette unter einem anderen Container ergibt
STATUS_ERR_MISMATCH. Commit 70963ac46ec.
§7.8.3.1 Table 5: reuse=TRUE, replace=TRUE, existiert
Spec: §7.8.3.1, Table 5, S. 50 — “TRUE / TRUE / YES — Check if object_representation matches the existing Object: If it matches, no action is taken […] STATUS_OK_MATCHES. If it does not match, delete existing object as specified by the delete operation and then create a new object according to Table 6. Set the StatusValue within returnValue to: STATUS_OK.”
Repo: crates/xrce/src/object_store.rs (ObjectStore::create Z. 177–192);
crates/xrce-agent/src/daemon/session.rs (create_core Z. 1672–1681)
Tests: crates/xrce/src/object_store.rs::tests::create_reuse_and_replace_replaces_an_unequal_object,
crates/xrce-agent/src/daemon/session.rs::tests::a_create_with_reuse_and_replace_updates_the_object
Status: done — bei Gleichheit STATUS_OK_MATCHED ohne Änderung, bei
Ungleichheit wird das Objekt gelöscht und neu angelegt (STATUS_OK), die
DDS-Seite eingeschlossen. Commit 3b066516f69.
§7.8.3.1 reuse und replace ersetzen ein ungleiches Objekt
Spec: §7.8.3.1, Table 5, S. 50 — wie oben.
Repo: crates/xrce/src/object_store.rs (ObjectStore::create Z. 177–192);
crates/xrce-agent/src/daemon/session.rs (create_core Z. 1672–1681)
Tests: crates/xrce/src/object_store.rs::tests::create_reuse_and_replace_replaces_an_unequal_object,
crates/xrce-agent/src/daemon/session.rs::tests::a_create_with_reuse_and_replace_updates_the_object,
crates/xrce-agent/src/daemon/session.rs::tests::the_update_of_a_missing_object_creates_it_or_is_refused,
crates/xrce-agent/src/daemon/session.rs::tests::an_update_needs_the_permission_to_update
Status: done — ObjectStore::create behandelt reuse mit und ohne
replace verschieden: ohne replace ergibt ein ungleiches Objekt
STATUS_ERR_MISMATCH, mit replace ersetzt es das Objekt. Das ist auch die
Operation update (§7.8.3.2, Table 14, §8.4.13): XrceClient::update_object,
Berechtigung update im AccessController, ohne vorhandenes Objekt wird angelegt
(Table 5); update_of_missing_object: refuse liefert
STATUS_ERR_UNKNOWN_REFERENCE (§7.8.3.2). Die beiden Lesarten widersprechen
sich in der Spec; Standard ist Table 5, getestet in
the_update_of_a_missing_object_creates_it_or_is_refused. Commit 3b066516f69.
§7.8.3.1 Alle Repräsentationen mit Referenz und XML
Spec: §7.8.3.1, S. 50 — “the representations for the different kinds of objects all derive from either OBJK_Representation2_Base or OBJK_Representation3_Base. Therefore, they all have at least the REPRESENTATION_BY_REFERENCE and the REPRESENTATION_AS_XML_STRING.”
Repo: crates/xrce-agent/src/daemon/session.rs (format_is_allowed Z. 279,
handle_create Z. 1508); crates/xrce-agent/src/daemon/config.rs
(representation_formats)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::the_formats_of_each_kind_are_enforced,
crates/xrce-agent/src/daemon/config.rs::tests::the_representation_formats_can_be_widened
Status: done — die Spec widerspricht sich: der Text sagt, alle
Repräsentationen hätten REPRESENTATION_BY_REFERENCE und
REPRESENTATION_AS_XML_STRING; §7.7.3.1 und Annex A geben Type, QosProfile,
Application und Domain Referenz oder XML (OBJK_RepresentationRefAndXML_Base),
Publisher, Subscriber, DataWriter und DataReader binär oder XML
(OBJK_RepresentationBinAndXML_Base), DomainParticipant und Topic alle drei.
OBJK_Representation2_Base gibt es nicht. Standard ist Annex A
(representation_formats: spec): ein anderes Format ergibt
STATUS_ERR_INVALID_DATA. Die benannte Einstellung representation_formats: any
nimmt jedes Format an, für Clients, die Publisher, Subscriber, DataWriter und
DataReader per Referenz anlegen; gegen einen solchen Client nicht gemessen.
Commits 0429eab4fb2, 23d8f50c712.
§7.8.3.1 Eingebettete Objekte
Spec: §7.8.3.1, S. 50 — “Certain representations support the representation of nested objects. […] In this case, the creation of the XRCE object shall also create the nested objects and the failure to create any nested entity shall be considered a failure to create the contained entity as well.”
Repo: crates/xrce-agent/src/daemon/session.rs (create_nested Z. 1833,
create_embedded Z. 1785, create_core Z. 1743–1759)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_participant_definition_creates_the_objects_inside_it,
crates/xrce-agent/src/daemon/session.rs::tests::a_participant_definition_with_a_broken_part_creates_nothing,
crates/xrce-agent/src/daemon/session.rs::tests::a_publisher_with_nested_data_writers_creates_them
Status: done — ein DomainParticipant oder eine Application legt die
Objekte an, die ihre Definition enthält (DDS-XML), ebenso ein Publisher oder
Subscriber seine eingebetteten DataWriter und DataReader. Schlägt ein Kind fehl,
scheitert das Ganze: was angelegt war, wird entfernt (remove_with_nested) und
das vorige Objekt kommt zurück. Commits 9d5c64dc398, b97657ef4ec.
### §7.8.3.1 Proxy legt die DDS-Entität an
Spec: §7.8.3.1, S. 50 — “Some of the XRCE objects may be defined by this specification as proxies for DDS entities. In this case the creation of the XRCE Object will automatically trigger the creation of the proxy DDS Entity.”
Repo: crates/xrce-agent/src/daemon/session.rs (plan_dds_create,
apply_dds_create); crates/xrce-agent/src/daemon/dds_port.rs
(DdsPort::create_participant_with, DdsPort::create_topic,
DdsPort::create_publisher, DdsPort::create_subscriber,
DdsPort::create_writer, DdsPort::create_reader);
crates/xrce-agent/src/daemon/dcps_bridge.rs (RealDdsPort)
Tests: crates/xrce-agent/tests/replay_foreign_session.rs::replay_creates_the_dds_entities_the_real_clients_describe,
crates/xrce-agent/tests/e2e_udp_loopback.rs::e2e_udp_loopback_keyed_dispose_reliable_besteffort_and_fragments,
crates/xrce-agent/src/daemon/session.rs::tests::a_publisher_and_a_subscriber_get_a_dds_entity_with_their_policies,
crates/xrce-agent/src/daemon/dcps_bridge.rs::tests::a_publisher_is_a_dds_entity_of_its_participants_domain
Status: done — Commits 505c2e56d24. Participant, Topic, Publisher, Subscriber,
DataWriter und DataReader haben eine DDS-Entität. Publisher und Subscriber legen
DdsPort::create_publisher und create_subscriber an (PRESENTATION,
ENTITY_FACTORY, PARTITION, GROUP_DATA werden angewendet). QosProfile, Type und
Application haben nach Table 6 keine DDS-Entität.
§7.8.3.1 Scheitern der DDS-Entität ist Scheitern des Objekts
Spec: §7.8.3.1, S. 50 — “Failure to create a DDS Entity shall be considered a failure to create the proxy XRCE object as well.”
Repo: crates/xrce-agent/src/daemon/session.rs (create_core,
apply_dds_create, remove_with_nested)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_dds_entity_is_enabled_when_the_creation_has_succeeded,
crates/xrce-agent/src/daemon/session.rs::tests::a_topic_of_an_unknown_type_is_refused_when_the_agent_is_told_to,
crates/xrce-agent/src/daemon/session.rs::tests::a_participant_definition_with_a_broken_part_creates_nothing
Status: done — Commits 70963ac46ec, 9d5c64dc398. Scheitert apply_dds_create
oder DdsPort::enable, löscht create_core die DDS-Seite und den
Speichereintrag und antwortet mit dem Code des Fehlers. Scheitert ein
eingebettetes Objekt, entfällt das ganze Objekt (remove_with_nested).
§7.8.3.1 Kein Discovery-Verkehr bei Fehlschlag, Entitäten deaktiviert
Spec: §7.8.3.1, S. 50 — “If the creation of the XRCE object fails then there should be no associated DDS-RTPS discovery traffic generated by the Agent. This means that all DDS entities shall be created disabled […] and enabled (if so configured by their QoS) only after it has been determined that the creation has succeeded.”
Repo: crates/xrce-agent/src/daemon/dcps_bridge.rs (enable, create_participant_with); crates/xrce-agent/src/daemon/session.rs (create_core)
Tests: crates/xrce-agent/src/daemon/dcps_bridge.rs::tests::a_participant_qos_is_applied_to_the_participant, crates/xrce-agent/src/daemon/dcps_bridge.rs::tests::an_endpoint_is_announced_only_when_it_is_enabled
Status: done — DataWriter, DataReader und DomainParticipant werden erst mit DdsPort::enable beim DcpsRuntime registriert und damit entdeckt; create_core ruft enable auf, wenn das Objekt gespeichert ist und nichts mehr scheitern kann. Ein Objekt, das beim Anlegen oder in enable scheitert, wird nie angekündigt. 70963ac46ec, 348ad4265e7.
### §7.8.3.1 DomainParticipant wird deaktiviert angelegt
Spec: §7.8.3.1, S. 50 — “This means that all DDS entities shall be created
disabled […] and enabled (if so configured by their QoS) only after it has
been determined that the creation has succeeded.”
Repo: crates/xrce-agent/src/daemon/dcps_bridge.rs (create_participant_with, enable, runtime_for)
Tests: crates/xrce-agent/src/daemon/dcps_bridge.rs::tests::a_participant_qos_is_applied_to_the_participant
Status: done — create_participant_with startet keinen Runtime mehr; es merkt sich den Participant (bei USER_DATA den Platz eines eigenen Runtime), enable startet ihn, wenn das CREATE gelingt. Eine Domain-ID über 232 wird beim CREATE abgewiesen. 348ad4265e7.
### §7.8.3.1 Erfolg ergibt STATUS_OK
Spec: §7.8.3.1, S. 50 — “If the creation succeeds the Agent shall set the StatusValue within returnStatus to STATUS_OK..”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create,
create_core)
Tests: crates/xrce-agent/tests/replay_foreign_session.rs::replay_matches_the_real_agents_create_client_create_and_delete_replies
Status: done — Eine erfolgreiche Anlage ist STATUS_OK; bei reuse mit
gleicher Darstellung STATUS_OK_MATCHED (Table 5 schreibt STATUS_OK_MATCHES,
unterschiedlich ist nur der Name im Code).
§7.8.3.1 Table 6 OBJK_QOSPROFILE
Spec: §7.8.3.1, Table 6, S. 51 — “The agent shall use that definition to create an XRCE QosProfile in accordance to the representation defined in 7.7.3.2.”
Repo: crates/xrce-agent/src/daemon/session.rs (plan_dds_create,
definition_to_register, rebuild_profiles)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::type_and_qos_profile_xml_follow_their_clauses,
crates/xrce-agent/src/daemon/session.rs::tests::what_a_configuration_client_defines_is_referenced_by_another_client
Status: done — Commits 9d5c64dc398, b97657ef4ec. Das Objekt hat keine
DDS-Entität. Ein <qos_library> mit einem <qos_profile> ist dem Agenten als
Definition bekannt, solange das Objekt besteht; andere Clients legen es per
REPRESENTATION_BY_REFERENCE an. Eine Referenz löst sich gegen die Profildateien
und diese Definitionen auf.
§7.8.3.1 Table 6 OBJK_TYPE
Spec: §7.8.3.1, Table 6, S. 51 — “The agent shall use that definition to create an XRCE Type in accordance to the representation defined in 7.7.3.3.”
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (types); crates/xrce-agent/src/daemon/session.rs (find_type_definition)
Tests: crates/xrce-agent/tests/spec_items_session.rs::a_type_by_reference_names_a_known_type_by_its_fully_qualified_name
Status: done — XML <types> (genau ein nicht verschachtelter Typ) und ein binäres TypeObject legen Typen an; eine Referenz löst sich gegen die dem Agenten bekannten Typen auf, und ein Typ darf auf einen bereits bekannten Typ verweisen (Item zu §7.7.3.3.2).
### §7.8.3.1 Table 6 OBJK_APPLICATION
Spec: §7.8.3.1, Table 6, S. 51 — “The agent shall use that definition to create an XRCE Application with all the contained entities found within the definition in accordance to the representation defined in 7.7.3.5.”
Repo: crates/xrce-agent/src/daemon/session.rs (plan_dds_create,
create_nested, ensure_predefined);
crates/xrce-agent/src/daemon/definitions.rs (plan_participant)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::what_a_configuration_client_defines_is_referenced_by_another_client,
crates/xrce-agent/src/daemon/session.rs::tests::a_create_client_makes_the_objects_configured_for_the_client
Status: done — Commits b97657ef4ec, 2ba972cd270. create_nested legt die
DomainParticipants der Application mit den Objekten in ihnen unter den ObjectIds
ihrer Namen an (Table 16); ein zweites Anlegen verwendet die vorhandenen Objekte
wieder.
§7.8.3.1 Table 6 OBJK_PARTICIPANT
Spec: §7.8.3.1, Table 6, S. 51 — “The agent shall use that definition to create an XRCE DomainParticipant and an associated DDS DomainParticipant with all the contained entities found within the definition in accordance to the representation defined in 7.7.3.6.”
Repo: crates/xrce-agent/src/daemon/session.rs (plan_dds_create,
create_core, create_nested); crates/xrce-agent/src/daemon/dcps_bridge.rs
(RealDdsPort::create_participant_with);
crates/xrce-agent/src/daemon/entity_repr.rs (participant);
crates/xrce-agent/src/daemon/binary_forms.rs (participant)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_participant_definition_creates_the_objects_inside_it,
crates/xrce-agent/src/daemon/session.rs::tests::a_participant_definition_with_a_broken_part_creates_nothing,
crates/xrce-agent/src/daemon/dcps_bridge.rs::tests::full_chain_against_a_real_leased_domain,
crates/xrce-agent/src/daemon/dcps_bridge.rs::tests::a_participant_qos_is_applied_to_the_participant,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_participant_domain_comes_from_the_wire_unless_the_xml_names_one,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_domain_reference_is_resolved_against_the_domain_libraries,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_participant_qos_profile_reference_is_applied
Status: done — Commits 9d5c64dc398, 0b67c04800c. Der Participant bindet den
DcpsRuntime seiner Domain. Die Entitäten in der Definition werden mit ihm
angelegt; scheitert eine, entfällt der ganze Participant. domain_reference und
qos_profile_reference der Binärform werden aufgelöst.
§7.8.3.1 Table 6 OBJK_TOPIC
Spec: §7.8.3.1, Table 6, S. 51 — “The agent shall locate the XRCE DomainParticipant identified by the participant_id. If this object is not found the operation shall fail and return STATUS_ERR_UNKNOWN_REFERENCE. The agent shall use the definition to create an XRCE Topic […] and an associated DDS Topic. The DDS Topic shall be created using the DomainParticipant identified by the participant_id.”
Repo: crates/xrce-agent/src/daemon/session.rs (plan_dds_create,
participant_of_create); crates/xrce-agent/src/daemon/dcps_bridge.rs
(RealDdsPort::create_topic)
Tests: crates/xrce-agent/src/daemon/dds_port.rs::tests::null_port_rejects_topic_before_participant,
crates/xrce-agent/tests/replay_foreign_session.rs::replay_creates_the_dds_entities_the_real_clients_describe,
crates/xrce-agent/src/daemon/session.rs::tests::a_topic_is_created_by_name_or_by_register_type_ref,
crates/xrce-agent/src/daemon/session.rs::tests::a_topic_of_an_unknown_type_is_refused_when_the_agent_is_told_to
Status: done — Commits 969c784c93b. Das Topic ist im DcpsRuntime Name und Typ
seiner Endpunkte. Ein Typ, den der Agent nicht kennt, folgt dem Agent-Schlüssel
unknown_topic_types: refuse (Standard) antwortet
STATUS_ERR_UNKNOWN_REFERENCE und legt nichts an, forward legt das Topic an und
leitet die Samples undekodiert weiter.
§7.8.3.1 Table 6 OBJK_PUBLISHER
Spec: §7.8.3.1, Table 6, S. 51–52 — “The agent shall locate the XRCE DomainParticipant identified by the participant_id. If this object is not found the operation shall fail and return STATUS_ERR_UNKNOWN_REFERENCE. […] an associated DDS Publisher. The DDS Publisher shall be created using the DomainParticipant identified by the participant_id.”
Repo: crates/xrce-agent/src/daemon/session.rs (plan_dds_create,
participant_of_create, DdsCreate::Container);
crates/xrce-agent/src/daemon/dcps_bridge.rs (RealDdsPort::create_publisher)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_publisher_or_subscriber_needs_an_existing_participant,
crates/xrce-agent/src/daemon/session.rs::tests::a_publisher_and_a_subscriber_get_a_dds_entity_with_their_policies,
crates/xrce-agent/src/daemon/dcps_bridge.rs::tests::a_publisher_is_a_dds_entity_of_its_participants_domain,
crates/xrce-agent/src/daemon/dds_port.rs::tests::publisher_and_subscriber_need_their_participant_and_endpoints_need_them
Status: done — Commits 505c2e56d24. Ein Participant, den der Client nicht hat,
ergibt STATUS_ERR_UNKNOWN_REFERENCE; eine participant_id anderer Art
STATUS_ERR_INVALID_DATA; nichts wird gespeichert. Der DDS-Publisher entsteht
unter dem Participant mit PRESENTATION, ENTITY_FACTORY, PARTITION und
GROUP_DATA.
§7.8.3.1 Table 6 OBJK_SUBSCRIBER
Spec: §7.8.3.1, Table 6, S. 51–52 — wie beim Publisher für den Subscriber.
Repo: crates/xrce-agent/src/daemon/session.rs (plan_dds_create,
participant_of_create, DdsCreate::Container);
crates/xrce-agent/src/daemon/dcps_bridge.rs (RealDdsPort::create_subscriber)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_publisher_or_subscriber_needs_an_existing_participant,
crates/xrce-agent/src/daemon/session.rs::tests::a_publisher_and_a_subscriber_get_a_dds_entity_with_their_policies,
crates/xrce-agent/src/daemon/dds_port.rs::tests::publisher_and_subscriber_need_their_participant_and_endpoints_need_them
Status: done — Commits 505c2e56d24. Wie beim Publisher, für den Subscriber.
§7.8.3.1 Table 6 OBJK_DATAWRITER
Spec: §7.8.3.1, Table 6, S. 52 — “The agent shall locate the XRCE Publisher identified by the publisher_id. If this object is not found the operation shall fail and return STATUS_ERR_UNKNOWN_REFERENCE. […] an associated DDS DataWriter. The DDS DataWriter shall be created using the Publisher identified by the publisher_id.”
Repo: crates/xrce-agent/src/daemon/session.rs (plan_dds_create,
DdsCreate::Endpoint); crates/xrce-agent/src/daemon/dcps_bridge.rs
(RealDdsPort::create_writer)
Tests: crates/xrce-agent/src/daemon/dcps_bridge.rs::tests::create_writer_before_topic_rejected,
crates/xrce-agent/tests/replay_foreign_session.rs::replay_creates_the_dds_entities_the_real_clients_describe,
crates/xrce-agent/src/daemon/session.rs::tests::annex_b_2_3_create_of_a_binary_data_writer,
crates/xrce-agent/src/daemon/session.rs::tests::an_endpoint_and_its_topic_belong_to_one_participant,
crates/xrce-agent/src/daemon/session.rs::tests::a_data_writer_states_its_qos_over_a_profile,
crates/xrce-agent/src/daemon/dds_port.rs::tests::publisher_and_subscriber_need_their_participant_and_endpoints_need_them
Status: done — Der Writer erbt PARTITION und GROUP_DATA des Publisher. Ein Publisher, den der Client nicht hat, ergibt STATUS_ERR_UNKNOWN_REFERENCE; Publisher und Topic müssen zum selben Participant gehören.
§7.8.3.1 Table 6 OBJK_DATAREADER
Spec: §7.8.3.1, Table 6, S. 52 — “OBJK_DATEREADER The ObjectVariant is a DATAWRITER_Representation […]. The agent shall locate the XRCE Subscriber identified by the subscriber_id. If this object is not found the operation shall fail and return STATUS_ERR_UNKNOWN_REFERENCE.”
Repo: crates/xrce-agent/src/daemon/session.rs (plan_dds_create,
DdsCreate::Endpoint); crates/xrce-agent/src/daemon/dcps_bridge.rs
(RealDdsPort::create_reader)
Tests: crates/xrce-agent/tests/replay_foreign_session.rs::replay_creates_the_dds_entities_the_real_clients_describe,
crates/xrce-agent/tests/e2e_udp_loopback.rs::e2e_udp_loopback_keyed_dispose_reliable_besteffort_and_fragments,
crates/xrce-agent/src/daemon/session.rs::tests::an_endpoint_and_its_topic_belong_to_one_participant,
crates/xrce-agent/src/daemon/dds_port.rs::tests::publisher_and_subscriber_need_their_participant_and_endpoints_need_them
Status: done — Die Zeile der Spec schreibt OBJK_DATEREADER und
DATAWRITER_Representation; gemeint sind OBJK_DATAREADER und
DATAREADER_Representation. Der Reader erbt PARTITION und GROUP_DATA des
Subscriber; ein fehlender Subscriber ergibt STATUS_ERR_UNKNOWN_REFERENCE.
§7.8.3.2 update eines bestehenden Objekts
Spec: §7.8.3.2, S. 52 — “This operation shall attempt to update an existing object in the XRCE Agent. If the object exists and the update is successful STATUS_OK shall be returned”.
Repo: crates/xrce-agent/src/daemon/session.rs (create_core);
crates/xrce/src/object_store.rs (ObjectStore::create);
crates/xrce-client/src/lib.rs (XrceClient::update_object)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_create_with_reuse_and_replace_updates_the_object,
crates/xrce-client/src/lib.rs::tests::update_object_sends_a_create_with_reuse_and_replace
Status: done — Commits 3b066516f69. Table 14 und §8.4.13 bilden update auf CREATE
mit reuse und replace ab. Eine gleiche Darstellung (Container und
domain_id eingeschlossen) ergibt STATUS_OK_MATCHED und ändert nichts; eine
abweichende ersetzt das Objekt samt DDS-Seite (STATUS_OK).
§7.8.3.2 update ohne Objekt
Spec: §7.8.3.2, S. 52 — “If the object does not already exist STATUS_ERR_UNKNOWN_REFERENCE shall be returned.”
Repo: crates/xrce-agent/src/daemon/session.rs (create_core);
crates/xrce-agent/src/daemon/config.rs (update_of_missing_object)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::the_update_of_a_missing_object_creates_it_or_is_refused
Status: done — Commits 3b066516f69. Die Spec widerspricht sich: §7.8.3.2 verlangt
STATUS_ERR_UNKNOWN_REFERENCE, Table 5 und §8.4.13 lassen dasselbe CREATE das
Objekt anlegen. Standard ist Table 5 (anlegen); der Agent-Schlüssel
update_of_missing_object: refuse liefert STATUS_ERR_UNKNOWN_REFERENCE.
§7.8.3.2 update mit ungültigen Parametern, Rückkehr zur alten Konfiguration
Spec: §7.8.3.2, S. 52 — “If the update was unsuccessful due to invalid parameters, STATUS_ERR_INVALID_DATA shall be returned. If an update is unsuccessful the referenced object shall return to its previous configuration.”
Repo: crates/xrce-agent/src/daemon/session.rs (create_core,
refuse_create, restore_previous)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_replace_that_fails_returns_the_object_to_its_previous_configuration
Status: done — Commits 70963ac46ec. Eine Darstellung, aus der sich kein Objekt
bilden lässt, wird vor jeder Änderung mit ihrem STATUS abgewiesen
(STATUS_ERR_INVALID_DATA für eine fehlerhafte Darstellung,
STATUS_ERR_UNKNOWN_REFERENCE für eine Referenz, die sich nicht auflöst).
Scheitert die neue DDS-Seite, stellt restore_previous Speichereintrag und
DDS-Seite aus dem gespeicherten Plan wieder her.
§7.8.3.2 update ohne Rechte
Spec: §7.8.3.2, S. 52 — “If the object cannot be updated due to permission restrictions, STATUS_ERR_DENIED shall be returned.”
Repo: crates/xrce-agent/src/daemon/session.rs (create_core, permits);
crates/xrce-agent/src/daemon/access.rs (Operation::Update,
AccessController::permits)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::an_update_needs_the_permission_to_update,
crates/xrce-agent/src/daemon/session.rs::tests::replacing_an_object_needs_the_permission_to_delete_it
Status: done — Commits 5f7a8652d95, 3b066516f69. Ein update (CREATE mit reuse
und replace) braucht die Berechtigung Operation::Update, ein replace ohne
reuse die Berechtigung Operation::Delete; sonst STATUS_ERR_DENIED.
§7.8.3.3 get_info eines Objekts
Spec: §7.8.3.3, S. 52 — “object_info (ObjectInfo): contains the current activity and configuration of the specified object. This operation returns the configuration and activity data for an existing object.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_get_info,
object_info, answer_info); crates/xrce/src/object_info.rs (ObjectInfo);
crates/xrce/src/submessages/info.rs (InfoPayload)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_an_object_returns_the_object_variant_it_was_created_with,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_a_data_writer_reports_its_activity,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_a_data_reader_reports_its_activity,
crates/xrce-agent/src/daemon/session.rs::tests::any_object_id_of_kind_agent_is_the_root_in_a_session
Status: done — Commits ca0cf7e08bf. Die Antwort ist ein INFO mit activity
(DataWriter, DataReader) und config (die ObjectVariant, mit der das Objekt
angelegt wurde); die InfoMask wählt aus. sample_seq_num, stream_seq_num und
highest_acked_num zählt der Agent selbst; die Spec definiert die Werte nicht,
ein Vergleich mit einem anderen Agent wurde nicht gemessen.
§7.8.3.3 get_info ohne Objekt
Spec: §7.8.3.3, S. 53 — “If the object does not already exist STATUS_ERR_UNKNOWN_REFERENCE shall be returned.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_get_info,
answer_info)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_a_missing_object_is_an_info_with_unknown_reference,
crates/xrce-agent/src/daemon/transport.rs::tests::the_udp_listener_answers_get_info_before_a_session
Status: done — Commits ca0cf7e08bf. Der Agent antwortet mit einem INFO, dessen
ResultStatus STATUS_ERR_UNKNOWN_REFERENCE ist und das request_id und
object_id der Anfrage trägt (§8.3.5.7.2: die Antwort auf GET_INFO ist INFO).
§7.8.3.3 get_info ohne Rechte
Spec: §7.8.3.3, S. 53 — “If the object cannot be accessed due to permission restrictions STATUS_ERR_DENIED shall be returned.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_get_info);
crates/xrce-agent/src/daemon/access.rs (Operation::GetInfo)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::get_info_and_delete_without_permission_are_denied
Status: done — Commits 5f7a8652d95. Ohne Berechtigung Operation::GetInfo
antwortet der Agent mit einem INFO mit STATUS_ERR_DENIED; das Objekt bleibt.
§7.8.3.4 delete eines Objekts
Spec: §7.8.3.4, S. 53 — “This operation deletes an existing object. If the object is successfully deleted STATUS_OK shall be returned.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_delete)
Tests: crates/xrce-agent/tests/endpoint_client_fixtures.rs::delete_fixture_decodes_and_removes_the_object_create_added,
crates/xrce-agent/tests/replay_foreign_session.rs::replay_matches_the_real_agents_create_client_create_and_delete_replies,
crates/xrce-agent/src/daemon/session.rs::tests::delete_client_needs_a_proxy_client
Status: done — Die Spec gibt dem Eingang object_id den Typ
ObjectIdPrefix. DELETE(OBJECTID_CLIENT) beendet die Sitzung und löscht den
ProxyClient (d7aec9c2d78).
§7.8.3.4 delete ohne Objekt
Spec: §7.8.3.4, S. 53 — “If the object does not exist STATUS_ERR_UNKNOWN_REFERENCE shall be returned.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_delete)
Tests: crates/xrce-agent/tests/spec_items_session.rs::delete_of_an_object_that_does_not_exist_is_an_unknown_reference, crates/xrce-agent/src/daemon/session.rs::tests::delete_client_needs_a_proxy_client
Status: done — handle_delete antwortet STATUS_ERR_UNKNOWN_REFERENCE, wenn kein Objekt entfernt wurde; für DELETE(OBJECTID_CLIENT) ohne ProxyClient (d7aec9c2d78) und für ein gewöhnliches Objekt (02c704651e4).
### §7.8.3.4 delete ohne Rechte
Spec: §7.8.3.4, S. 53 — “If the object cannot be deleted due to permission restrictions, STATUS_ERR_DENIED shall be returned.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_delete);
crates/xrce-agent/src/daemon/access.rs (Operation::Delete)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::get_info_and_delete_without_permission_are_denied,
crates/xrce-agent/src/daemon/session.rs::tests::replacing_an_object_needs_the_permission_to_delete_it
Status: done — Commits 5f7a8652d95. Ohne Berechtigung Operation::Delete
antwortet der Agent STATUS_ERR_DENIED; das Objekt bleibt.
§7.8.4 XRCE DataWriter
§7.8.4 Table 7 Operation write
Spec: §7.8.4, Table 7, S. 53 — write mit object_id und data.
Repo: —
Tests: —
Status: n/a (informative) — Übersicht.
§7.8.4.1 write schreibt ein oder mehrere Samples
Spec: §7.8.4.1, S. 53 — “This operation writes one or more samples using the XRCE DataWriter identified by the object_id. […] The DataRepresentation type (see 7.7.2) supports multiple DataFormats. This allows sending single data items (FORMAT_DATA) as well as sequences (batches) of data items (FORMAT_SAMPLE_SEQ).”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_write_data,
split_write_items, dds_write_and_report);
crates/xrce-agent/src/daemon/dcps_bridge.rs (RealDdsPort::write,
RealDdsPort::sample_length)
Tests: crates/xrce-agent/tests/e2e_udp_loopback.rs::e2e_udp_loopback_keyed_dispose_reliable_besteffort_and_fragments,
crates/xrce-agent/tests/endpoint_client_fixtures.rs::write_data_fixture_decodes_into_the_sample_bytes_the_client_sent,
crates/xrce-agent/src/daemon/session.rs::tests::a_data_seq_is_split_by_the_type_and_written_sample_by_sample,
crates/xrce-agent/src/daemon/session.rs::tests::a_sample_seq_carries_state_and_time_per_sample,
crates/xrce-agent/src/daemon/session.rs::tests::packed_samples_resolve_their_deltas_against_the_base
Status: done — Commits f40bd568ad1. FORMAT_DATA, FORMAT_SAMPLE, FORMAT_DATA_SEQ,
FORMAT_SAMPLE_SEQ und FORMAT_PACKED_SAMPLES werden geschrieben. Die Elemente
einer Sequenz liegen ohne Länge hintereinander (Annex A sequence<SampleData>);
der Typ des Topic (DdsPort::sample_length) trennt sie. Annahme, nicht gegen
einen anderen Agent gemessen: zwischen den Elementen steht kein Padding, jedes
wird ab Ausrichtungsursprung 0 gelesen (Annex B.5.2 zeigt nur 4-Byte-Elemente).
§7.8.4.1 Sequenzformate beim Schreiben
Spec: §7.8.4.1, S. 53 — wie oben.
Repo: crates/xrce-agent/src/daemon/session.rs (split_write_items,
handle_write_data); crates/xrce-agent/src/daemon/dcps_bridge.rs
(RealDdsPort::sample_length)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_data_seq_is_split_by_the_type_and_written_sample_by_sample,
crates/xrce-agent/src/daemon/session.rs::tests::a_sequence_that_does_not_split_writes_nothing,
crates/xrce-agent/src/daemon/session.rs::tests::a_sequence_of_a_topic_of_unknown_type_is_refused
Status: done — Commits f40bd568ad1. Die drei Sequenzformate werden Sample für
Sample geschrieben. Eine Sequenz, die sich nicht trennen lässt (Anzahl größer
als die Bytes, Bytes hinter dem letzten Sample, abgeschnittenes Sample),
schreibt nichts und ergibt STATUS_ERR_INVALID_DATA. Dasselbe gilt für ein Topic
unbekannten Typs (nur mit unknown_topic_types: forward möglich), dessen
Samples sich nicht trennen lassen.
§7.8.4.1 Erfolg ergibt STATUS_OK
Spec: §7.8.4.1, S. 53 — “If the data is successfully written STATUS_OK shall be returned.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_write_data)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_successful_write_is_answered_with_status_ok
Status: done — Commits 869304e6b63. Ein erfolgreiches WRITE_DATA wird mit einem
STATUS beantwortet, der request_id und DataWriter der Anfrage nennt; mehrere
Samples in einer Anfrage ergeben einen STATUS. Der Mitschnitt des Agents von
eProsima enthält keine Antwort auf WRITE_DATA; der Text der Spec (§8.3.5.8,
Table 14) wird befolgt.
§7.8.4.1 Unbekannter DataWriter
Spec: §7.8.4.1, S. 53 — “If the XRCE DataWriter object identified by the object_id does not exist, the ResultStatus STATUS_ERR_UNKNOWN_REFERENCE shall be returned.”
Repo: crates/xrce-agent/src/daemon/dcps_bridge.rs (RealDdsPort::write);
crates/xrce-agent/src/daemon/session.rs (dds_write_and_report,
dds_port_error_status)
Tests: crates/xrce-agent/src/daemon/dcps_bridge.rs::tests::full_chain_against_a_real_leased_domain
Status: done — RealDdsPort::write gibt für einen Writer, den es nicht
gibt, DdsPortError::UnknownReference zurück; die Sitzung antwortet
STATUS_ERR_UNKNOWN_REFERENCE.
§7.8.4.1 write ohne Rechte
Spec: §7.8.4.1, S. 53 — “If the client is not allowed to write data using the referenced object_id due to permission restrictions, the ResultStatus STATUS_ERR_DENIED shall be returned.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_write_data,
permit); crates/xrce-agent/src/daemon/access.rs (Operation::WriteData)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::write_and_read_without_permission_are_denied
Status: done — Commits 5f7a8652d95. Ohne Berechtigung Operation::WriteData
antwortet der Agent STATUS_ERR_DENIED; nichts erreicht die DDS-Seite.
§7.8.4.1 Ungültige Daten
Spec: §7.8.4.1, S. 53 — “If the data could not be written successfully due, for example invalid data format, the ResultStatus STATUS_ERR_INVALID_DATA shall be returned.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_write_data,
refuse_unreadable, dds_port_error_status);
crates/xrce-agent/src/daemon/dcps_bridge.rs (RealDdsPort::write)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_request_that_cannot_be_read_is_answered_invalid_data,
crates/xrce-agent/src/daemon/session.rs::tests::a_sequence_that_does_not_split_writes_nothing,
crates/xrce-agent/src/daemon/session.rs::tests::a_dispose_the_agent_cannot_identify_is_answered_with_a_status
Status: done — Commits 97de94f63e4, f40bd568ad1. Ein WRITE_DATA, dessen Body
sich nicht lesen lässt, eine Sequenz, die sich nicht trennen lässt, und ein
dispose ohne bestimmbare Instanz ergeben STATUS_ERR_INVALID_DATA. Liest der
bekannte Typ des Topic einen Payload nicht, gibt RealDdsPort::write
DdsPortError::InvalidType zurück (ebenfalls STATUS_ERR_INVALID_DATA); dieser
Zweig hat keinen eigenen Test.
§7.8.4.1 Zeitstempel in SampleInfo
Spec: §7.8.4.1, S. 53 — “The DataRepresentation type also supports sending sample information in addition to the data. This is encoded in the SampleInfo type (see 7.7.1) allowing sending timestamps and also notifications of dispose and unregister.”
Repo: crates/xrce-agent/src/daemon/session.rs (split_write_items,
source_time_of); crates/xrce-agent/src/daemon/dcps_bridge.rs
(RealDdsPort::write, he_timestamp)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_sample_is_stamped_with_the_session_time_plus_its_offset,
crates/xrce-agent/src/daemon/session.rs::tests::a_sample_seq_carries_state_and_time_per_sample,
crates/xrce-agent/src/daemon/dcps_bridge.rs::tests::known_keyed_type_gets_a_real_keyhash_and_honors_dispose
Status: done — Commits f40bd568ad1. Die Merker für dispose und unregister und
session_time_offset werden aus SampleInfo (FORMAT_SAMPLE, FORMAT_SAMPLE_SEQ)
und SampleInfoDelta (FORMAT_PACKED_SAMPLES) gelesen; der Zeitstempel erreicht
den DDS-Writer als Quellzeit.
§7.8.4.1 session_time_offset als Quellzeit
Spec: §7.8.4.1, S. 53 — wie oben.
Repo: crates/xrce-agent/src/daemon/session.rs (source_time_of,
handle_create_client); crates/xrce-agent/src/daemon/dcps_bridge.rs
(RealDdsPort::write)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_sample_is_stamped_with_the_session_time_plus_its_offset,
crates/xrce-agent/src/daemon/session.rs::tests::a_sample_seq_carries_state_and_time_per_sample
Status: done — Commits f40bd568ad1. Die Quellzeit ist die Sitzungszeit plus
session_time_offset. Die Sitzungszeit ist die Uhr des Agents, als die Sitzung
angelegt wurde: Annex A CLIENT_Representation hat kein client_timestamp. Mit
representation_timestamps: present liest der Agent ein client_timestamp,
verwendet es aber nicht als Sitzungszeit. FORMAT_DATA trägt keine SampleInfo und
stempelt nicht.
§7.8.4.1 dispose
Spec: §7.8.4.1, S. 54 — “If the DataRepresentation contains a Sample where the SampleInfo has the ‘dispose’ flag set, the XRCE Agent shall call the dispose operation on the corresponding DDS DataWriter for the instance identified in the associated data.”
Repo: crates/xrce-agent/src/daemon/dcps_bridge.rs (RealDdsPort::write); crates/xrce-agent/src/daemon/session.rs (handle_write_data)
Tests: crates/xrce-agent/src/daemon/dcps_bridge.rs::tests::dispose_on_a_topic_of_unknown_type_is_refused, crates/xrce-agent/src/daemon/session.rs::tests::a_dispose_the_agent_cannot_identify_is_answered_with_a_status, crates/xrce-agent/tests/e2e_udp_loopback.rs::e2e_udp_loopback_keyed_dispose_reliable_besteffort_and_fragments
Status: done — für einen bekannten Typ mit Schlüssel ruft der Agent write_user_lifecycle mit dem Merker DISPOSED und dem echten KeyHash auf (f40bd568ad1). Die Spec verlangt das dispose „for the instance identified in the associated data“; ein Typ ohne Schlüssel oder ein unbekannter Typ identifiziert keine Instanz, die Daten sind für den Agent nicht deutbar: STATUS_ERR_INVALID_DATA (nächstes Item).
### §7.8.4.1 dispose ohne bekannten Typ
Spec: §7.8.4.1, S. 54 — wie oben.
Repo: crates/xrce-agent/src/daemon/dcps_bridge.rs (RealDdsPort::write); crates/xrce-agent/src/daemon/session.rs (handle_write_data)
Tests: crates/xrce-agent/src/daemon/dcps_bridge.rs::tests::dispose_on_a_topic_of_unknown_type_is_refused, crates/xrce-agent/src/daemon/session.rs::tests::a_dispose_the_agent_cannot_identify_is_answered_with_a_status, crates/xrce-agent/tests/e2e_udp_loopback.rs::e2e_udp_loopback_keyed_dispose_reliable_besteffort_and_fragments
Status: done — für ein Topic unbekannten Typs oder eines Typs ohne @key kann der Agent die Instanz nicht aus den Daten bestimmen (SerializedTypeSupport::key_material ist None); eine Instanz, die die Spec identifiziert sehen will, gibt es nicht. RealDdsPort::write schreibt nichts und gibt DdsPortError::InvalidType zurück; die Sitzung antwortet STATUS_ERR_INVALID_DATA, den Status der Spec für Daten, die der Agent nicht deuten kann, und meldet SessionEvent::DdsPortFailed (f40bd568ad1).
### §7.8.4.1 unregister
Spec: §7.8.4.1, S. 54 — “Similarly there is a Sample where the SampleInfo
has the ‘unregister’ flag set, the XRCE Agent shall call the unregister
operation on the corresponding DDS DataWriter for the instance identified in
the associated data.”
Repo: crates/xrce-agent/src/daemon/dcps_bridge.rs (RealDdsPort::write); crates/xrce-agent/src/daemon/session.rs (handle_write_data)
Tests: crates/xrce-agent/src/daemon/dcps_bridge.rs::tests::dispose_on_a_topic_of_unknown_type_is_refused, crates/xrce-agent/src/daemon/session.rs::tests::a_dispose_the_agent_cannot_identify_is_answered_with_a_status, crates/xrce-agent/tests/e2e_udp_loopback.rs::e2e_udp_loopback_keyed_dispose_reliable_besteffort_and_fragments
Status: done — für einen bekannten Typ mit Schlüssel ruft der Agent write_user_lifecycle mit dem Merker UNREGISTERED auf; der native Reader des e2e-Tests sieht die Abmeldung (f40bd568ad1). Für einen Typ ohne Schlüssel oder ohne bekannten Typ gilt wie beim dispose STATUS_ERR_INVALID_DATA.
§7.8.5 XRCE DataReader
§7.8.5 Table 8 Operation read
Spec: §7.8.5, Table 8, S. 54 — read mit object_id,
read_specification und Ausgabe read_data.
Repo: —
Tests: —
Status: n/a (informative) — Übersicht.
§7.8.5.1 read liest Samples
Spec: §7.8.5.1, S. 54 — “This operation reads one or more samples from the XRCE DataReader identified by the object_id. If the data is successfully read STATUS_OK shall be returned.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_read_data,
pump_read, data_submessages)
Tests: crates/xrce-agent/tests/e2e_udp_loopback.rs::e2e_udp_loopback_keyed_dispose_reliable_besteffort_and_fragments,
crates/xrce-agent/src/daemon/session.rs::tests::read_data_elapsed_time_is_measured_from_the_real_request_time,
crates/xrce-agent/src/daemon/session.rs::tests::a_read_for_data_seq_is_answered_with_one_data_seq
Status: done — Commits 8bcb1d00161, fd5253ca805. Der Erfolg ist DATA
(§8.3.5.10) im verlangten data_format.
§7.8.5.1 read ohne Objekt
Spec: §7.8.5.1, S. 54 — “If the object does not exist STATUS_ERR_UNKNOWN_REFERENCE shall be returned.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_read_data);
crates/xrce-agent/src/daemon/dds_port.rs (NullDdsPort::set_read_filter);
crates/xrce-agent/src/daemon/dcps_bridge.rs (RealDdsPort::set_read_filter)
Tests: crates/xrce-agent/src/daemon/dds_port.rs::tests::null_port_rejects_content_filter_but_accepts_clearing_it
Status: done — Ein Reader, den es nicht gibt, ergibt aus
DdsPort::set_read_filter DdsPortError::UnknownReference; handle_read_data
antwortet STATUS_ERR_UNKNOWN_REFERENCE und startet kein Lesen.
§7.8.5.1 read ohne Rechte
Spec: §7.8.5.1, S. 54 — “If the client is not allowed to read data using the referenced object_id due to permission restrictions, STATUS_ERR_DENIED shall be returned.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_read_data,
permit); crates/xrce-agent/src/daemon/access.rs (Operation::ReadData)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::write_and_read_without_permission_are_denied,
crates/xrce-agent/src/daemon/session.rs::tests::read_with_permission_is_not_denied
Status: done — Commits 5f7a8652d95. Ohne Berechtigung Operation::ReadData
antwortet der Agent STATUS_ERR_DENIED und startet kein Lesen.
§7.8.5.1 Table 9 preferred_stream_id
Spec: §7.8.5.1, Table 9, S. 54 — “Specifies the StreamId the Agent should use to send the Samples to the Client. The special value STREAMID_NONE indicates that Agent can choose the StreamId unconstrained. The Agent is allowed to use an StreamId different from the preferred_stream_id if it determines that using the preferred_stream_id could cause problems with its resource-management.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_read_data,
pump_read, ActiveRead)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_sample_above_the_clients_mtu_on_a_reliable_stream_splits_into_fragments,
crates/xrce-agent/src/daemon/session.rs::tests::streamid_none_lets_the_agent_choose_the_stream
Status: done — Commits 8bcb1d00161. DATA geht auf dem gewünschten Stream; für
STREAMID_NONE wählt der Agent STREAMID_BUILTIN_BEST_EFFORTS.
§7.8.5.1 STREAMID_NONE als gewünschter Stream
Spec: §7.8.5.1, Table 9, S. 54 — wie oben.
Repo: crates/xrce-agent/src/daemon/session.rs (handle_read_data)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::streamid_none_lets_the_agent_choose_the_stream
Status: done — Commits 8bcb1d00161. Der Agent wählt den eingebauten
Best-Effort-Stream 0x01; DATA geht nicht auf STREAMID_NONE.
§7.8.5.1 Table 9 data_format
Spec: §7.8.5.1, Table 9, S. 55 — “data_format DataFormat Selects one the data formats. See 7.7.1”; S. 55: “The setting of the data_format controls whether the read operation returns a single sample per message or a collection of samples. It also determines whether the data or it includes the additional information that appears in the SampleInfo”.
Repo: crates/xrce-agent/src/daemon/session.rs (data_submessages,
pump_read, ActiveRead)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_read_for_data_seq_is_answered_with_one_data_seq,
crates/xrce-agent/src/daemon/session.rs::tests::a_read_for_sample_is_answered_with_a_sample_each,
crates/xrce-agent/src/daemon/session.rs::tests::a_read_for_sample_seq_is_answered_with_one_sample_seq,
crates/xrce-agent/src/daemon/session.rs::tests::a_read_for_packed_samples_is_answered_with_one_packed_samples,
crates/xrce-agent/src/daemon/session.rs::tests::the_sequence_formats_split_at_the_size_of_a_submessage,
crates/xrce-client/src/lib.rs::tests::poll_hands_over_the_data_of_every_format
Status: done — Commits fd5253ca805. DATA kommt in FORMAT_DATA, FORMAT_SAMPLE,
FORMAT_DATA_SEQ, FORMAT_SAMPLE_SEQ oder FORMAT_PACKED_SAMPLES, wie verlangt; die
Sequenzformate teilen sich bei der Größe einer Submessage (PACKED_SAMPLES
höchstens 256 Samples). Die SampleInfo-Werte kennt nur der Agent:
sequence_number zählt die gelieferten Samples, session_time_offset ist der
Lieferzeitpunkt, state ist 0, weil DdsPort::poll_samples nur Payload-Bytes
übergibt (kein Quellzeitstempel, kein Instanz-, View- oder Sample-Zustand).
§7.8.5.1 Table 9 content_filter_expression
Spec: §7.8.5.1, Table 9, S. 55 — “A content filter expression selecting which data to read. The syntax shall be as specified in Annex B (Syntax for Queries and Filters) of the DDS specification [DDS].” S. 55: “Only samples for which the filter evaluates to TRUE shall be returned to the XRCE Client.”
Repo: crates/xrce-agent/src/daemon/dcps_bridge.rs
(RealDdsPort::set_read_filter, CompiledReadFilter, drain_buffer);
crates/xrce-agent/src/daemon/session.rs (handle_read_data);
crates/xrce/src/submessages/read_data.rs (ReadSpecification)
Tests: crates/xrce-agent/src/daemon/dcps_bridge.rs::tests::a_content_filter_admits_an_xcdr2_sample,
crates/xrce-agent/src/daemon/session.rs::tests::read_data_with_an_unhonorable_content_filter_is_rejected_not_silently_unfiltered,
crates/xrce/src/submessages/read_data.rs::tests::annex_b_4_2_read_data_with_filter_and_delivery_control,
crates/xrce/src/submessages/read_data.rs::tests::the_content_filter_is_a_string_with_a_nul_and_an_aligned_length
Status: done — Commits b589558e671. Die Kodierung auf der Leitung ist ein
XCDR2-String mit NUL. Ein Filter, den der Agent nicht anwenden kann, ergibt ein
STATUS und liefert keine ungefilterten Daten.
§7.8.5.1 Table 9 max_samples
Spec: §7.8.5.1, Table 9, S. 55 — “Maximum number of samples to return as a result of the read. The special value MAX_SAMPLES_ZERO =0 is used to cancel any prior read operation that may still be active. The special value MAX_SAMPLES_UNLIMITED =0xffff is used to indicate that there is limit on the number of samples returned.”
Repo: crates/xrce/src/continuous_read.rs
(ReadStream::pull_pending_samples, ReadStream::capacity);
crates/xrce-agent/src/daemon/session.rs (pump_read)
Tests: crates/xrce/src/continuous_read.rs::tests::max_samples_cap_enforced,
crates/xrce/src/continuous_read.rs::tests::the_capacity_is_what_the_stream_still_delivers,
crates/xrce-agent/src/daemon/session.rs::tests::a_read_takes_only_the_samples_it_delivers
Status: done — Die Grenze wird gezählt; der Agent nimmt aus dem DataReader
nur die Samples, die das Lesen noch liefert. Der Text zu MAX_SAMPLES_UNLIMITED
sagt „there is limit“; §8.3.5.9.2 (S. 71) sagt „no limit“, dem folgt der Code.
§7.8.5.1 MAX_SAMPLES_ZERO und MAX_SAMPLES_UNLIMITED
Spec: §7.8.5.1, Table 9, S. 55; §8.3.5.9.2, S. 71 — wie oben.
Repo: crates/xrce/src/continuous_read.rs (MAX_SAMPLES_ZERO,
MAX_SAMPLES_UNLIMITED); crates/xrce-agent/src/daemon/session.rs
(handle_read_data)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::max_samples_zero_cancels_the_active_read,
crates/xrce/src/continuous_read.rs::tests::max_samples_zero_ends_the_read_and_unlimited_has_no_limit
Status: done — Commits 8bcb1d00161. 0 beendet das laufende Lesen des DataReader
ohne weiteres DATA; 0xFFFF liest ohne Grenze.
§7.8.5.1 Table 9 max_elapsed_time
Spec: §7.8.5.1, Table 9, S. 55 — “Maximum amount of time in seconds that may be spent delivering the samples from the read operation. […] The special value MAX_ELAPSED_TIME_UNLIMITED = 0 indicates there is no maximum”.
Repo: crates/xrce-agent/src/daemon/session.rs (elapsed_time_limit, handle_read_data)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::max_elapsed_time_is_in_seconds_or_in_the_milliseconds_of_the_example
Status: done — der Agent liest max_elapsed_time als Sekunden (Table 9, die Definition; 0 ist MAX_ELAPSED_TIME_UNLIMITED) und misst ab dem Zeitpunkt der Anfrage. Annex B.4.2 (Beispiel) schreibt für 30 Sekunden 30000; diese Lesart ist die Einstellung max_elapsed_time_unit: milliseconds. 0db56a58a0e.
### §7.8.5.1 max_elapsed_time in Millisekunden nach Annex B.4.2
Spec: Annex B.4.2, S. 152 — “over a time window not to exceed 30 seconds”
mit max_elapsed_time = 30000 = 0x7530; dagegen Table 9, S. 55: “Maximum
amount of time in seconds”.
Repo: crates/xrce-agent/src/daemon/config.rs (max_elapsed_time_unit); crates/xrce-agent/src/daemon/session.rs (SessionEngineConfig::max_elapsed_time_in_milliseconds)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::max_elapsed_time_is_in_seconds_or_in_the_milliseconds_of_the_example, crates/xrce-agent/src/daemon/config.rs::tests::the_unit_of_max_elapsed_time_can_be_set
Status: done — die Lesart des Annex-B-Beispiels (Millisekunden) ist die Einstellung max_elapsed_time_unit: milliseconds. 0db56a58a0e.
### §7.8.5.1 Table 9 max_bytes_per_sec
Spec: §7.8.5.1, Table 9, S. 55 — “Maximum rate in bytes per second at which the data may be returned to the read operation.”
Repo: crates/xrce/src/continuous_read.rs (ReadStream,
ReadStream::pull_pending_samples)
Tests: crates/xrce/src/continuous_read.rs::tests::rate_limit_partitions_samples_over_time
Status: done — Das Feld heißt im IDL max_bytes_per_second.
§7.8.5.1 Table 9 min_pace_period
Spec: §7.8.5.1, Table 9, S. 55 — “Minimum separation between data messages returned from the read operation in milliseconds.” S. 55: “This period makes it possible for the client to go into a sleep cycle between messages.”
Repo: crates/xrce/src/continuous_read.rs
(ReadStream::pull_pending_samples)
Tests: crates/xrce/src/continuous_read.rs::tests::pacing_throttles_per_period
Status: done
§8.1 General
§8.1 Eigenschaften des Protokolls
Spec: §8.1, S. 57 — Bandbreite 40–100 Kbit/s, Schlafphasen, Unabhängigkeit von der Sprache, minimale Discovery, voller Zugang zu DDS, Updates mehrerer Topics, Lieferung verlässlich und best-effort, Sicherheit auf der Ebene des Transports, Zugang zu allen Daten, “Provide a full implementation requiring less than 100KB of code.”
Repo: —
Tests: —
Status: n/a (informative) — Ziele des Entwurfs; die Größe des Codes ist
nicht gemessen.
§8.1 XRCE-Clients ohne Standard-API und ohne Peer-to-Peer
Spec: §8.1, S. 57 — “In contrast to applications that use the DDS API directly, XRCE Clients: Do not have a standard API […]. Cannot operate without infrastructure support. […] Do not communicate directly peer-to-peer.”
Repo: —
Tests: —
Status: n/a (informative) — Beschreibung.
§8.2 Definitions
§8.2 Begriffe client, agent, session, message
Spec: §8.2, S. 57 — “At a high level, a client communicates with an agent using the DDS-XRCE protocol, exchanging messages on a stream belonging to a session.”
Repo: —
Tests: —
Status: n/a (informative) — Begriffe.
§8.2.1 Eine Transportnachricht trägt eine XRCE-Nachricht
Spec: §8.2.1, S. 57 — “The underlying XRCE Transport shall transfer each message as a unit. A single XRCE Transport ‘message’ shall transport a single XRCE message.”
Repo: crates/xrce/src/transport_udp.rs (send_message, recv_message);
crates/xrce/src/transport_tcp.rs (XrceTcpClient::send_message,
recv_message)
Tests: crates/xrce/src/transport_udp.rs::tests::rfc768_udp_delivers_one_datagram_per_message_with_boundaries_intact,
crates/xrce/src/transport_tcp.rs::tests::rfc793_byte_stream_is_delimited_by_the_length_prefix_not_by_writes
Status: done
§8.2.1 Ausrichtung ab dem ersten Byte der Nachricht
Spec: §8.2.1, S. 57 — “XRCE messages shall be encoded assuming the first byte has a 16-byte alignment. Therefore, the encoding is independent of any transport heading or prefix that may precede it.”
Repo: crates/xrce/src/submessages/mod.rs (Message::encode,
Message::decode); crates/xrce-agent/src/daemon/binary_forms.rs
(participant, topic, container, endpoint);
crates/xrce-agent/src/daemon/entity_repr.rs (Cdr)
Tests: crates/xrce/src/submessages/mod.rs::tests::message_two_submessages_padded_correctly
Status: done — Die Codecs der Payloads richten relativ zum Beginn ihrer
Struktur aus; diese Beginne liegen auf Vielfachen von 4. Die Binärformen nach
§7.7.3 liest binary_forms.rs als XCDR2 (Ausrichtung bis 4) relativ zum Beginn
der sequence<octet>, die Strukturen von eProsima liest entity_repr.rs::Cdr
als klassisches CDR (Ausrichtung bis 8) ab demselben Beginn.
§8.2.2 Sitzung mit Handshake
Spec: §8.2.2, S. 58 — “A session defines a bi-directional connection between a client and an agent that has been established with a handshake.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create_client);
crates/xrce-client/src/lib.rs (XrceClient::connect, handle_status_agent)
Tests: crates/xrce-agent/src/daemon/transport.rs::tests::udp_listener_answers_create_client_over_loopback,
crates/xrce-client/src/lib.rs::tests::connect_sends_a_real_create_client_and_moves_to_connecting,
crates/xrce-agent/src/daemon/session.rs::tests::a_wrong_cookie_is_answered_with_a_status_agent
Status: done — Der Agent beantwortet CREATE_CLIENT mit STATUS_AGENT; ein
falsches Cookie ergibt STATUS_AGENT mit STATUS_ERR_INVALID_DATA (d7aec9c2d78).
§8.2.2 Bis zu 256 Streams je Sitzung
Spec: §8.2.2, S. 58 — “A session can contain independent, reliable, and best-effort message streams. Each session may have up to 256 streams.”
Repo: crates/xrce/src/header.rs (StreamId);
crates/xrce-agent/src/daemon/session.rs (SessionEngine::reliable)
Tests: crates/xrce/src/header.rs::tests::stream_id_classification,
crates/xrce-agent/src/daemon/session.rs::tests::reset_clears_reads_backlog_best_effort_counters_and_every_reliable_stream
Status: done — Commits d4aad7c50b6. StreamId hat 256 Werte; der Agent führt den
Zustand je (client, stream), auch für Stream 255 (RESET löscht alle).
§8.2.2 Höchstens eine aktive Sitzung
Spec: §8.2.2, S. 58 — “There can be at most one active session between an XRCE client and an XRCE agent. Creation of a new session closes any previous sessions.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create_client,
refusal, session_ids)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::create_client_different_session_id_resets_object_store,
crates/xrce-agent/src/daemon/session.rs::tests::a_message_of_a_replaced_session_is_not_processed
Status: done — Commits d4aad7c50b6. Eine neue session_id ersetzt die alte
Sitzung; Nachrichten mit der alten session_id werden nicht verarbeitet (siehe
das nächste Item).
§8.2.2 Nachrichten einer beendeten Sitzung
Spec: §8.2.2, S. 58 — wie oben.
Repo: crates/xrce-agent/src/daemon/session.rs (SessionEngine::refusal,
handle_message, SessionEvent::MessageRefused)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_message_of_a_replaced_session_is_not_processed,
crates/xrce-agent/src/daemon/session.rs::tests::a_message_without_a_session_is_not_processed_unless_it_is_a_create_client,
crates/xrce-agent/src/daemon/session.rs::tests::a_create_client_for_a_session_id_of_no_session_is_refused
Status: done — Commits d4aad7c50b6. Eine Nachricht, deren session_id nicht die
aktive Sitzung des Clients ist, wird nicht verarbeitet und nicht beantwortet;
der Agent meldet SessionEvent::MessageRefused. Die Werte 0x00 und 0x80 (keine
Sitzung) nimmt der Agent nur für CREATE_CLIENT und für GET_INFO (§7.8.2.2) an.
§8.2.3 Streams mit eigenen Sequenznummern
Spec: §8.2.3, S. 58 — “A stream represents an independent ordered flow of messages within a session. Messages are ordered within a stream by means of a sequence number. The sequence numbers used by different streams are independent of each other.”
Repo: crates/xrce-agent/src/daemon/session.rs (reliable,
best_effort_seq je (client, stream))
Tests: crates/xrce-agent/src/daemon/session.rs::tests::best_effort_messages_get_increasing_sequence_numbers
Status: done
§8.2.3 Konstante Byte-Reihenfolge je Stream
Spec: §8.2.3, S. 58 — “Streams can be reliable or best efforts. Each stream uses a constant endianness to encode the data in the message/submessage headers and payload.”
Repo: crates/xrce/src/submessages/ (into_submessage aller Payloads mit
FLAG_E_LITTLE_ENDIAN)
Tests: crates/xrce/src/submessages/write_data.rs::tests::write_data_flags_are_e_le_and_format_data
Status: done — ZeroDDS sendet little-endian; beim Empfang folgt jede Payload dem
E-Flag ihrer Submessage (b9255734bfb, 299b3a41398). Die Gleichheit der
Byte-Reihenfolge innerhalb eines Stream prüft der Code nicht.
§8.2.4 Client beginnt die Sitzung
Spec: §8.2.4, S. 58 — “An XRCE client is the entity that initiates the establishment of a session with an XRCE agent.”
Repo: crates/xrce-client/src/lib.rs (XrceClient::connect)
Tests: crates/xrce-client/src/lib.rs::tests::connect_sends_a_real_create_client_and_moves_to_connecting
Status: done
§8.2.5 Agent nimmt Sitzungen an
Spec: §8.2.5, S. 58 — “An XRCE agent is the entity that listens to and accepts requests to establish sessions from XRCE clients.”
Repo: crates/xrce-agent/src/daemon/transport.rs (run_udp_listener)
Tests: crates/xrce-agent/src/daemon/transport.rs::tests::udp_listener_answers_create_client_over_loopback
Status: done
§8.3 Message Structure
§8.3.1 Header und eine oder mehrere Submessages
Spec: §8.3.1, S. 58 — “An XRCE message is composed of a message Header followed by one or more Submessages and shall be transferred as a unit by the underlying XRCE Transport.”
Repo: crates/xrce/src/submessages/mod.rs (Message, Message::new, encode,
decode)
Tests: crates/xrce/src/submessages/mod.rs::tests::message_encode_decode_roundtrip_with_key,
crates/xrce/tests/foreign_frames.rs::every_client_datagram_decodes_and_writes_back,
crates/xrce/tests/wire_roundtrips.rs::a_message_without_a_submessage_is_refused
Status: done — Header und Submessages. Eine Nachricht ohne Submessage lehnen
Message::new, encode und decode ab (d4aad7c50b6, siehe das Item
unten).
§8.3.1 Nachricht ohne Submessage
Spec: §8.3.1, S. 58 — wie oben.
Repo: crates/xrce/src/submessages/mod.rs (Message::new, Message::encode,
Message::decode; Fehler ValueOutOfRange)
Tests: crates/xrce/tests/wire_roundtrips.rs::a_message_without_a_submessage_is_refused
Status: done — Message::new und encode mit einer leeren Liste sowie decode eines
reinen Header liefern einen Fehler (d4aad7c50b6). Die beiden Tests, die den
früheren Zustand festschrieben, prüfen jetzt die Ablehnung.
§8.3.2 Layout des Header
Spec: §8.3.2, S. 59 — sessionId (8 Bit), streamId (8 Bit),
sequenceNr (16 Bit), clientKey (32 Bit, “if sessionId <= 127”).
Repo: crates/xrce/src/header.rs (MessageHeader, write_to, read_from)
Tests: crates/xrce/src/header.rs::tests::header_layout_bytes_no_key,
crates/xrce/src/header.rs::tests::header_layout_bytes_with_key,
crates/xrce/src/header.rs::tests::header_decode_truncated_with_key
Status: done
§8.3.2.1 sessionId mit 8 Bit, eindeutig je Client
Spec: §8.3.2.1, S. 59 — “A session is identified by an 8-bit sessionId. The sessionId is unique to an XRCE Agent for a given XRCE Client. The sessionId also determines whether the Header includes a clientKey or not.”
Repo: crates/xrce/src/header.rs (SessionId);
crates/xrce-agent/src/daemon/session.rs (session_ids)
Tests: crates/xrce/src/header.rs::tests::session_id_127_carries_client_key
Status: done
§8.3.2.1 sessionId 0 bis 127 mit clientKey
Spec: §8.3.2.1, S. 59 — “If the sessionId is between 0 and 127 (0x00 to 0x7f), both included, then the Header shall include the clientKey and the sessionId is scoped by the clientKey.”
Repo: crates/xrce/src/header.rs (SessionId::carries_client_key,
MessageHeader::with_client_key)
Tests: crates/xrce/src/header.rs::tests::header_with_client_key_wire_size_8,
crates/xrce/src/header.rs::tests::header_constructor_rejects_inconsistent_with_key
Status: done
§8.3.2.1 sessionId 128 bis 255 ohne clientKey
Spec: §8.3.2.1, S. 59 — “If the sessionId is between 128 and 255 (0x80 to 0xff), both included, then the Header shall not include the clientKey and the sessionId is scoped by the source address of the message.”
Repo: crates/xrce/src/header.rs (MessageHeader::without_client_key);
crates/xrce-agent/src/daemon/transport.rs (PeerTable)
Tests: crates/xrce/src/header.rs::tests::header_no_client_key_wire_size_4,
crates/xrce-agent/src/daemon/transport.rs::tests::peer_table_resolves_bound_address
Status: done
§8.3.2.1 clientKey aus der Quelladresse
Spec: §8.3.2.1, S. 59 — “If the clientKey does not appear explicitly in the message header, the XRCE Agent must be able to locate it from the source address of the message (see clause 8.3.2.4).”
Repo: crates/xrce-agent/src/daemon/transport.rs (PeerTable::resolve, bind)
Tests: crates/xrce-agent/src/daemon/transport.rs::tests::peer_table_bootstraps_from_create_client_payload,
crates/xrce-agent/src/daemon/transport.rs::tests::a_client_registering_again_is_answered_at_its_new_address
Status: done
§8.3.2.1 SESSION_ID_NONE_WITH_CLIENT_KEY = 0x00
Spec: §8.3.2.1, S. 59 — “The value 0 (0x00) shall be used to indicate the lack of a session within a Header containing a clientKey. This value is referred to as SESSION_ID_NONE_WITH_CLIENT_KEY.”
Repo: crates/xrce/src/header.rs (SESSION_ID_NONE_WITH_CLIENT_KEY,
SessionId::is_none, SessionId::none_like);
crates/xrce-agent/src/daemon/session.rs (refusal, handle_create_client);
crates/xrce-client/src/lib.rs (XrceClient::connect)
Tests: crates/xrce/src/header.rs::tests::only_0x00_and_0x80_are_the_no_session_values,
crates/xrce-agent/src/daemon/session.rs::tests::a_message_without_a_session_is_not_processed_unless_it_is_a_create_client,
crates/xrce-agent/src/daemon/session.rs::tests::a_create_client_for_a_session_id_of_no_session_is_refused,
crates/xrce-client/src/lib.rs::tests::create_client_travels_in_a_header_without_a_session
Status: done — der Client sendet CREATE_CLIENT in einem Header mit 0x00 (Sitzung
0 bis 127) oder 0x80; der Agent verarbeitet in einem solchen Header nur
CREATE_CLIENT (und GET_INFO, §7.8.2.2) und verweigert ein CREATE_CLIENT, das
0x00 oder 0x80 als session_id erbittet (d4aad7c50b6).
§8.3.2.1 SESSION_ID_NONE_WITHOUT_CLIENT_KEY = 0x80
Spec: §8.3.2.1, S. 59 — “The value 128 (0x80) shall be used to indicate the lack of a session within a Header that does not contain a clientKey. This value is referred to as SESSION_ID_NONE_WITHOUT_CLIENT_KEY.”
Repo: crates/xrce/src/header.rs (SESSION_ID_NONE_WITHOUT_CLIENT_KEY,
SessionId::is_none, SessionId::none_like);
crates/xrce-agent/src/daemon/session.rs (refusal);
crates/xrce-agent/src/daemon/discovery.rs (build_info_reply)
Tests: crates/xrce/src/header.rs::tests::only_0x00_and_0x80_are_the_no_session_values,
crates/xrce/src/header.rs::tests::header_roundtrip_no_key,
crates/xrce-agent/src/daemon/session.rs::tests::a_message_without_a_session_is_not_processed_unless_it_is_a_create_client,
crates/xrce-client/src/lib.rs::tests::create_client_travels_in_a_header_without_a_session
Status: done — CREATE_CLIENT eines Client mit session_id 128 bis 255 geht in einem
Header mit 0x80 ohne clientKey; INFO der Discovery nutzt 0x80
(d4aad7c50b6).
§8.3.2.1 Werte für „keine Sitzung“ im Header
Spec: §8.3.2.1, S. 59 — wie oben.
Repo: crates/xrce/src/header.rs (SessionId::is_none, SessionId::none_like);
crates/xrce-agent/src/daemon/session.rs (refusal, handle_create_client,
SessionEvent::MessageRefused);
crates/xrce-client/src/lib.rs (XrceClient::connect, send_control)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_message_without_a_session_is_not_processed_unless_it_is_a_create_client,
crates/xrce-agent/src/daemon/session.rs::tests::a_message_of_a_replaced_session_is_not_processed,
crates/xrce-agent/src/daemon/session.rs::tests::a_create_client_for_a_session_id_of_no_session_is_refused,
crates/xrce-client/src/lib.rs::tests::create_client_travels_in_a_header_without_a_session
Status: done — XrceClient::connect sendet CREATE_CLIENT mit SESSION_ID_NONE_* im
Header (0x00 mit clientKey, 0x80 ohne); der Agent verarbeitet in einem
Header ohne Sitzung nur CREATE_CLIENT und GET_INFO, verweigert 0x00 und 0x80
als erbetene session_id und verwirft Nachrichten einer ersetzten Sitzung
(d4aad7c50b6).
§8.3.2.2 Streams im Rahmen der Sitzung
Spec: §8.3.2.2, S. 59–60 — “Each XRCE message belongs to a single stream. […] Streams are scoped by the session they belong to.”
Repo: crates/xrce-agent/src/daemon/session.rs (reliable,
best_effort_seq mit dem Schlüssel (client, stream))
Tests: crates/xrce-agent/src/daemon/session.rs::tests::best_effort_messages_get_increasing_sequence_numbers
Status: done
§8.3.2.2 STREAMID_NONE
Spec: §8.3.2.2, S. 60 — “The streamId with value 0 (0x00) is referred as STREAMID_NONE. This stream is used for messages exclusively containing submessages that do not belong to any stream.”
Repo: crates/xrce/src/header.rs (StreamId::NONE)
Tests: crates/xrce/src/header.rs::tests::stream_id_classification
Status: done — die Regeln je Submessage stehen bei §8.3.5.11, §8.3.5.12, §8.3.5.15 und §8.3.5.16.
§8.3.2.2 streamId 1 bis 127 best-effort
Spec: §8.3.2.2, S. 60 — “The streams with streamId between 1 (0x01) and 127 (0x7F), both included, shall be best-effort streams.”
Repo: crates/xrce/src/header.rs (StreamId::is_best_effort)
Tests: crates/xrce/src/header.rs::tests::stream_id_classification
Status: done
§8.3.2.2 streamId 128 bis 255 reliable, oberstes Bit als Merker
Spec: §8.3.2.2, S. 60 — “The streams with streamId between 128 (0x80) and 255 (0xFF), both included, shall be reliable streams. Based on the rules above if the streamId is not STREAMID_NONE, then the leading bit of the streamId can be interpreted as a flag that indicates the reliability of the stream.”
Repo: crates/xrce/src/header.rs (StreamId::is_reliable)
Tests: crates/xrce/src/header.rs::tests::stream_id_classification
Status: done
§8.3.2.2 Eingebaute Streams 0x01 und 0x80
Spec: §8.3.2.2, S. 60 — “There are two built-in streams that are created whenever a session is created: A built-in best-effort stream identified by a streamId with value 1 (0x01). […] A built-in reliable stream identified by a streamId with value 128 (0x80).”
Repo: crates/xrce/src/header.rs (StreamId::BUILTIN_BEST_EFFORT,
BUILTIN_RELIABLE); crates/xrce-client/src/lib.rs
(send_maybe_fragmented: Stream 0x80 oder 0x01)
Tests: crates/xrce/src/header.rs::tests::stream_id_classification,
crates/xrce-agent/src/daemon/session.rs::tests::reliable_outbound_messages_get_real_incrementing_sequence_numbers
Status: done — der Zustand eines Stream entsteht beim ersten Gebrauch.
§8.3.2.3 STREAMID_NONE ohne Reihenfolge
Spec: §8.3.2.3, S. 60 — “For the stream with streamId STREAMID_NONE, the sequenceNr does not impose any order; however, it still may be used to discard duplicate messages.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_message: Prüfung der
Reihenfolge nur für Best-Effort- und Reliable-Streams)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::best_effort_streams_drop_duplicates_and_older_messages
Status: done — auf STREAMID_NONE prüft der Agent weder Reihenfolge noch Duplikate;
die Spec erlaubt das Verwerfen von Duplikaten dort, verlangt es nicht
(d4aad7c50b6).
§8.3.2.3 Reihenfolge und Duplikate auf den übrigen Streams
Spec: §8.3.2.3, S. 60 — “For the stream with streamId different from STREAMID_NONE, the sequenceNr imposes an order. Messages within a stream shall not be delivered out of order. In addition, duplicate messages shall be discarded.”
Repo: crates/xrce/src/reliable.rs (recv_data, drain_in_order);
crates/xrce-agent/src/daemon/session.rs (handle_message,
take_best_effort); crates/xrce-client/src/lib.rs (ingest_message)
Tests: crates/xrce/src/reliable.rs::tests::recv_data_reorders_out_of_order,
crates/xrce/src/reliable.rs::tests::recv_data_drops_duplicates,
crates/xrce-agent/src/daemon/session.rs::tests::out_of_order_reliable_messages_wait_for_the_gap_and_report_a_truthful_acknack,
crates/xrce-agent/src/daemon/session.rs::tests::best_effort_streams_drop_duplicates_and_older_messages,
crates/xrce-client/src/lib.rs::tests::a_best_effort_stream_discards_duplicate_and_older_messages
Status: done — Reliable Streams ordnen und verwerfen Duplikate über recv_data und
drain_in_order; Best-Effort-Streams verwerfen Duplikate und ältere
Nachrichten im Agent und im Client (d4aad7c50b6, siehe das Item unten).
§8.3.2.3 Reihenfolge und Duplikate auf Best-Effort-Streams
Spec: §8.3.2.3, S. 60 — wie oben.
Repo: crates/xrce-agent/src/daemon/session.rs (take_best_effort,
best_effort_in, SessionEvent::BestEffortMessageDiscarded);
crates/xrce-client/src/lib.rs (ingest_message, best_effort_in,
ClientEvent::BestEffortMessageDiscarded)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::best_effort_streams_drop_duplicates_and_older_messages,
crates/xrce-client/src/lib.rs::tests::a_best_effort_stream_discards_duplicate_and_older_messages
Status: done — eine Nachricht, die nicht neuer ist als die letzte des Stream (RFC 1982,
16 Bit, auch über den Zählerüberlauf), wird verworfen und als Ereignis
gemeldet; jeder Stream zählt für sich (d4aad7c50b6).
§8.3.2.3 Serial Number Arithmetic mit 16 Bit
Spec: §8.3.2.3, S. 60 — “Addition and comparison of sequence numbers shall use Serial Number Arithmetic as defined by [IETF RFC-1982] with SERIAL_BITS set to 16. This implies that the maximum number of outstanding (unacknowledged) messages for a specific client session stream is limited to 2 15 —that is, 32768.”
Repo: crates/xrce/src/serial_number.rs (SerialNumber16,
wrapping_lt, wrapping_cmp)
Tests: crates/xrce/src/serial_number.rs::tests::lt_across_wrap_boundary,
crates/xrce/src/serial_number.rs::tests::undefined_pair_at_exactly_half_window,
crates/xrce/src/serial_number.rs::tests::wrap_around_does_not_break_lt_for_consecutive_numbers
Status: done — der Sender hält höchstens 16 Nachrichten offen
(SENDER_WINDOW_CAP).
§8.3.2.3 sequenceNr little-endian
Spec: §8.3.2.3, S. 60 — “The sequenceNr shall be encoded using little endian format.”
Repo: crates/xrce/src/header.rs (write_to)
Tests: crates/xrce/src/header.rs::tests::header_layout_bytes_no_key
Status: done
§8.3.2.4 clientKey bei sessionId 0 bis 127
Spec: §8.3.2.4, S. 60 — “The clientKey shall be present on the Header if the sessionId is between 0 and 127. […] If the clientKey is present, it shall contain the ClientKey associated with the XRCE Client.”
Repo: crates/xrce-client/src/lib.rs (header_client_key)
Tests: crates/xrce-agent/tests/endpoint_client_fixtures.rs::every_fixture_shares_the_same_client_key_and_session_id
Status: done
§8.3.2.4 ClientKey aus der Quelladresse ableiten
Spec: §8.3.2.4, S. 60 — “If the clientKey is not present, the XRCE Agent shall be able to derive the ClientKey associated with the XRCE Client from the source address of the message. This means that the ClientKey has either been pre-configured on the XRCE Agent for that particular source address, or it has been exchanged as part of the session establishment.”
Repo: crates/xrce-agent/src/daemon/transport.rs (PeerTable::bind)
Tests: crates/xrce-agent/src/daemon/transport.rs::tests::peer_table_bootstraps_from_create_client_payload
Status: done — über den Austausch im CREATE_CLIENT; eine Vorkonfiguration je Quelladresse gibt es nicht.
§8.3.2.4 Schutz des ClientKey durch den Transport
Spec: §8.3.2.4, S. 60 — “Any exchange of the clientKey is protected by the security mechanisms provided by the XRCE transport.”
Repo: crates/xrce-agent/src/daemon/config.rs (ListenerConfig::Dtls,
ListenerConfig::Tls); crates/xrce-agent/src/daemon/transport/secure.rs;
crates/xrce/src/transport_dtls.rs, crates/xrce/src/transport_tls.rs
Tests: crates/xrce-agent/tests/secure_listeners.rs::tls::a_client_that_trusts_the_agents_certificate_opens_a_session,
crates/xrce-agent/tests/secure_listeners.rs::tls::a_plain_text_create_client_on_the_tls_port_is_not_answered,
crates/xrce-agent/tests/secure_listeners.rs::dtls::a_client_that_trusts_the_agents_certificate_opens_a_session,
crates/xrce-agent/tests/secure_listeners.rs::dtls::a_plain_text_create_client_on_the_dtls_port_is_not_answered
Status: done — Listener kind: dtls und kind: tls mit Zertifikat und Schlüssel aus
PEM-Dateien (eb44fbbf575); auf diesem Port wird Klartext nicht beantwortet.
Die Features dtls und tls gehören nicht zu daemon; ein Binary braucht
--features dtls,tls. Gesicherte Listener erscheinen nicht in GET_INFO(AGENT)
und der Multicast-Discovery. Der DTLS-Handshake eines Peer läuft im
Accept-Task des Listeners, einer nach dem anderen.
§8.3.3 Submessage mit Header und Payload bis 64 KB
Spec: §8.3.3, S. 60 — “Following the message header there shall be one or more submessages. A Submessage shall be composed of a SubmessageHeader and a payload.” Payload “up to to 64 KB”.
Repo: crates/xrce/src/submessages/mod.rs (Submessage,
Submessage::new)
Tests: crates/xrce/src/submessages/mod.rs::tests::message_decode_rejects_truncated_body,
crates/xrce/src/submessages/mod.rs::tests::message_encode_decode_roundtrip_no_key_single_sm
Status: done
§8.3.3 Submessages auf Vielfachen von 4
Spec: §8.3.3, S. 60 — “Submessages shall start at an offset that is a multiple of 4 relative to the beginning of the Message. This means that additional padding may be added between the end of a submessage and the beginning of the next submessage.”
Repo: crates/xrce/src/submessages/mod.rs (Message::encode,
Message::decode: UnalignedSubmessage)
Tests: crates/xrce/src/submessages/mod.rs::tests::message_two_submessages_padded_correctly,
crates/xrce/tests/foreign_frames.rs::every_client_datagram_decodes_and_writes_back
Status: done — nach der letzten Submessage schreibt der Code keine Füllung, eProsima schreibt sie; der Decoder nimmt beides an.
§8.3.4 Layout des SubmessageHeader
Spec: §8.3.4, S. 61 — submessageId (8 Bit), flags (8 Bit),
submessageLength (16 Bit).
Repo: crates/xrce/src/submessages/mod.rs (SubmessageHeader,
to_bytes, from_bytes)
Tests: crates/xrce/src/submessages/mod.rs::tests::submessage_header_roundtrip
Status: done
§8.3.4.1 submessageId
Spec: §8.3.4.1, S. 61 — “The submessageId identifies the kind of submessage. The kinds of submessages are defined in 8.3.5.”
Repo: crates/xrce/src/submessages/mod.rs (SubmessageId::from_u8)
Tests: crates/xrce/src/submessages/mod.rs::tests::submessage_id_rejects_unknown_byte
Status: done — eine unbekannte submessageId verwirft die ganze
Nachricht.
§8.3.4.2 Endianness-Bit in den flags
Spec: §8.3.4.2, S. 61 — “Bit 0, the ‘Endianness’ bit, shall indicate the endianness used to encode the submessage header and payload. If the Endianness bit is set to 0, the encoding shall be big endian and otherwise little endian. The flags field for all submessage kinds shall have the Endianness bit. Specific submessage kinds may define additional flag bits.”
Repo: crates/xrce/src/submessages/mod.rs (FLAG_E_LITTLE_ENDIAN,
SubmessageHeader::body_endianness); crates/xrce/src/handshake.rs,
crates/xrce/src/object_info.rs, crates/xrce/src/transport_locator.rs
(encode_with/decode_with); crates/xrce-agent/src/daemon/session.rs,
crates/xrce-client/src/lib.rs (lesen mit body_endianness)
Tests: crates/xrce/src/submessages/acknack.rs::tests::acknack_be_roundtrip,
crates/xrce/src/submessages/heartbeat.rs::tests::heartbeat_be_roundtrip,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_big_endian_binary_topic_reads_back,
crates/xrce/src/submessages/create_client.rs::tests::create_client_follows_the_e_flag
Status: done — alle Payloads folgen dem Bit (b9255734bfb, 299b3a41398, siehe das
Item unten). Der Agent schreibt seine eigenen Antworten little-endian mit
E=1; jede Submessage nennt ihre Byte-Reihenfolge selbst.
§8.3.4.2 Payloads und das Endianness-Bit
Spec: §8.3.4.2, S. 61 — wie oben.
Repo: crates/xrce/src/handshake.rs (ClientRepresentation,
AgentRepresentation, PropertySeq: encode_with/decode_with);
crates/xrce/src/object_info.rs (ObjectInfo, ActivityInfoVariant);
crates/xrce/src/transport_locator.rs (Ports in der Byte-Reihenfolge des
Flags); crates/xrce/src/submessages/create_client.rs
(CreateClientPayload::into_submessage_with)
Tests: crates/xrce/src/handshake.rs::tests::a_big_endian_client_representation_with_properties_reads_back,
crates/xrce/src/handshake.rs::tests::a_big_endian_agent_representation_with_properties_reads_back,
crates/xrce/src/submessages/create_client.rs::tests::create_client_follows_the_e_flag,
crates/xrce/src/transport_locator.rs::tests::medium_has_a_padding_octet_and_a_port_in_the_byte_order_of_the_flag,
crates/xrce-agent/src/daemon/session.rs::tests::a_big_endian_create_client_with_properties_is_read_right,
crates/xrce-client/src/lib.rs::tests::a_big_endian_status_agent_is_read_with_its_properties
Status: done — ClientRepresentation, AgentRepresentation, PropertySeq,
ObjectInfo, ActivityInfoVariant und die Ports der TransportLocator werden
in der Byte-Reihenfolge des E-Flag gelesen und geschrieben (b9255734bfb,
299b3a41398). Der Agent schreibt das INFO, das er baut, weiter
little-endian mit E=1.
§8.3.4.3 submessageLength ohne Header, little-endian
Spec: §8.3.4.3, S. 61 — “The submessageLength indicates the length of the Submessage (excluding the Submessage header). The submessageLength shall be encoded using little endian format, independent of the value of the flags.”
Repo: crates/xrce/src/submessages/mod.rs (SubmessageHeader::to_bytes)
Tests: crates/xrce/src/submessages/mod.rs::tests::submessage_header_length_is_always_le_even_with_be_body
Status: done
§8.3.4.4 payload mit den Typen von §7.7
Spec: §8.3.4.4, S. 61 — “The definition of the payload shall use the data types defined in clause 7.7.”
Repo: —
Tests: —
Status: n/a (informative) — Aufbau der Spec; die Typen stehen in den
Items zu §7.7.
§8.3.5 Submessage Types
§8.3.5 Table 10 Werte der SubmessageId
Spec: §8.3.5, Table 10, S. 62–63 — CREATE_CLIENT 0, CREATE 1, GET_INFO 2, DELETE 3, STATUS_AGENT 4, STATUS 5, INFO 6, WRITE_DATA 7, READ_DATA 8, DATA 9, ACKNACK 10, HEARTBEAT 11, RESET 12, FRAGMENT 13, TIMESTAMP 14, TIMESTAMP_REPLY 15.
Repo: crates/xrce/src/submessages/mod.rs (SubmessageId)
Tests: crates/xrce/tests/profile_conformance.rs::spec_1_2_submessage_ids_match_spec_assignment,
crates/xrce/src/submessages/mod.rs::tests::submessage_id_roundtrip_all_16_values
Status: done — der Text davor nennt 13 Arten, Table 10 und Figure 7 zeigen 16.
§8.3.5.1 CREATE_CLIENT vom Client
Spec: §8.3.5.1, S. 63 — “The CREATE_CLIENT submessage shall be sent by the XRCE Client to create an XRCE ProxyClient.”
Repo: crates/xrce-client/src/lib.rs (XrceClient::connect)
Tests: crates/xrce-client/src/lib.rs::tests::connect_sends_a_real_create_client_and_moves_to_connecting
Status: done
§8.3.5.1 Empfang ruft create_client
Spec: §8.3.5.1, S. 63 — “Reception of this submessage shall result in the XRCE Agent calling the create_client operation on the XRCE Root object, see 7.8.2.1. The parameters to this operation are obtained from the payload.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create_client)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::create_client_happy_path_registers_and_replies_ok
Status: done
§8.3.5.1 STATUS_AGENT als Antwort
Spec: §8.3.5.1, S. 63 — “The XRCE Agent shall send a STATUS_AGENT message in response, see 8.3.5.5.”
Repo: crates/xrce-agent/src/daemon/session.rs (agent_status_reply,
handle_create_client)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::create_client_happy_path_registers_and_replies_ok,
crates/xrce-agent/src/daemon/session.rs::tests::create_client_rejects_wrong_major_version,
crates/xrce-agent/src/daemon/session.rs::tests::a_wrong_cookie_is_answered_with_a_status_agent
Status: done — jeder Ausgang antwortet mit STATUS_AGENT; ein falsches Cookie oder eine
nicht lesbare Payload ergibt STATUS_AGENT mit STATUS_ERR_INVALID_DATA
(d7aec9c2d78).
§8.3.5.1 Flags von CREATE_CLIENT
Spec: §8.3.5.1.1, S. 63 — “The CREATE_CLIENT submessage does not define any additional flag bits beyond the common ones specified in 8.3.4.2.”
Repo: crates/xrce/src/submessages/create_client.rs
(CreateClientPayload::into_submessage)
Tests: crates/xrce/src/submessages/create_client.rs::tests::create_client_roundtrip_via_submessage,
crates/xrce/src/submessages/create_client.rs::tests::annex_b_1_create_client_example_bytes
Status: done — der Code setzt nur das E-Flag. Annex B.1 nennt 0x07 („reuse, replace“),
die CREATE_CLIENT nicht hat; der Test zu Annex B.1 (be97b3247a6) prüft die
Bytes der CLIENT_Representation, nicht dieses Flag.
§8.3.5.1 Payload CREATE_CLIENT_Payload
Spec: §8.3.5.1.2, S. 64 — “struct CLIENT_Representation { XrceCookie xrce_cookie; XrceVersion xrce_version; XrceVendorId xrce_vendor_id; ClientKey client_key; SessionId session_id; @optional PropertySeq properties; }; struct CREATE_CLIENT_Payload { CLIENT_Representation client_representation; };”
Repo: crates/xrce/src/handshake.rs (ClientRepresentation, encode_form,
decode_form); crates/xrce/src/encoding.rs
(RepresentationTimestamps); crates/xrce/src/submessages/create_client.rs;
Agent-Schlüssel representation_timestamps in
crates/xrce-agent/src/daemon/config.rs; XrceClient::set_representation_timestamps
Tests: crates/xrce/src/submessages/create_client.rs::tests::decodes_the_committed_fixture_member_by_member,
crates/xrce/src/submessages/create_client.rs::tests::annex_b_1_create_client_example_bytes,
crates/xrce/src/handshake.rs::tests::client_representation_decodes_the_captured_create_client_prefix,
crates/xrce/src/handshake.rs::tests::by_default_the_representations_have_no_timestamp,
crates/xrce/src/handshake.rs::tests::the_prose_form_has_a_time_t_after_the_vendor_id,
crates/xrce-client/src/lib.rs::tests::the_representation_timestamp_is_an_option_of_the_client,
crates/xrce-agent/src/daemon/config.rs::tests::the_form_of_the_representations_can_be_set
Status: done — Annex A und die Bytes von Annex B.1 haben kein client_timestamp; das
ist die Voreinstellung. Die Prosa von §7.8.2.1 und §8.3.5.1.2 nennt ein
Time_t hinter xrce_vendor_id; diese Form ist die Einstellung
representation_timestamps: present (Rust:
encoding::RepresentationTimestamps::Present; SDKs: Option representation timestamps) (f8bdf3cd878, 571ee6893d1). Beide Formen sind in zerodds-xrce
und im Client mit Bytes getestet. Zwei Byte nach properties liest und
schreibt der Code als requested_mtu, wie eProsima sie sendet; die Spec
kennt das Feld nicht. PropertySeq ist nach Annex A ausgerichtet
(ca0cf7e08bf).
§8.3.5.2 CREATE vom Client
Spec: §8.3.5.2, S. 64 — “The CREATE submessage shall be sent by the XRCE Client to create an XRCE Object.”
Repo: crates/xrce-client/src/lib.rs (XrceClient::create_object)
Tests: crates/xrce-client/src/lib.rs::tests::create_object_builds_the_real_two_level_object_variant
Status: done
§8.3.5.2 Empfang ruft create mit Flags und Payload
Spec: §8.3.5.2, S. 64 — “Reception of this submessage shall result in the XRCE Agent calling the create operation on the XRCE ProxyClient object […]. The parameters to this operation shall be obtained from the SubmessageHeader flags and payload.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create)
Tests: crates/xrce-agent/tests/replay_foreign_session.rs::replay_matches_the_real_agents_create_client_create_and_delete_replies
Status: done
§8.3.5.2 STATUS als Antwort auf CREATE
Spec: §8.3.5.2, S. 64 — “The XRCE Agent shall send a STATUS submessage in response, see 8.3.5.6.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create, status_reply,
refuse_unreadable)
Tests: crates/xrce-agent/tests/replay_foreign_session.rs::replay_matches_the_real_agents_create_client_create_and_delete_replies,
crates/xrce-agent/src/daemon/session.rs::tests::a_create_without_a_base_object_request_is_answered
Status: done — jede Anfrage erhält STATUS: eine Payload ohne BaseObjectRequest und
eine nicht lesbare Darstellung ergeben STATUS_ERR_INVALID_DATA
(70963ac46ec, 97de94f63e4).
§8.3.5.2 CREATE ohne BaseObjectRequest
Spec: §8.3.5.2, S. 64 — wie oben.
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create,
SessionEvent::CreateRefused)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_create_without_a_base_object_request_is_answered
Status: done — ein CREATE von weniger als 4 Byte ergibt STATUS mit
STATUS_ERR_INVALID_DATA für OBJECTID_INVALID (mit dem request_id, wenn
seine zwei Byte da sind) und ein Ereignis CreateRefused (70963ac46ec).
§8.3.5.2 Flags reuse und replace
Spec: §8.3.5.2.1, S. 64 — “Bit 1, the ‘Reuse’ bit, encodes the value of the CreationMode reuse field. Bit 2, the ‘Replace’ bit, encodes the value of the CreationMode replace field.”
Repo: crates/xrce/src/submessages/create.rs (CREATE_FLAG_REUSE,
CREATE_FLAG_REPLACE)
Tests: crates/xrce/src/submessages/create.rs::tests::create_roundtrip_carries_reuse_replace_flags,
crates/xrce/src/submessages/create.rs::tests::create_default_flags_have_no_reuse_no_replace
Status: done
§8.3.5.2 Payload CREATE_Payload
Spec: §8.3.5.2.2, S. 64–65 — “struct CREATE_Payload : BaseObjectRequest { ObjectVariant object_representation; };”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create:
BaseObjectRequest::decode, ObjectVariant::decode_for_kind)
Tests: crates/xrce-agent/tests/endpoint_client_fixtures.rs::create_fixture_decodes_into_an_object_the_agent_accepts,
crates/xrce/src/object_repr.rs::tests::participant_representation_matches_the_captured_create_bytes
Status: done
§8.3.5.3 GET_INFO vom Client
Spec: §8.3.5.3, S. 65 — “The GET_INFO submessage shall be sent by the XRCE Client to get information about a resource identified by its object_id.”
Repo: crates/xrce-client/src/lib.rs (XrceClient::request_get_info,
XrceClient::request_agent_info, ClientEvent::Info,
ClientEvent::InfoUnreadable)
Tests: crates/xrce-client/src/lib.rs::tests::request_agent_info_works_before_the_session_and_sends_the_mask,
crates/xrce-client/src/lib.rs::tests::request_get_info_needs_a_session_and_names_the_object,
crates/xrce-client/src/lib.rs::tests::an_info_is_read_into_an_event
Status: done — request_get_info fragt nach einem Objekt der Sitzung,
request_agent_info nach dem Agent, auch ohne Sitzung; ein INFO wird als
ClientEvent::Info ausgewertet (ca0cf7e08bf).
§8.3.5.3 Ziel nach der ObjectKind der object_id
Spec: §8.3.5.3, S. 65 — “The targeted XRCE Object shall depend on the ObjectKind encoded in the last 4 bits of the object_id. If the ObjectKind is set to OBJK_AGENT, then it shall result in the XRCE Agent calling the get_info operation on the XRCE Root object […]. If the ObjectKind is set to one of OBJK_PARTICIPANT, […] That is to a value between 0x01 and 0x0c (both included), then it shall result in the XRCE Agent calling the get_info operation on the XRCE ProxyClient object”.
Repo: crates/xrce-agent/src/daemon/session.rs (handle_get_info: Art
OBJK_AGENT ist die Root, 0x01 bis 0x0C der ProxyClient, OBJK_CLIENT die
Sitzung); crates/xrce-agent/src/daemon/discovery.rs
(run_discovery_responder)
Tests: crates/xrce-agent/src/daemon/discovery.rs::tests::discovery_responder_answers_get_info_on_agent,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_the_agent_in_a_session_returns_activity_and_representation,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_without_a_session_is_answered_for_the_agent_only,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_an_object_returns_the_object_variant_it_was_created_with
Status: done — die Root antwortet auf jede object_id der Art OBJK_AGENT, auch
ohne Sitzung; die Arten 0x01 bis 0x0C gehen an den ProxyClient
(ca0cf7e08bf). Die Spec verweist für die Root auf §7.8.3.3 statt §7.8.2.2,
die Liste nennt „OBJK“ statt OBJK_TOPIC.
§8.3.5.3 Unterscheidung nach dem Halbbyte der Art
Spec: §8.3.5.3, S. 65 — wie oben.
Repo: crates/xrce-agent/src/daemon/session.rs (handle_get_info);
crates/xrce-agent/src/daemon/discovery.rs (run_discovery_responder)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::any_object_id_of_kind_agent_is_the_root_in_a_session,
crates/xrce-agent/src/daemon/transport.rs::tests::the_udp_listener_answers_get_info_before_a_session,
crates/xrce-agent/src/daemon/transport.rs::tests::the_tcp_listener_answers_get_info_before_a_session
Status: done — handle_get_info und der Responder prüfen die Art der object_id und
nicht den Wert 0xFFFD; eine ObjectId 0x010 der Art OBJK_AGENT wird von
der Root beantwortet (ca0cf7e08bf, a8f300b7bcf).
§8.3.5.3 INFO als Antwort auf GET_INFO
Spec: §8.3.5.3, S. 65 — “The XRCE Agent shall send an INFO submessage in response to this message, see 8.3.5.6.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_get_info, answer_info,
InfoPayload)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_the_agent_in_a_session_returns_activity_and_representation,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_a_missing_object_is_an_info_with_unknown_reference,
crates/xrce-agent/src/daemon/discovery.rs::tests::discovery_responder_answers_get_info_on_agent
Status: done — jede Antwort auf GET_INFO ist ein INFO; für ein unbekanntes Objekt
trägt es STATUS_ERR_UNKNOWN_REFERENCE, ohne Recht STATUS_ERR_DENIED
(ca0cf7e08bf). Der Verweis lautet auf §8.3.5.6 statt §8.3.5.7.
§8.3.5.3 Flags von GET_INFO
Spec: §8.3.5.3.1, S. 65 — “The GET_INFO submessage does not define any additional flag bits beyond the common ones specified in 8.3.4.2.”
Repo: crates/xrce/src/submessages/get_info.rs
(GetInfoPayload::into_submessage)
Tests: crates/xrce/src/submessages/get_info.rs::tests::get_info_roundtrip
Status: done
§8.3.5.3 Payload GET_INFO_Payload
Spec: §8.3.5.3.2, S. 65 — “struct GET_INFO_Payload : BaseObjectRequest { InfoMask info_mask; };”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_get_info:
BaseObjectRequest::decode, GetInfoPayload::parse);
crates/xrce/src/object_info.rs (InfoMask)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::get_info_without_an_info_mask_is_invalid_data,
crates/xrce/src/object_info.rs::tests::info_mask_bits_and_wire_form,
crates/xrce/src/submessages/get_info.rs::tests::get_info_roundtrip,
crates/xrce-agent/src/daemon/discovery.rs::tests::discovery_responder_answers_get_info_on_agent
Status: done — der Agent liest BaseObjectRequest und info_mask; fehlt die Maske,
antwortet er mit INFO und STATUS_ERR_INVALID_DATA (ca0cf7e08bf). Das
client_info aus Figure 10 (§8.4.4) steht hinter der InfoMask
(GetInfoPayload::with_client_info), weil Annex A dafür kein Mitglied hat.
§8.3.5.4 DELETE vom Client
Spec: §8.3.5.4, S. 65 — “The DELETE submessage shall be sent by the XRCE Client to delete the XRCE:ProxyClient or any other XRCE Object”.
Repo: crates/xrce-client/src/lib.rs (XrceClient::delete_object,
disconnect)
Tests: crates/xrce-client/src/lib.rs::tests::disconnect_sends_delete_client_and_clears_state
Status: done
§8.3.5.4 delete_client bei OBJK_CLIENT, sonst delete
Spec: §8.3.5.4, S. 65–66 — “The related XRCE Object is identified by the object_id field in the payload. If the ObjectVariant contained within the payload has ObjectKind set to OBJK_CLIENT, then the XRCE Agent shall call the delete_client operation. Otherwise it shall call the delete operation.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_delete)
Tests: crates/xrce-agent/tests/replay_foreign_session.rs::replay_matches_the_real_agents_create_client_create_and_delete_replies,
crates/xrce-agent/src/daemon/session.rs::tests::delete_client_needs_a_proxy_client
Status: done — der Code nimmt die Art aus der object_id; ein ObjectVariant hat
DELETE_Payload nicht. delete_client ohne ProxyClient ergibt
STATUS_ERR_UNKNOWN_REFERENCE (d7aec9c2d78).
§8.3.5.4 STATUS als Antwort auf DELETE
Spec: §8.3.5.4, S. 66 — “The XRCE Agent shall send a STATUS submessage in response, see 8.3.5.6.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_delete, status_reply)
Tests: crates/xrce-agent/tests/replay_foreign_session.rs::replay_matches_the_real_agents_create_client_create_and_delete_replies
Status: done — der Code antwortet auf jedes DELETE mit STATUS, auch auf
delete_client, wie der Text der Klausel es sagt. Table 14 (S. 86) nennt für
delete_client STATUS_AGENT; dafür gibt es keine Einstellung.
§8.3.5.4 Flags und Payload DELETE_Payload
Spec: §8.3.5.4.1–§8.3.5.4.2, S. 66 — keine zusätzlichen Flags; “struct DELETE_Payload : BaseObjectRequest { };”
Repo: crates/xrce/src/submessages/delete.rs (DeletePayload)
Tests: crates/xrce-agent/tests/endpoint_client_fixtures.rs::delete_fixture_decodes_and_removes_the_object_create_added
Status: done
§8.3.5.5 STATUS_AGENT auf CREATE_CLIENT
Spec: §8.3.5.5, S. 66 — “The STATUS_AGENT submessage shall be sent by the XRCE Agent in response to a CREATE_CLIENT submessage. The submessage shall contain the returnStatus to the create_client operation invocation”.
Repo: crates/xrce-agent/src/daemon/session.rs (agent_status_reply; SessionEngine::handle_create_client)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::create_client_happy_path_registers_and_replies_ok,
crates/xrce-agent/src/daemon/session.rs::tests::a_wrong_cookie_is_answered_with_a_status_agent,
crates/xrce-agent/src/daemon/session.rs::tests::create_client_rejects_wrong_major_version
Status: done — Commits d7aec9c2d78. auch jeder Fehler von CREATE_CLIENT (falsches
Cookie, session_id ohne Sitzung, falsche Hauptversion, ClientKey nicht
zugelassen, keine Ressourcen) wird als STATUS_AGENT beantwortet, nicht als
STATUS.
§8.3.5.5 Flags von STATUS_AGENT
Spec: §8.3.5.5.1, S. 66 — keine zusätzlichen Flags.
Repo: crates/xrce/src/submessages/status_agent.rs
(StatusAgentPayload::into_submessage)
Tests: crates/xrce/src/submessages/status_agent.rs::tests::status_agent_roundtrip,
crates/xrce-client/src/lib.rs::tests::a_big_endian_status_agent_is_read_with_its_properties
Status: done — der Agent schreibt die Submessage mit gesetztem E-Flag und
ohne weiteres Flag; der Client liest auch E=0 (§8.3.4.2, b9255734bfb).
§8.3.5.5 Payload STATUS_AGENT_Payload
Spec: §8.3.5.5.2, S. 66–67 — “struct STATUS_AGENT_Payload { AGENT_Representation agent_info; }; If the operation fails, the STATUS_AGENT_Payload shall have the ResultStatus within the BaseObjectReply set to with the StatusValue that corresponds to the type of error encountered.”
Repo: crates/xrce-agent/src/daemon/session.rs (agent_status_reply); crates/xrce/src/submessages/status_agent.rs (StatusAgentPayload::result_and_position); crates/xrce-client/src/lib.rs (handle_status_agent)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::the_status_agent_payload_is_annex_a_unless_the_result_status_is_named, crates/xrce-agent/src/daemon/config.rs::tests::the_payload_of_status_agent_can_be_set
Status: done — die IDL von Annex A ist STATUS_AGENT_Payload { AGENT_Representation agent_info; }: ein erfolgreiches CREATE_CLIENT wird mit der AGENT_Representation allein beantwortet (agent_timestamp nur mit representation_timestamps: present). Die Form des Textes und des Mitschnitts von eProsima mit einem ResultStatus davor ist die Einstellung status_agent: with_result_status; ein Fehler trägt das ResultStatus, das der Text ihm gibt, in beiden Formen, weil die IDL keinen Platz dafür hat. Der Client liest beide (am Cookie unterschieden); der Replay setzt die Einstellung. ceff32b54a4.
### §8.3.5.5 request_id und object_id im STATUS_AGENT
Spec: §8.3.5.5.2, S. 67 — “The request_id and object_id within the
BaseObjectReply shall match the namesake fields in the BaseObjectRequest of the
corresponding CREATE_CLIENT message.”
Repo: —
Tests: —
Status: n/a (informative) — Der Text verlangt, dass request_id und object_id im BaseObjectReply des STATUS_AGENT denen des BaseObjectRequest des CREATE_CLIENT gleichen. CREATE_CLIENT_Payload hat in Annex A kein BaseObjectRequest (nur die CLIENT_Representation), also gibt es nichts zu gleichen, und STATUS_AGENT_Payload hat kein BaseObjectReply (siehe das Item zur Nutzlast). Es gibt keine erfüllbare Anforderung.
### §8.3.5.5 xrce_cookie XRCE
Spec: §8.3.5.5.2, S. 67 — “The xrce_cookie shall be set to the four bytes {‘X’, ‘R’, ‘C’, ‘E’}.”
Repo: crates/xrce/src/handshake.rs (XRCE_COOKIE,
AgentRepresentation::encode_into)
Tests: crates/xrce/src/handshake.rs::tests::agent_representation_roundtrip_no_properties,
crates/xrce/src/handshake.rs::tests::agent_representation_decodes_the_captured_status_agent_body
Status: done
§8.3.5.5 xrce_version des Agent
Spec: §8.3.5.5.2, S. 67 — “The xrce_version shall be set to the version of the XRCE protocol that the Agent will implement in its connection to the Client.”
Repo: crates/xrce/src/handshake.rs (XRCE_VERSION);
crates/xrce-agent/src/daemon/session.rs (agent_status_reply)
Tests: crates/xrce/src/handshake.rs::tests::agent_representation_decodes_the_captured_status_agent_body
Status: done
§8.3.5.6 STATUS auf CREATE und DELETE
Spec: §8.3.5.6, S. 67 — “The STATUS submessage shall be sent by the XRCE Agent in response to a CREATE or DELETE.”
Repo: crates/xrce-agent/src/daemon/session.rs (status_reply; handle_create, handle_delete)
Tests: crates/xrce-agent/tests/replay_foreign_session.rs::replay_matches_the_real_agents_create_client_create_and_delete_replies,
crates/xrce-agent/src/daemon/session.rs::tests::delete_client_needs_a_proxy_client,
crates/xrce-agent/src/daemon/session.rs::tests::a_create_without_a_base_object_request_is_answered
Status: done
§8.3.5.6 STATUS auf READ_DATA bei Fehler
Spec: §8.3.5.6, S. 67 — “The STATUS submessage shall also be sent by the XRCE Agent in response to a READ_DATA submessage when the returnStatus to the read_data operation is anything other than STATUS_OK.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_read_data; refuse_unreadable)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::read_data_with_an_unhonorable_content_filter_is_rejected_not_silently_unfiltered,
crates/xrce-agent/src/daemon/session.rs::tests::a_request_that_cannot_be_read_is_answered_invalid_data,
crates/xrce-agent/src/daemon/session.rs::tests::a_sample_too_large_for_data_is_reported
Status: done — Fehler beim Setzen des Filters, eine nicht lesbare Anfrage
(97de94f63e4) und ein Sample, das in keine Submessage passt, werden als STATUS
beantwortet.
§8.3.5.6 STATUS trägt den Rückgabewert der Operation
Spec: §8.3.5.6, S. 67 — “The STATUS submessage shall contain the returnStatus to the operation that was triggered by the corresponding request message.”
Repo: crates/xrce-agent/src/daemon/session.rs (status_reply)
Tests: crates/xrce-agent/tests/replay_foreign_session.rs::replay_matches_the_real_agents_create_client_create_and_delete_replies
Status: done
§8.3.5.6 Flags und Payload STATUS_Payload
Spec: §8.3.5.6.1–§8.3.5.6.2, S. 67 — keine zusätzlichen Flags; “struct STATUS_Payload : BaseObjectReply { }; […] The request_id and object_id within the BaseObjectReply shall match the namesake fields in the corresponding request message.”
Repo: crates/xrce/src/object_info.rs (BaseObjectReply, ResultStatus);
crates/xrce/src/submessages/status.rs (StatusPayload)
Tests: crates/xrce/src/object_info.rs::tests::base_object_reply_roundtrip,
crates/xrce/tests/unannotated_types.rs::the_final_setting_writes_the_reference_implementations_octets,
crates/xrce-agent/tests/replay_foreign_session.rs::replay_matches_the_real_agents_create_client_create_and_delete_replies
Status: done — ResultStatus hat in Annex A keine @extensibility und ist
APPENDABLE: in der Vorgabe trägt es ein DHEADER (BaseObjectReply 10 Byte), mit
unannotated_types: final sind es 6 Byte wie im Mitschnitt; beide Formen werden
gelesen (7f85e76debd, 220857a1e90).
§8.3.5.7 INFO auf GET_INFO
Spec: §8.3.5.7, S. 67 — “The INFO submessage shall be sent by the XRCE Agent to the XRCE Client in response to a GET_INFO message.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_get_info, answer_info);
crates/xrce-agent/src/daemon/discovery.rs (build_info_reply)
Tests: crates/xrce-agent/src/daemon/discovery.rs::tests::discovery_responder_answers_get_info_on_agent,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_the_agent_in_a_session_returns_activity_and_representation,
crates/xrce-agent/src/daemon/transport.rs::tests::the_udp_listener_answers_get_info_before_a_session,
crates/xrce-agent/src/daemon/transport.rs::tests::the_tcp_listener_answers_get_info_before_a_session
Status: done — Commits ca0cf7e08bf, a8f300b7bcf. in der Sitzung, vor einer
Sitzung an UDP- und TCP-Listener und über die Discovery-Gruppe.
§8.3.5.7 Flags von INFO
Spec: §8.3.5.7.1, S. 67 — keine zusätzlichen Flags.
Repo: crates/xrce/src/submessages/info.rs (InfoPayload::into_submessage_with)
Tests: crates/xrce/src/submessages/info.rs::tests::info_roundtrip,
crates/xrce/src/submessages/info.rs::tests::info_payload_is_the_reply_and_the_object_info
Status: done — das E-Flag nennt die Byte-Reihenfolge der Payload; der Agent
schreibt E=1 (ca0cf7e08bf).
§8.3.5.7 Payload INFO_Payload
Spec: §8.3.5.7.2, S. 67–68 — “struct INFO_Payload : BaseObjectReply { ObjectInfo object_info; }; […] The activity and config within members within the INFO_Payload shall contain the value of the identically named output parameters of the get_info operation.”
Repo: crates/xrce/src/submessages/info.rs (InfoPayload::new, InfoPayload::parse);
crates/xrce/src/object_info.rs (BaseObjectReply, ObjectInfo, ActivityInfoVariant);
crates/xrce-agent/src/daemon/session.rs (handle_get_info, object_info, agent_object_info)
Tests: crates/xrce/src/submessages/info.rs::tests::info_payload_is_the_reply_and_the_object_info,
crates/xrce/src/object_info.rs::tests::object_info_puts_the_activity_before_the_config,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_an_object_returns_the_object_variant_it_was_created_with,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_a_data_writer_reports_its_activity,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_a_data_reader_reports_its_activity,
crates/xrce-agent/src/daemon/discovery.rs::tests::the_info_mask_selects_activity_and_configuration
Status: done — Commits ca0cf7e08bf. BaseObjectReply und ObjectInfo (activity
vor config, @optional als Präsenz-Oktett) nach Annex A; activity und
config folgen der InfoMask. Die Werte highest_acked_num (DataReader) sowie
stream_seq_num und sample_seq_num (DataWriter) zählt der Agent selbst; die
Spec definiert sie nicht, gegen einen anderen Agent nicht gemessen.
§8.3.5.7 Fehler im INFO
Spec: §8.3.5.7.2, S. 68 — “If the operation fails the ResultStatus within the BaseObjectReply shall be set to the StatusValue that corresponds to the type of error encountered.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_get_info, answer_info);
crates/xrce-agent/src/daemon/discovery.rs (build_info_reply)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_a_missing_object_is_an_info_with_unknown_reference,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_without_an_info_mask_is_invalid_data,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_and_delete_without_permission_are_denied,
crates/xrce-agent/src/daemon/discovery.rs::tests::a_get_info_without_a_mask_is_answered_with_an_error_info
Status: done — Commits ca0cf7e08bf. ein Fehler von GET_INFO (UNKNOWN_REFERENCE,
INVALID_DATA, DENIED) wird als INFO mit dem Status gesendet, nicht als STATUS.
§8.3.5.7 request_id und object_id des GET_INFO
Spec: §8.3.5.7.2, S. 68 — “The request_id and object_id within the BaseObjectReply shall match the identically named fields in the BaseObjectRequest of the corresponding GET_INFO message.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_get_info: InfoRequest::base, answer_info);
crates/xrce-agent/src/daemon/discovery.rs (build_info_reply)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_the_agent_in_a_session_returns_activity_and_representation,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_a_missing_object_is_an_info_with_unknown_reference,
crates/xrce-agent/src/daemon/session.rs::tests::any_object_id_of_kind_agent_is_the_root_in_a_session,
crates/xrce-agent/src/daemon/discovery.rs::tests::any_object_id_of_kind_agent_is_the_root
Status: done — Commits ca0cf7e08bf. die Tests prüfen request_id und object_id
im INFO, auch für eine object_id der Art OBJK_AGENT außer 0xFFFD.
§8.3.5.8 WRITE_DATA vom Client
Spec: §8.3.5.8, S. 68 — “The WRITE_DATA submessage is used by the XRCE Client to write data using an XRCE DataWriter object within the XRCE Agent.”
Repo: crates/xrce-client/src/lib.rs (XrceClient::request_write,
XrceClient::request_write_sample); crates/xrce/src/submessages/write_data.rs
Tests: crates/xrce/src/submessages/write_data.rs::tests::write_data_matches_the_annex_b_example,
crates/endpoint-e2e/tests/xrce_write_framing.rs::rust_endpoint_frames_conformant_write_data
Status: done — xrce_write_framing.rs prüft die Rahmen der Endpoint-SDKs
weiterer Sprachen gegen denselben Decoder.
§8.3.5.8 Empfang ruft write, STATUS als Antwort
Spec: §8.3.5.8, S. 68 — “Reception of this submessage shall result in the XRCE Agent calling the write operation on an XRCE DataWriter object (see 7.8.4.1). The XRCE Agent shall respond with a STATUS submessage.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_write_data)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_successful_write_is_answered_with_status_ok,
crates/xrce-agent/tests/e2e_udp_loopback.rs::e2e_udp_loopback_keyed_dispose_reliable_besteffort_and_fragments
Status: done — Commits 869304e6b63. write wird aufgerufen; ein Schreiben ohne
Fehler wird mit STATUS_OK beantwortet, ein Fehler mit dessen Status. Die Antwort
folgt dem Text von §8.3.5.8; der Mitschnitt des eProsima-Agent zeigt keine
Antwort auf WRITE_DATA, eine Einstellung dafür gibt es nicht.
§8.3.5.8 DataWriter aus object_id, Daten aus dem Payload
Spec: §8.3.5.8, S. 68 — “The data parameter to the write operation shall be obtained from the payload. The related XRCE DataWriter is identified by the object_id field in the payload. Upon reception of this message the XRCE Agent shall located the XRCE DataWriter identified by the object_id and use it to write the data to the DDS domain.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_write_data, dds_write_and_report)
Tests: crates/xrce-agent/tests/e2e_udp_loopback.rs::e2e_udp_loopback_keyed_dispose_reliable_besteffort_and_fragments,
crates/xrce-agent/src/daemon/session.rs::tests::a_client_writes_through_a_preconfigured_data_writer_without_a_create
Status: done
§8.3.5.8 Flags: Endianness und DataFormat in Bit 1 bis 3
Spec: §8.3.5.8.1, S. 68 — “The WRITE_DATA sub-message uses the lowest order 4 bits of the flags: Bit 0 indicates the ‘Endianness’ […]. Bits 1, 2, and 3 shall be set to indicate the DataFormat used for the payload.”
Repo: crates/xrce/src/submessages/write_data.rs
(DataFormat::to_flag_bits, DataFormat::from_flag_bits, DataFormat::FORMAT_MASK)
Tests: crates/xrce/src/submessages/write_data.rs::tests::write_data_sample_flags_carry_format_sample,
crates/xrce/src/submessages/write_data.rs::tests::write_data_rejects_reserved_format
Status: done
§8.3.5.8 Table 11 Werte der Flags
Spec: §8.3.5.8.1, Table 11, S. 68–69 — FORMAT_DATA 0x0/0x1, FORMAT_SAMPLE 0x2/0x3, FORMAT_DATA_SEQ 0x8/0x9, FORMAT_SAMPLE_SEQ 0xA/0xB, FORMAT_PACKED_SAMPLES 0xE/0xF; Beispiel 0x09 für FORMAT_DATA_SEQ little-endian.
Repo: crates/xrce/src/submessages/write_data.rs (DataFormat)
Tests: crates/xrce/src/submessages/write_data.rs::tests::write_data_flags_are_e_le_and_format_data,
crates/xrce/src/submessages/write_data.rs::tests::data_format_raw_roundtrip,
crates/xrce/src/submessages/write_data.rs::tests::any_write_data_dispatches_every_format
Status: done
§8.3.5.8 Table 12 Payload je DataFormat
Spec: §8.3.5.8.2, Table 12, S. 69–70 — WRITE_DATA_Payload_Data,
_Sample, _DataSeq, _SampleSeq, _PackedSamples; “All the WRITE_DATA
payload representations extend BaseObjectRequest”.
Repo: crates/xrce/src/submessages/write_data.rs (WriteDataPayload,
WriteDataPayloadSample, WriteDataPayloadDataSeq, WriteDataPayloadSampleSeq,
WriteDataPayloadPackedSamples);
crates/xrce-agent/src/daemon/session.rs (split_write_items)
Tests: crates/xrce/src/submessages/write_data.rs::tests::write_data_base_object_request_precedes_the_sample,
crates/xrce/src/submessages/write_data.rs::tests::write_data_sample_seq_matches_annex_b_5_4_layout,
crates/xrce/src/submessages/write_data.rs::tests::write_data_packed_samples_matches_annex_b_5_5_layout,
crates/xrce-agent/src/daemon/session.rs::tests::a_data_seq_is_split_by_the_type_and_written_sample_by_sample,
crates/xrce-agent/src/daemon/session.rs::tests::a_sample_seq_carries_state_and_time_per_sample,
crates/xrce-agent/src/daemon/session.rs::tests::packed_samples_resolve_their_deltas_against_the_base,
crates/xrce-agent/src/daemon/session.rs::tests::a_sequence_that_does_not_split_writes_nothing,
crates/xrce-agent/src/daemon/session.rs::tests::a_sequence_of_a_topic_of_unknown_type_is_refused
Status: done — Commits f40bd568ad1. Codec und Verarbeitung im Agent: die Samples
der drei Sequenzformate werden nach dem Typ des Topics getrennt und einzeln
geschrieben, mit SampleInfo je Sample. Für ein Topic unbekannten Typs ist eine
Sequenz nicht teilbar und wird mit STATUS_ERR_INVALID_DATA beantwortet, ohne
etwas zu schreiben. Annahme, nicht gegen einen anderen Agent gemessen: die
Samples stehen ohne Füllbytes hintereinander, jedes ab Ausrichtung 0 (Annex
B.5.2 zeigt nur 4-Byte-Elemente).
§8.3.5.9 READ_DATA vom Client
Spec: §8.3.5.9, S. 70 — “The READ_DATA submessage is used by the XRCE Client to initiate a reception (read) of data from an XRCE DataReader object within the XRCE Agent.”
Repo: crates/xrce-client/src/lib.rs (XrceClient::request_read)
Tests: crates/xrce-agent/tests/endpoint_client_fixtures.rs::read_data_fixture_decodes_into_a_real_read_specification
Status: done
§8.3.5.9 Empfang ruft read, DATA oder STATUS
Spec: §8.3.5.9, S. 70 — “Reception of this submessage shall result in the XRCE Agent calling the read operation on an XRCE DataReader object (see 7.8.5.1) one or more times. Depending on the returnStatus, the XRCE Agent may respond with a DATA submessages or a STATUS submessage. The read_specification parameters to the read operation shall be obtained from the payload.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_read_data, pump_read)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::read_data_elapsed_time_is_measured_from_the_real_request_time,
crates/xrce-agent/src/daemon/session.rs::tests::read_data_with_an_unhonorable_content_filter_is_rejected_not_silently_unfiltered
Status: done
§8.3.5.9 Ein oder mehrere DATA, DataReader aus object_id
Spec: §8.3.5.9, S. 70 — “The XRCE Agent shall send one or more DATA submessages in response to this message, see 8.3.5.10. The related XRCE DataReader is identified by the object_id field in the payload.”
Repo: crates/xrce-agent/src/daemon/session.rs (pump_read)
Tests: crates/xrce-agent/tests/e2e_udp_loopback.rs::e2e_udp_loopback_keyed_dispose_reliable_besteffort_and_fragments
Status: done
§8.3.5.9 DATA bis zum Endkriterium
Spec: §8.3.5.9, S. 70 — “After reception of this message, the XRCE Agent shall continue to send DATA submessages to the client until either the ‘end criteria’ specified in the payload read_specification and continuous_read_options attained”.
Repo: crates/xrce/src/continuous_read.rs (ReadStream);
crates/xrce-agent/src/daemon/session.rs (tick, pump_read)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::read_data_elapsed_time_is_measured_from_the_real_request_time,
crates/xrce/src/continuous_read.rs::tests::max_samples_cap_enforced
Status: done — Commits 8bcb1d00161. continuous_read_options gibt es in der IDL
nicht; das Gegenstück ist delivery_control (Item „Lesen ohne und mit
continuous_read_options“ unten).
§8.3.5.9 Neues READ_DATA für dieselbe object_id
Spec: §8.3.5.9, S. 70 — “[…] or else a new READ_DATA message for the same object_id is received from the XRCE Client.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_read_data: self.reads.insert)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_new_read_data_replaces_the_active_read
Status: done — das neue Lesen ersetzt das laufende; DATA trägt danach nur die
request_id des neuen.
§8.3.5.9 Steuerung des Zeitpunkts der Lieferung
Spec: §8.3.5.9, S. 71 — “The read operation also allows an XRCE Client to control when data may be sent by the XRCE Agent so that the Agent does not unnecessarily wake up the Client during its sleep cycle.”
Repo: —
Tests: —
Status: n/a (informative) — Zweck; die Felder stehen in den Items zu
Table 9.
§8.3.5.9 Flags von READ_DATA
Spec: §8.3.5.9.1, S. 71 — keine zusätzlichen Flags.
Repo: crates/xrce/src/submessages/read_data.rs
(ReadDataPayload::into_submessage, ReadDataPayload::into_submessage_with)
Tests: crates/xrce/src/submessages/read_data.rs::tests::read_data_minimal_roundtrip
Status: done
§8.3.5.9 Payload READ_DATA_Payload
Spec: §8.3.5.9.2, S. 71 — “struct READ_DATA_Payload : BaseObjectRequest { ReadSpecification read_specification; };”
Repo: crates/xrce/src/submessages/read_data.rs (ReadDataPayload,
ReadSpecification, DataDeliveryControl, DeliveryControlForm);
crates/xrce-client/src/lib.rs (XrceClient::set_delivery_control_form)
Tests: crates/xrce/src/submessages/read_data.rs::tests::read_data_base_object_request_precedes_the_spec,
crates/xrce/src/submessages/read_data.rs::tests::read_data_matches_the_captured_read_data_example,
crates/xrce/src/submessages/read_data.rs::tests::annex_b_4_2_read_data_with_filter_and_delivery_control,
crates/xrce/src/submessages/read_data.rs::tests::the_content_filter_is_a_string_with_a_nul_and_an_aligned_length,
crates/xrce/src/submessages/read_data.rs::tests::the_data_format_octet_has_the_values_of_annex_a
Status: done — Commits b589558e671. BaseObjectRequest und ReadSpecification
nach Annex A (data_format 0x00/0x02/0x08/0x0A/0x0E,
content_filter_expression als XCDR2-String, DataDeliveryControl mit
DHEADER). Der Widerspruch zwischen Annex B.4.2 (DHEADER) und dem Mitschnitt von
eProsima (ohne DHEADER) ist eine benannte Einstellung:
XrceClient::set_delivery_control_form(DeliveryControlForm::Bare) schreibt die
Form ohne DHEADER; der Agent liest beide.
§8.3.5.9 Lesen ohne und mit continuous_read_options
Spec: §8.3.5.9.2, S. 71–72 — “If the continuous_read_options member is not present, then the Agent shall call the read operation just once. As a result the only data returned will be the one already in the DDS DataReader cache. If the continuous_read_options member is present, then the Agent shall call the read operation multiple times. The period of calling shall be no faster than the pace_period. […] The Agent shall stop calling the read operation once either max_total_samples have been returned, or else max_total_elapsed_time has elapsed.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_read_data);
crates/xrce/src/continuous_read.rs (ReadStream::once, ReadStream::new, ReadStream::pull_pending_samples)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_read_without_delivery_control_returns_the_cache_once,
crates/xrce/src/continuous_read.rs::tests::a_read_without_delivery_control_returns_the_cache_once,
crates/xrce-agent/src/daemon/session.rs::tests::next_sample_waits_for_one_sample,
crates/xrce/src/continuous_read.rs::tests::pacing_throttles_per_period,
crates/xrce/src/continuous_read.rs::tests::max_elapsed_time_finalizes,
crates/xrce/src/continuous_read.rs::tests::max_samples_cap_enforced
Status: done — Commits 8bcb1d00161. die IDL kennt continuous_read_options,
pace_period, max_total_samples und max_total_elapsed_time nicht; der Code
nimmt das Vorhandensein von delivery_control als Merker (max_samples,
max_elapsed_time, min_pace_period). Mit delivery_control liest er
fortgesetzt; ohne liest er einmal und liefert, was im Cache liegt. Der
Widerspruch zu Micro-XRCE-DDS 3.0.1 (DataReader::read, aus dem Quelltext
gelesen: nächstes Sample ohne Zeitgrenze) ist die benannte Einstellung
read_without_delivery_control: once | next-sample (Vorgabe once).
§8.3.5.9 Lesen ohne delivery_control liest den Cache einmal
Spec: §8.3.5.9.2, S. 71–72 — wie oben.
Repo: crates/xrce/src/continuous_read.rs (ReadStream::pull_pending_samples);
crates/xrce-agent/src/daemon/session.rs (pump_read)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_read_without_delivery_control_returns_the_cache_once,
crates/xrce-agent/src/daemon/session.rs::tests::next_sample_waits_for_one_sample
Status: done — Commits 8bcb1d00161. ohne delivery_control liefert der Agent
alle Samples im Cache und beendet das Lesen; ein später eintreffendes Sample
liefert er nicht (Vorgabe once). Mit read_without_delivery_control: next-sample liefert er das nächste eintreffende Sample.
§8.3.5.9 MIN_PACE_PERIOD_NONE
Spec: §8.3.5.9.2, S. 72 — “The member min_pace_period may take the special value MIN_PACE_PERIOD_NONE. This value shall indicate that there is no minimum time interval between samples.”
Repo: crates/xrce/src/continuous_read.rs (ReadStream::capacity,
ReadStream::pull_pending_samples: 0 ohne Mindestabstand)
Tests: crates/xrce/src/continuous_read.rs::tests::max_samples_cap_enforced,
crates/xrce/src/continuous_read.rs::tests::rate_limit_partitions_samples_over_time,
crates/xrce/src/continuous_read.rs::tests::pacing_throttles_per_period
Status: done — die Spec gibt MIN_PACE_PERIOD_NONE keinen Wert; der Code
nimmt 0.
§8.3.5.10 DATA bei STATUS_OK, sonst STATUS
Spec: §8.3.5.10, S. 72 — “The DATA submessage shall be sent by the XRCE Agent to the XRCE Client in response to a READ_DATA message when the read operation performed by the XRCE Agent returns STATUS_OK. If the read operation returns any other status the XRCE Agent shall send a STATUS message, not a DATA message.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_read_data,
pump_read)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::read_data_with_an_unhonorable_content_filter_is_rejected_not_silently_unfiltered,
crates/xrce-agent/tests/e2e_udp_loopback.rs::e2e_udp_loopback_keyed_dispose_reliable_besteffort_and_fragments,
crates/xrce-agent/src/daemon/session.rs::tests::a_sample_too_large_for_data_is_reported
Status: done
§8.3.5.10 Folge von DATA bis zum Ende oder Abbruch
Spec: §8.3.5.10, S. 72 — “A single READ_DATA message may result on multiple, possible an open-ended sequence, of DATA submessages sent as a response by the XRCE Agent. The DATA messages will continue to be sent until the one of the terminating conditions on the READ_DATA operation is reached, or until it is explicitly cancelled.”
Repo: crates/xrce-agent/src/daemon/session.rs (tick, pump_read, handle_read_data)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::read_data_elapsed_time_is_measured_from_the_real_request_time,
crates/xrce-agent/src/daemon/session.rs::tests::max_samples_zero_cancels_the_active_read
Status: done — bis zur Endbedingung oder zum Abbruch mit MAX_SAMPLES_ZERO.
§8.3.5.10 request_id und object_id des READ_DATA
Spec: §8.3.5.10, S. 72 — “The request_id and object_id within the DATA payload shall match the namesake fields in the corresponding READ_DATA message.”
Repo: crates/xrce-agent/src/daemon/session.rs (pump_read: ActiveRead::request_id;
data_submessages: BaseObjectRequest)
Tests: crates/xrce-agent/tests/e2e_udp_loopback.rs::e2e_udp_loopback_keyed_dispose_reliable_besteffort_and_fragments,
crates/xrce/src/submessages/data.rs::tests::data_base_object_request_precedes_the_sample
Status: done
§8.3.5.10 Flags von DATA
Spec: §8.3.5.10.1, S. 72 — “The flags shall be interpreted the same way as the flags of the WRITE_DATA submessage.”
Repo: crates/xrce/src/submessages/data.rs (DataPayload::flags,
DataPayloadSample::flags, DataPayloadDataSeq::flags, DataPayloadSampleSeq::flags,
DataPayloadPackedSamples::flags)
Tests: crates/xrce/src/submessages/data.rs::tests::data_uses_id_9,
crates/xrce/src/submessages/data.rs::tests::data_sample_rejects_non_sample_format
Status: done
§8.3.5.10 Format von DATA wie im READ_DATA verlangt
Spec: §8.3.5.10.2, S. 72 — “The format the payload shall match the one requested in the READ_DATA message having the matching request_id. It shall also match the DataFormat encoded in the flags”.
Repo: crates/xrce-agent/src/daemon/session.rs (handle_read_data: ActiveRead::format;
data_submessages)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_read_for_data_seq_is_answered_with_one_data_seq,
crates/xrce-agent/src/daemon/session.rs::tests::a_read_for_sample_is_answered_with_a_sample_each,
crates/xrce-agent/src/daemon/session.rs::tests::a_read_for_sample_seq_is_answered_with_one_sample_seq,
crates/xrce-agent/src/daemon/session.rs::tests::a_read_for_packed_samples_is_answered_with_one_packed_samples,
crates/xrce-agent/src/daemon/session.rs::tests::the_sequence_formats_split_at_the_size_of_a_submessage
Status: done — Commits fd5253ca805. der Agent sendet DATA in dem data_format,
das das READ_DATA verlangt (FORMAT_DATA, _SAMPLE, _DATA_SEQ, _SAMPLE_SEQ,
_PACKED_SAMPLES); die Sequenzformate teilen sich an der Größe einer Submessage.
§8.3.5.10 Table 13 Payload je DataFormat
Spec: §8.3.5.10.2, Table 13, S. 72–73 — DATA_Payload_Data, _Sample,
_DataSeq, _SampleSeq, _PackedSamples; “All the DATA payload
representations extend RelatedObjectRequest.”
Repo: crates/xrce/src/submessages/data.rs (DataPayload,
DataPayloadSample, DataPayloadDataSeq, DataPayloadSampleSeq,
DataPayloadPackedSamples, AnyData);
crates/xrce-agent/src/daemon/session.rs (data_submessages)
Tests: crates/xrce/src/submessages/data.rs::tests::any_data_dispatches_every_format,
crates/xrce/src/submessages/data.rs::tests::data_sample_seq_matches_annex_b_5_4_layout,
crates/xrce-agent/src/daemon/session.rs::tests::a_read_for_sample_seq_is_answered_with_one_sample_seq
Status: done — Commits fd5253ca805. Codec und Agent. In der Liste fehlt nach
DATA_Payload_Sample die schließende Klammer (S. 73). Die SampleInfo füllt
der Agent mit dem, was er kennt: sequence_number zählt die gelieferten
Samples, session_time_offset ist der Lieferzeitpunkt, state ist 0, weil
DdsPort::poll_samples nur die Nutzdaten liefert (Quellzeit, Instanz-, View-
und Sample-Zustand fehlen).
§8.3.5.11 ACKNACK für ein Protokoll unabhängig vom Transport
Spec: §8.3.5.11, S. 74 — “The ACKNACK submessage is used to enable a transport independent reliability protocol to be implemented. If the transport used for a session is able to reliably send messages […] then these messages may not be required.”
Repo: —
Tests: —
Status: n/a (informative) — Zweck; auch über TCP benutzt der Code
ACKNACK.
§8.3.5.11 Agent sendet ACKNACK nur auf HEARTBEAT
Spec: §8.3.5.11, S. 74 — “in general it is expected that it is the XRCE Client that initiates any synchronization, and therefore, the XRCE Agent will only send ACKNACK messages in response to HEARTBEAT messages.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_heartbeat;
keine andere Stelle des Agent erzeugt ACKNACK)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::out_of_order_reliable_messages_wait_for_the_gap_and_report_a_truthful_acknack
Status: done
§8.3.5.11 ACKNACK auf STREAMID_NONE
Spec: §8.3.5.11, S. 74 — “The ACKNACK submessage does not belong to any stream, for this reason the MessageHeader shall have the streamId set to STREAM_ID_NONE”.
Repo: crates/xrce-agent/src/daemon/session.rs (handle_heartbeat); crates/xrce-client/src/lib.rs (handle_heartbeat)
Tests: crates/xrce-agent/tests/spec_items_session.rs::the_acknack_of_the_agent_is_on_streamid_none
Status: done — handle_heartbeat des Agent und XrceClient::handle_heartbeat setzen StreamId::NONE im Header des ACKNACK, der Payload nennt den Stream (02c704651e4).
### §8.3.5.11 Flags von ACKNACK
Spec: §8.3.5.11.1, S. 74 — keine zusätzlichen Flags.
Repo: crates/xrce/src/submessages/acknack.rs
(AckNackPayload::into_submessage)
Tests: crates/xrce/src/submessages/acknack.rs::tests::acknack_roundtrip_via_submessage
Status: done
§8.3.5.11 Payload ACKNACK_Payload
Spec: §8.3.5.11.2, S. 74 — “struct ACKNACK_Payload { short first_unacked_seq_num; octet[2] nack_bitmap; octet stream_id; };”
Repo: crates/xrce/src/submessages/acknack.rs (AckNackPayload,
ACKNACK_BODY_SIZE = 5 Oktette der Member; encode_body, decode_body)
Tests: crates/xrce/src/submessages/acknack.rs::tests::acknack_le_roundtrip,
crates/xrce/src/submessages/acknack.rs::tests::acknack_be_roundtrip,
crates/xrce/tests/unannotated_types.rs::the_default_is_appendable_with_a_dheader,
crates/xrce/tests/unannotated_types.rs::the_final_setting_writes_the_reference_implementations_octets,
crates/xrce/tests/unannotated_types.rs::both_forms_are_read_in_either_setting
Status: done — Commits 7f85e76debd. ACKNACK_Payload hat in Annex A keine
@extensibility und ist APPENDABLE (DDS-XTypes 1.3 §7.3.1.2.1.8): in der
Vorgabe DHEADER (4 Byte) und 5 Byte Member; mit unannotated_types: final sind
es 5 Byte wie im Mitschnitt von eProsima; beide Formen werden gelesen, in allen
SDKs (6bb66e420b7, 82fa0a977e2). Der Text nennt short, Annex A unsigned short für first_unacked_seq_num; beide haben 2 Oktette.
§8.3.5.11 first_unacked_seq_num
Spec: §8.3.5.11.2, S. 74 — “The first_unacked_seq_num shall indicate that all sequence numbers up to but not including it have been received.”
Repo: crates/xrce/src/reliable.rs (ReliableStreamState::pending_acknack:
expected_seq; ReliableStreamState::recv_acknack)
Tests: crates/xrce/src/reliable.rs::tests::pending_acknack_marks_missing_slots,
crates/xrce/src/reliable.rs::tests::recv_acknack_clears_acked_seqnrs
Status: done — das Beispiel darunter sagt „up to and including 99“ für den Wert 100.
§8.3.5.11 nack_bitmap
Spec: §8.3.5.11.2, S. 74 — “The nack_bitmap shall indicate missing sequence numbers, starting from first_unacked_seq_num. […] first_unacked_seq_num set to 100 and nack_bitmap set to 0x4009 […] would indicate that sequence numbers 100, 103, and 114 are missing.”
Repo: crates/xrce/src/reliable.rs (ReliableStreamState::pending_acknack,
ReliableStreamState::recv_acknack: u16::from_le_bytes(nack_bitmap));
crates/xrce-agent/src/daemon/session.rs (handle_acknack);
crates/xrce-client/src/lib.rs (XrceClient::handle_acknack)
Tests: crates/xrce/src/reliable.rs::tests::end_to_end_sender_receiver_with_loss_recovery,
crates/xrce-agent/src/daemon/session.rs::tests::acknack_nack_triggers_retransmission_of_the_exact_buffered_bytes
Status: done — Bit i steht für first_unacked_seq_num + i, nack_bitmap[0]
für die Bits 0 bis 7. Die Spec legt nicht fest, welches Oktett von octet[2]
die niedrigen Bits trägt; alle ACKNACK im Mitschnitt von eProsima haben
nack_bitmap = 0x0000 (mit einem Skript über die Datei gezählt), die
Reihenfolge ist daran nicht prüfbar.
§8.3.5.11 stream_id des ACKNACK
Spec: §8.3.5.11.2, S. 74 — “The stream_id indicates the stream to which the ACKNACK is directed.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_acknack:
self.reliable.get_mut(&(client, ack.stream_id)))
Tests: crates/xrce-agent/src/daemon/session.rs::tests::acknack_nack_triggers_retransmission_of_the_exact_buffered_bytes
Status: done
§8.3.5.12 HEARTBEAT für ein Protokoll unabhängig vom Transport
Spec: §8.3.5.12, S. 74 — “The HEARTBEAT submessage is used to enable a transport independent reliability protocol to be implemented. […] If a session transport is able to reliably send messages […] then these messages may not be required.”
Repo: —
Tests: —
Status: n/a (informative) — Zweck.
§8.3.5.12 HEARTBEAT nur bei aktivem Client
Spec: §8.3.5.12, S. 74 — “This specification does not dictate the timing of HEARTBEAT messages. However, in general it is expected that it is the XRCE Agent will only send HEARTBEAT messages when it has some indication that the XRCE Client is active and not in a sleep cycle.”
Repo: —
Tests: —
Status: open — eine Erwartung, die das Produkt erfüllen kann. crates/xrce/src/reliable.rs sendet HEARTBEAT in tick alle DEFAULT_HEARTBEAT_PERIOD (500 ms), solange unbestätigte Nachrichten bestehen und die Sitzung nicht abgelaufen ist, ohne Rücksicht auf eine Ruhephase des Client.
§8.3.5.12 HEARTBEAT auf STREAMID_NONE
Spec: §8.3.5.12, S. 74 — “The HEARTBEAT submessage does not belong to any stream, for this reason the MessageHeader shall have the stream_id set to STREAM_ID_NONE”.
Repo: crates/xrce-agent/src/daemon/session.rs (tick);
crates/xrce-client/src/lib.rs (XrceClient::tick)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_heartbeat_of_the_agent_is_on_streamid_none,
crates/xrce-client/src/lib.rs::tests::a_heartbeat_of_the_client_is_on_streamid_none
Status: done — der Header von HEARTBEAT trägt STREAMID_NONE, die Payload den Stream, den es meldet.
§8.3.5.12 Flags von HEARTBEAT
Spec: §8.3.5.12.1, S. 74 — keine zusätzlichen Flags.
Repo: crates/xrce/src/submessages/heartbeat.rs
(HeartbeatPayload::into_submessage)
Tests: crates/xrce/src/submessages/heartbeat.rs::tests::heartbeat_roundtrip_via_submessage
Status: done
§8.3.5.12 Payload HEARTBEAT_Payload
Spec: §8.3.5.12.2, S. 75 — “struct HEARTBEAT_Payload { short first_unacked_seq_nr; short last_unacked_seq_nr; octet stream_id; };”
Repo: crates/xrce/src/submessages/heartbeat.rs (HeartbeatPayload,
HEARTBEAT_BODY_SIZE = 5)
Tests: crates/xrce/src/submessages/heartbeat.rs::tests::heartbeat_le_roundtrip,
crates/xrce/src/submessages/heartbeat.rs::tests::heartbeat_be_roundtrip
Status: done — Annex A schreibt @extensibility(FINAL): 5 Byte ohne
DHEADER. Annex A nennt die Member first_unacked_seq_num und
last_unacked_seq_num (unsigned short), der Text first_unacked_seq_nr und
last_unacked_seq_nr (short); der Code heißt _nr und hat i16, beide haben
2 Oktette.
§8.3.5.12 first_unacked_seq_nr und last_unacked_seq_nr
Spec: §8.3.5.12.2, S. 75 — “The first_unacked_seq_nr indicates the first available message sequence number on the sending side. The last_unacked_seq_nr indicates the first available message sequence number on the sending side.”
Repo: crates/xrce/src/reliable.rs (ReliableStreamState::pending_heartbeat:
window_base und das größte offene seq)
Tests: crates/xrce/src/reliable.rs::tests::pending_heartbeat_fires_first_time,
crates/xrce/src/reliable.rs::tests::heartbeat_window_end_with_hole_is_serial_max_not_count
Status: done — der Satz zu last_unacked_seq_nr wiederholt den zu
first_unacked_seq_nr; der Code setzt die letzte offene Nummer.
§8.3.5.12 stream_id des HEARTBEAT
Spec: §8.3.5.12.2, S. 75 — “The stream_id indicates the stream to which the HEARTBEAT is directed.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_heartbeat:
Zustand je hb.stream_id)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::out_of_order_reliable_messages_wait_for_the_gap_and_report_a_truthful_acknack
Status: done
§8.3.5.13 RESET setzt den Zustand der Sitzung zurück
Spec: §8.3.5.13, S. 75 — “The RESET submessage shall be used to reset and re-establish a session. It contains no payload. It shall cause the XRCE Agent to reset all state associated with the session_id indicated in the submessage header.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_reset);
crates/xrce/src/reliable.rs (ReliableStreamState::reset)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::reset_clears_reads_backlog_best_effort_counters_and_every_reliable_stream,
crates/xrce/src/reliable.rs::tests::reset_clears_state_completely
Status: done — Commits d4aad7c50b6. RESET setzt zurück: alle Reliable Streams
(auch Stream 255), die Reassemblierung von FRAGMENT, die laufenden Lesevorgänge,
den Rückstau auf volle Sender-Fenster und die Zähler der Best-Effort-Streams,
ein- und ausgehend. Die Objekte des ProxyClient und seine session_id bleiben;
ob „all state“ sie meint, legt die Spec nicht fest.
§8.3.5.13 Laufendes Lesen und Zähler nach RESET
Spec: §8.3.5.13, S. 75 — wie oben.
Repo: crates/xrce-agent/src/daemon/session.rs (handle_reset)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::reset_clears_reads_backlog_best_effort_counters_and_every_reliable_stream
Status: done — Commits d4aad7c50b6. handle_reset beendet laufende READ_DATA,
leert den Rückstau und setzt die Zähler der Best-Effort-Streams zurück; der Test
ruft RESET über die Sitzung.
§8.3.5.13 Flags und leerer Payload von RESET
Spec: §8.3.5.13.1–§8.3.5.13.2, S. 75 — keine zusätzlichen Flags; “The RESET submessage shall have an empty payload.”
Repo: crates/xrce/src/submessages/reset.rs (ResetPayload)
Tests: crates/xrce/src/submessages/reset.rs::tests::reset_roundtrip_empty_body,
crates/xrce/src/submessages/reset.rs::tests::reset_rejects_nonempty_body
Status: done
§8.3.5.14 FRAGMENT für Submessages über der MTU
Spec: §8.3.5.14, S. 75 — “The FRAGMENT submessage is used to enable sending of other submessages whose length exceeds the transport MTU.”
Repo: crates/xrce-agent/src/daemon/session.rs (emit_possibly_fragmented);
crates/xrce-client/src/lib.rs (XrceClient::send_maybe_fragmented)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_sample_above_the_clients_mtu_on_a_reliable_stream_splits_into_fragments,
crates/xrce-client/src/lib.rs::tests::write_above_mtu_splits_into_fragments,
crates/xrce-agent/src/daemon/session.rs::tests::a_fragment_run_without_a_submessage_is_answered_invalid_data
Status: done — die MTU kommt aus dem Feld requested_mtu, das eProsima
anhängt; fehlt es, gelten 508 Byte. FRAGMENT nur auf Reliable Streams
(§8.3.5.14): auf einem Best-Effort-Stream sendet der Agent eine zu große
Submessage ungeteilt und meldet SessionEvent::ReliableSendOverflowed. Ein Lauf
ohne Submessage wird abgelehnt (622d2496da0).
§8.3.5.14 FRAGMENT nur auf Reliable Streams
Spec: §8.3.5.14, S. 75 — “The FRAGMENT message shall only be sent within reliable streams.”
Repo: crates/xrce-agent/src/daemon/session.rs (emit_possibly_fragmented:
auf Best-Effort-Streams ganz gesendet); crates/xrce-client/src/lib.rs
(send_maybe_fragmented)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_sample_above_the_clients_mtu_on_a_reliable_stream_splits_into_fragments,
crates/xrce-client/src/lib.rs::tests::write_above_mtu_splits_into_fragments,
crates/xrce-agent/tests/e2e_udp_loopback.rs::e2e_udp_loopback_keyed_dispose_reliable_besteffort_and_fragments
Status: done — Agent und Client zerlegen nur auf Reliable Streams; eine
Submessage über der MTU geht auf einem Best-Effort-Stream ganz hinaus (Ereignis
ReliableSendOverflowed). Beim Empfang setzt der Code FRAGMENT auf jedem Stream
zusammen. Der Best-Effort-Zweig hat keinen eigenen Test.
§8.3.5.14 Bit Last Fragment
Spec: §8.3.5.14, S. 75 — “all FRAGMENT submessage except for the last shall have the ‘Last Fragment’ bit in the flags set to 0. The last FRAGMENT submessage shall have the ‘Last Fragment’ flag set 1.”
Repo: crates/xrce/src/submessages/fragment.rs (FRAGMENT_FLAG_LAST)
Tests: crates/xrce/src/submessages/fragment.rs::tests::fragment_roundtrip_carries_last_flag,
crates/xrce/src/submessages/fragment.rs::tests::fragment_intermediate_has_no_last_flag
Status: done
§8.3.5.14 Zusammensetzen und Auslegen als Submessages
Spec: §8.3.5.14, S. 75 — “Upon reception of the last fragment submessage the Agent shall concatenate the payload bytes of all FRAGMENT messages for that Stream in the order of the stream sequence number without sequence number gaps. The concatenated payloads shall be interpreted as XRCE submessages as if they had been received following the HEADER that came with the last fragment.”
Repo: crates/xrce-agent/src/daemon/session.rs
(process_message_submessages); crates/xrce/src/fragment.rs
(FragmentAssembler::add_fragment); crates/xrce/src/submessages/mod.rs
(decode_submessages)
Tests:
crates/xrce-agent/src/daemon/session.rs::tests::multi_fragment_create_reassembles_correctly,
crates/xrce-agent/src/daemon/session.rs::tests::a_second_fragmented_message_reassembles_like_the_first,
crates/xrce-agent/src/daemon/session.rs::tests::a_fragmented_run_of_two_submessages_runs_both
Status: done — die Bytes werden in der Reihenfolge des Stream zusammengesetzt und unter dem Header der Nachricht mit dem letzten Fragment verarbeitet, jede Submessage des Laufs (8e0bfe868aa).
§8.3.5.14 Alle Submessages der zusammengesetzten Folge
Spec: §8.3.5.14, S. 75 — wie oben.
Repo: crates/xrce/src/submessages/mod.rs (decode_submessages);
crates/xrce-agent/src/daemon/session.rs (process_message_submessages);
crates/xrce-client/src/lib.rs (XrceClient, ClientEvent::FragmentDiscarded)
Tests: crates/xrce/src/submessages/mod.rs::tests::a_submessage_run_decodes_every_submessage_past_the_padding,
crates/xrce-agent/src/daemon/session.rs::tests::a_fragmented_run_of_two_submessages_runs_both,
crates/xrce-agent/src/daemon/session.rs::tests::a_fragment_run_without_a_submessage_is_answered_invalid_data,
crates/xrce-client/src/lib.rs::tests::a_fragment_run_without_a_submessage_is_reported
Status: done — Agent und Client nehmen jede Submessage des zusammengesetzten
Laufs, auf Vielfachen von 4 (§8.3.3) (8e0bfe868aa). Ein Lauf ohne Submessage
oder ohne Folge von Submessages ergibt beim Agent STATUS
STATUS_ERR_INVALID_DATA, beim Client ClientEvent::FragmentDiscarded
(622d2496da0).
§8.3.5.14 Flags von FRAGMENT
Spec: §8.3.5.14.1, S. 75 — “Bit 0 indicates the ‘Endianness’ […]. Bit 1, the ‘Last Fragment’ bit, indicates the last fragment in the sequence.”
Repo: crates/xrce/src/submessages/fragment.rs (FragmentPayload::flags)
Tests: crates/xrce/src/submessages/fragment.rs::tests::fragment_roundtrip_carries_last_flag
Status: done
§8.3.5.14 Payload von FRAGMENT im Puffer
Spec: §8.3.5.14.2, S. 75 — “The payload of the FRAGMENT submessage is opaque. The Agent shall cache the payload bytes of all FRAGMENT submessages for a Stream in the order of the stream sequence number until the last FRAGMENT submessage is received.”
Repo: crates/xrce/src/fragment.rs (FragmentAssembler);
crates/xrce-agent/src/daemon/session.rs (FragmentRun)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_tick_between_fragments_keeps_the_reassembly,
crates/xrce/src/fragment.rs::tests::out_of_order_reassembly
Status: done — ein unvollständiger Lauf wird nach 10 s verworfen
(DEFAULT_GC_TTL) und als Ereignis gemeldet.
§8.3.5.15 TIMESTAMP senden
Spec: §8.3.5.15, S. 76 — “The TIMESTAMP submessage is used to send timestamp information. […] The TIMESTAMP submessage does not belong to any stream, for this reason the MessageHeader shall have the streamId set to STREAM_ID_NONE”. §8.3.5.15.2: “The transmit_timestamp shall contain the timestamp of the sender of the message at the time the message is sent.”
Repo: crates/xrce-agent/src/daemon/session.rs
(SessionEngine::request_timestamp, tick mit timestamp_interval,
handle_timestamp_reply); crates/xrce-client/src/lib.rs
(XrceClient::send_timestamp, send_timestamp_reply)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::the_agent_sends_a_timestamp_and_reads_the_reply,
crates/xrce-agent/src/daemon/session.rs::tests::tick_sends_a_timestamp_every_interval,
crates/xrce-client/src/lib.rs::tests::the_client_sends_and_reads_timestamps
Status: done — Agent und Client senden TIMESTAMP auf STREAMID_NONE mit der
Uhrzeit des Senders (b224ed97138). Der Agent sendet ungefragt im Abstand des
Agent-Schlüssels timestamp_interval_secs; Vorgabe 0 (keine), weil die
eProsima-Clients keine TIMESTAMP erwarten. Die TIMESTAMP_REPLY des Client ergibt
das Ereignis ClockSynchronised.
§8.3.5.15 Flags und Payload TIMESTAMP_Payload
Spec: §8.3.5.15.1–§8.3.5.15.2, S. 76 — keine zusätzlichen Flags; “struct TIMESTAMP_Payload { Time_t transmit_timestamp; };”
Repo: crates/xrce/src/submessages/timestamp.rs (TimestampPayload,
TimePoint, TimePoint::encode_into, TimePoint::decode_at)
Tests: crates/xrce/src/submessages/timestamp.rs::tests::timestamp_roundtrip_via_submessage,
crates/xrce/src/submessages/timestamp.rs::tests::time_t_roundtrip_be,
crates/xrce/src/submessages/timestamp.rs::tests::a_timestamp_body_has_the_dheader_of_an_appendable_time_t
Status: done — TIMESTAMP_Payload ist @extensibility(FINAL); Time_t hat
in Annex A keine Angabe und ist APPENDABLE (Body: DHEADER 8 und 8 Oktette). Die
8 Oktette der Referenzimplementierung schreibt die Einstellung
unannotated_types: final (Rust UnannotatedTypes::Final); beide Formen werden
gelesen (7f85e76debd, 220857a1e90).
§8.3.5.16 TIMESTAMP_REPLY als Antwort
Spec: §8.3.5.16, S. 76 — “The TIMESTAMP_REPLY submessage is used to reply to a timestamp information message.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_timestamp)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::timestamp_reply_echoes_originate_and_uses_real_wall_clock,
crates/xrce-agent/src/daemon/session.rs::tests::the_agent_sends_a_timestamp_and_reads_the_reply,
crates/xrce-client/src/lib.rs::tests::the_client_sends_and_reads_timestamps
Status: done — der Agent beantwortet TIMESTAMP, der Client beantwortet die
TIMESTAMP des Agent (send_timestamp_reply).
§8.3.5.16 TIMESTAMP_REPLY auf STREAMID_NONE
Spec: §8.3.5.16, S. 76 — “The TIMESTAMP_REPLY submessage does not belong to any stream, for this reason the MessageHeader shall have the streamId set to STREAM_ID_NONE”.
Repo: crates/xrce-agent/src/daemon/session.rs (handle_timestamp); crates/xrce-client/src/lib.rs (send_control)
Tests: crates/xrce-agent/tests/spec_items_session.rs::the_timestamp_reply_of_the_agent_is_on_streamid_none
Status: done — der Code setzt StreamId::NONE in der Antwort des Agent und des Client; der Test prüft den Header der TIMESTAMP_REPLY des Agent (02c704651e4).
### §8.3.5.16 Flags und Payload TIMESTAMP_REPLY_Payload
Spec: §8.3.5.16.1–§8.3.5.16.2, S. 76 — keine zusätzlichen Flags; “struct TIMESTAMP_REPLY_Payload { Time_t transmit_timestamp; Time_t receive_timestamp; Time_t originate_timestamp; };”
Repo: crates/xrce/src/submessages/timestamp_reply.rs
(TimestampReplyPayload)
Tests: crates/xrce/src/submessages/timestamp_reply.rs::tests::timestamp_reply_roundtrip_le,
crates/xrce/src/submessages/timestamp_reply.rs::tests::timestamp_reply_roundtrip_via_submessage,
crates/xrce/src/transport_udp.rs::tests::loopback_roundtrip_timestamp_reply
Status: done — TIMESTAMP_REPLY_Payload ist @extensibility(FINAL) mit
drei Time_t, jedes APPENDABLE (DHEADER 8, zusammen 36 Oktette); mit
unannotated_types: final drei mal 8 Oktette; beide Formen werden gelesen
(7f85e76debd).
§8.3.5.16 Bedeutung der drei Zeitstempel
Spec: §8.3.5.16.2, S. 76 — “The transmit_timestamp shall contain the timestamp of the sender of the TIMESTAMP_REPLY message at the time the message is sent. The originate_timestamp shall contain the transmit_timestamp of the related TIMESTAMP […]. The receive_timestamp the shall contain the timestamp at which the related TIMESTAMP message was received.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_timestamp,
wall_clock_now, handle_timestamp_reply)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::timestamp_reply_echoes_originate_and_uses_real_wall_clock,
crates/xrce-agent/src/daemon/session.rs::tests::the_agent_sends_a_timestamp_and_reads_the_reply
Status: done — originate_timestamp ist die transmit_timestamp der
TIMESTAMP; transmit_timestamp und receive_timestamp der Antwort des Agent
stammen aus einer Ablesung der Uhr. Aus den vier Zeiten einer TIMESTAMP_REPLY
des Client berechnet der Agent Versatz und Umlaufzeit.
§8.4 Interaction Model
§8.4.1 Typische Abläufe, teils durch Konfiguration ersetzbar
Spec: §8.4.1, S. 77 — “This section describes typical message flows. […] some of the message flows are optional and may be replaced by out-of-band configuration of the XRCE Client and Agent.”
Repo: —
Tests: —
Status: n/a (informative) — Beschreibung; die Abläufe stehen einzeln in
den folgenden Items.
§8.4.2 Senden über einen vorkonfigurierten DataWriter
Spec: §8.4.2, S. 77 — “The XRCE Agent has been pre-configured to create an XRCE Application containing a DomainParticipant, Publisher and DataWriter. The DataWriter pre-configured object_id is known to the XRCE Client. […] The reception of the CREATE_CLIENT triggers the creation or reuse of the corresponding XRCE objects. […] Subsequent WRITE_DATA messages reference the ObjectId of those DataWriters”. Figure 8: CREATE_CLIENT(reuse = 1), STATUS_AGENT, WRITE_DATA, DELETE.
Repo: crates/xrce-agent/src/daemon/session.rs (make_client_applications,
ensure_predefined); crates/xrce-agent/src/daemon/config.rs
(client_applications); crates/xrce/src/object_id.rs
(ObjectId::from_reference)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_client_writes_through_a_preconfigured_data_writer_without_a_create,
crates/xrce-agent/src/daemon/session.rs::tests::a_create_client_makes_the_objects_configured_for_the_client,
crates/xrce-agent/src/daemon/session.rs::tests::a_preconfigured_object_is_made_only_for_a_client_allowed_to_create_it,
crates/xrce-agent/src/daemon/config.rs::tests::client_applications_are_read,
crates/xrce/src/object_id.rs::tests::from_reference_matches_the_examples_of_the_spec
Status: done — WRITE_DATA auf die ObjectId einer konfigurierten Ressource
(MD5 des Namens, §9.3) legt den DomainParticipant mit allem darin für den Client
an; der AccessController (§7.4) gilt dabei. Der Text nennt ein
application_object_id in CREATE_CLIENT und ein Flag reuse;
CLIENT_Representation (Annex A) und §8.3.5.1.1 haben beides nicht. Auslöser
ist der Agent-Schlüssel client_applications: (ClientKey, Application- oder
DomainParticipant-Referenz); das CREATE_CLIENT legt die Objekte an, ein zweites
CREATE_CLIENT derselben Sitzung nutzt sie weiter (468aa0940da, 2ba972cd270).
§8.4.3 Empfangen über einen vorkonfigurierten DataReader
Spec: §8.4.3, S. 77–78 — “The XRCE Agent has been pre-configured to create an XRCE Application containing a DomainParticipant, Subscriber and DataReader. The DataReader pre-configured object_id is known to the XRCE Client. […] A subsequent READ messag e references the ObjectId of those DataReaders”. Figure 9: CREATE_CLIENT(reuse=1), STATUS_AGENT, READ_DATA, DATA, DELETE.
Repo: crates/xrce-agent/src/daemon/session.rs (handle_read_data,
ensure_predefined, make_client_applications)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_client_reads_through_a_preconfigured_data_reader_without_a_create,
crates/xrce-agent/src/daemon/session.rs::tests::a_create_client_makes_the_objects_configured_for_the_client
Status: done — READ_DATA auf die ObjectId des konfigurierten DataReader
legt ihn an, DATA kommt mit der request_id des READ_DATA. Dieselbe Abweichung
vom Text (application_object_id, reuse) und derselbe Agent-Schlüssel
client_applications: wie bei §8.4.2 (2ba972cd270).
§8.4.4 Discovery eines Agent über GET_INFO
Spec: §8.4.4, S. 78–79 — “This flow is only required when the Client is not pre-configured with the TransportLocator of the XRCE Agent. It allows an XRCE Client to be configured to content one or more TransportLocators (which may include multicast addresses) in order to dynamically discover the presence and actual Address of the Agents.” Figure 10: GET_INFO(OBJECTID_AGENT, CLIENT_Representation), INFO(AGENT_Representation): STATUS_OK, INFO(): STATUS_ERR_INCOMPATIBLE, dann CREATE_CLIENT und STATUS_AGENT.
Repo: crates/xrce-agent/src/daemon/discovery.rs
(run_discovery_responder, build_info_reply, bind_discovery_socket);
crates/xrce-agent/src/daemon/session.rs (client_info_status,
handle_get_info); crates/xrce/src/discovery.rs (MulticastDiscovery)
Tests: crates/xrce-agent/src/daemon/discovery.rs::tests::discovery_responder_answers_get_info_on_agent,
crates/xrce-agent/src/daemon/discovery.rs::tests::the_info_mask_selects_activity_and_configuration,
crates/xrce-agent/src/daemon/discovery.rs::tests::a_client_of_another_major_version_is_answered_incompatible,
crates/xrce-agent/src/daemon/discovery.rs::tests::the_discovery_group_is_the_one_given,
crates/xrce/src/discovery.rs::tests::loopback_send_recv_roundtrip
Status: done — der Agent beantwortet GET_INFO(OBJECTID_AGENT) auf dem Port
der Discovery mit INFO (AGENT_Representation und AGENT_ActivityInfo nach der
InfoMask), mit und ohne Sitzung; die Multicast-Adresse ist einstellbar
(discovery.address:). Annex A hat in GET_INFO_Payload kein Feld für die
CLIENT_Representation der Figure 10; Annex A ist die Vorgabe, die Figure 10
ist eine Erweiterung hinter der InfoMask (GetInfoPayload::with_client_info,
Client: AgentDiscovery::with_client_info), die ein Agent ohne sie überliest
(fd2e9a5bcfd, ca0cf7e08bf).
§8.4.4 Discovery auf Seite des Client
Spec: §8.4.4, S. 78–79 — wie oben.
Repo: crates/xrce-client/src/discovery.rs (AgentDiscovery,
discover_over_udp, connect_over_tcp); crates/xrce-client/src/lib.rs
(XrceClient::request_agent_info)
Tests: crates/xrce-client/src/discovery.rs::tests::get_info_goes_to_the_candidates_every_period,
crates/xrce-client/src/discovery.rs::tests::a_suitable_answer_ends_the_search,
crates/xrce-client/src/discovery.rs::tests::answers_that_are_not_suitable_are_passed_over,
crates/xrce-client/src/discovery.rs::tests::the_search_over_udp_finds_the_agent_that_answers,
crates/xrce-client/src/discovery.rs::tests::the_search_over_tcp_connects_to_the_agent_that_accepts,
crates/xrce-client/src/lib.rs::tests::request_agent_info_works_before_the_session_and_sends_the_mask,
crates/xrce-client/src/lib.rs::tests::an_info_is_read_into_an_event
Status: done — der Client sendet GET_INFO an eine Liste von Adressen im festen Takt, wertet das INFO aus und verbindet sich mit dem ersten Agent, der passt (UDP, TCP). Die Tests erreichen die Agents über Unicast auf Loopback; der Empfang auf einer Multicast-Gruppe ist nicht getestet (fd2e9a5bcfd).
§8.4.4 INFO mit STATUS_ERR_INCOMPATIBLE
Spec: §8.4.4, Figure 10, S. 79 — “INFO(): STATUS_ERR_INCOMPATIBLE”.
Repo: crates/xrce-agent/src/daemon/session.rs (client_info_status,
handle_get_info); crates/xrce-agent/src/daemon/discovery.rs
(build_info_reply)
Tests: crates/xrce-agent/src/daemon/discovery.rs::tests::a_client_of_another_major_version_is_answered_incompatible,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_the_agent_checks_the_version_in_client_info,
crates/xrce-client/src/discovery.rs::tests::client_info_names_the_version_and_hides_the_client_key
Status: done — enthält das GET_INFO eine CLIENT_Representation mit anderer
Hauptversion als die des Agent, ist die Antwort ein INFO mit
STATUS_ERR_INCOMPATIBLE; eine unlesbare Angabe ergibt
STATUS_ERR_INVALID_DATA. Die client_info ist die Erweiterung hinter der
InfoMask des Items oben (fd2e9a5bcfd).
§8.4.4 Auswahl unter mehreren Agents
Spec: §8.4.4, S. 78 — “the XRCE Client may discover more than one XRCE Agent. In that case it may use the information received about the XRCE Agent configuration […] and the XRCE Agent activity […] to select the most appropriate XRCE Agent and even connect to more than one XRCE Agents.”
Repo: —
Tests: —
Status: n/a (informative) — Erlaubnis für den Client.
§8.4.5 Verbindung mit CREATE_CLIENT und STATUS_AGENT
Spec: §8.4.5, S. 79–80 — “An XRCE Client connects to an Agent using the CREATE_CLIENT message. The Agent responds with a STATUS_AGENT indicating whether the connection succeeded and the ClientProxy was created on behalf of the XRCE Client.”
Repo: crates/xrce-client/src/lib.rs (XrceClient::connect);
crates/xrce-agent/src/daemon/session.rs (handle_create_client,
agent_status_reply)
Tests: crates/xrce-client/src/lib.rs::tests::full_lifecycle_creates_unique_request_ids_and_real_submessages,
crates/xrce-agent/src/daemon/session.rs::tests::create_client_happy_path_registers_and_replies_ok
Status: done
§8.4.6 Anlegen einer vollständigen Application
Spec: §8.4.6, S. 80 — “An XRCE Client uses the CREATE message to create an XRCE Application. The CREATE message carries a CREATE_Payload containing an ObjectVariant with ObjectKind set to OBJK_APPLICATION. The corresponding OBJK_APPLICATION_Representation may use the REPRESENTATION_BY_REFERENCE to refer to an Application pre-configured in the Agent or it may use the REPRESENTATION_AS_XML_STRING to fully describe the Application including any necessary Types, Qos, and DDS Entities.”
Repo: crates/xrce-agent/src/daemon/session.rs (plan_dds_create, Zweig
ObjectKind::Application); crates/xrce-agent/src/daemon/entity_repr.rs
(application_definition); crates/xrce-agent/src/daemon/definitions.rs
(SystemDefinitions::add_application_library)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::what_a_configuration_client_defines_is_referenced_by_another_client,
crates/xrce-agent/src/daemon/session.rs::tests::a_create_client_makes_the_objects_configured_for_the_client,
crates/xrce-agent/src/daemon/definitions.rs::tests::the_example_file_defines_the_objects_of_table_16
Status: done — CREATE(OBJK_APPLICATION) mit einer <application_library>
legt die DomainParticipants der Application mit Topics, Publishern, Subscribern
und Endpunkten an; BY_REFERENCE nennt eine Application der Definitionen des
Agent (9d5c64dc398, 2ba972cd270).
§8.4.7 Festlegen eines QosProfile
Spec: §8.4.7, S. 80 — “An XRCE Client uses the CREATE message to define Qos Profile. The CREATE message carries a CREATE_Payload containing an ObjectVariant with ObjectKind set to OBJK_QOSPROFILE. The corresponding OBJK_QOSPROFILE_Representation may use the REPRESENTATION_AS_XML_STRING to fully describe the Qos Profile.” Mit diesem Profil werden später andere Objekte angelegt.
Repo: crates/xrce-agent/src/daemon/session.rs (plan_dds_create, Zweig
ObjectKind::QosProfile, definition_to_register, rebuild_profiles);
crates/xrce-agent/src/daemon/entity_repr.rs (apply_qos_profile)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::type_and_qos_profile_xml_follow_their_clauses,
crates/xrce-agent/src/daemon/session.rs::tests::what_a_configuration_client_defines_is_referenced_by_another_client,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_qos_profile_reference_applies_the_profile
Status: done — das Profil gehört zu den Definitionen des Agent, solange das
Objekt besteht; ein späteres CREATE nennt es als Bibliothek::Profil
(qos_profile_ref, base_name). In Figure 13 sind Client und Agent vertauscht
(9d5c64dc398).
§8.4.8 Festlegen von Typen
Spec: §8.4.8, S. 81 — “An XRCE Client uses the CREATE message to create an XRCE Type. The CREATE message carries a CREATE_Payload containing an ObjectVariant with ObjectKind set to OBJK_TYPE. The corresponding OBJK_TYPE_Representation may use the REPRESENTATION_AS_XML_STRING to fully describe the DDS-XTYPES Type including any referenced types.”
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (types)
Tests: crates/xrce-agent/tests/spec_items_session.rs::a_type_by_reference_names_a_known_type_by_its_fully_qualified_name
Status: done — ein Typ als <types> wird übersetzt und ist unter seinem Namen bekannt; er darf auf Typen verweisen, die der Agent schon kennt (Item zu §7.7.3.3.2 „Verweis auf bekannte Typen“).
### §8.4.9 Anlegen eines Topic
Spec: §8.4.9, S. 81 — “An XRCE Client uses the CREATE message to create an XRCE Topic. The CREATE message carries a CREATE_Payload containing an ObjectVariant with ObjectKind set to OBJK_TOPIC. The corresponding OBJK_TOPIC_Representation may use the REPRESENTATION_IN_BINARY or the REPRESENTATION_AS_XML_STRING to fully define the Topic.”
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (topic,
topic_from_xml); crates/xrce-agent/src/daemon/session.rs (plan_dds_create)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_topic_gets_the_type_its_type_name_names,
crates/xrce-agent/tests/replay_foreign_session.rs::replay_creates_the_dds_entities_the_real_clients_describe,
crates/xrce-agent/src/daemon/session.rs::tests::a_topic_of_an_unknown_type_is_refused_when_the_agent_is_told_to
Status: done — die XML-Form im ersten Test, die binäre Form aus dem
eProsima-Mitschnitt im zweiten. Ein Topic eines Typs, den der Agent nicht kennt,
ergibt STATUS_ERR_UNKNOWN_REFERENCE (Agent-Schlüssel unknown_topic_types: refuse, Vorgabe; forward legt es an), dritter Test (969c784c93b).
§8.4.10 Anlegen eines DataWriter und Schreiben
Spec: §8.4.10, S. 82 — “An XRCE Client uses the CREATE message to create an XRCE DataWriter. […] The corresponding DATAREADER_Representation may use the REPRESENTATION_IN_BINARY or the REPRESENTATION_AS_XML_STRING to fully define the DataWriter. Both these representations allow specification of the DataWriter Qos. The DATAREADER_Representation may also use the REPRESENTATION_BY_REFERENCE to refer to a DataWriter definition known to the Agent.” Figure 16: CREATE, STATUS, WRITE_DATA, DELETE_RESOURCE(DataWriter, Session).
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (endpoint,
endpoint_from_xml); crates/xrce-agent/src/daemon/session.rs
(plan_dds_create, format_is_allowed, handle_write_data, handle_delete)
Tests: crates/xrce-agent/tests/e2e_udp_loopback.rs::e2e_udp_loopback_keyed_dispose_reliable_besteffort_and_fragments,
crates/xrce-agent/tests/replay_foreign_session.rs::replay_creates_the_dds_entities_the_real_clients_describe,
crates/xrce-agent/src/daemon/session.rs::tests::references_resolve_against_the_profile_files,
crates/xrce-agent/src/daemon/session.rs::tests::the_formats_of_each_kind_are_enforced
Status: done — XML im ersten Test, die binäre Form im zweiten. Annex A und
§7.7.3.1 geben dem DataWriter nur Binär und XML; §8.4.10 nennt auch
REPRESENTATION_BY_REFERENCE. Annex A ist die Vorgabe (die Referenz ergibt
STATUS_ERR_INVALID_DATA, vierter Test); der Agent-Schlüssel
representation_formats: any lässt die Referenz zu (dritter Test) (0429eab4fb2,
23d8f50c712). Der Text schreibt DATAREADER_Representation für den DataWriter;
Figure 16 nennt DELETE_RESOURCE, eine solche Submessage gibt es nicht (gemeint
ist DELETE).
§8.4.11 Anlegen eines DataReader und Lesen
Spec: §8.4.11, S. 82–83 — “An XRCE Client uses the CREATE message to create an XRCE DataReader. […] The corresponding OBJK_DATAREADER_Representation may use the REPRESENTATION_IN_BINARY or the REPRESENTATION_AS_XML_STRING to fully define the DataReader. […] may also use the REPRESENTATION_BY_REFERENCE”. Figure 17: CREATE, STATUS, READ, DATA.
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (endpoint,
endpoint_from_xml); crates/xrce-agent/src/daemon/session.rs
(plan_dds_create, format_is_allowed, handle_read_data, pump_read)
Tests: crates/xrce-agent/tests/e2e_udp_loopback.rs::e2e_udp_loopback_keyed_dispose_reliable_besteffort_and_fragments,
crates/xrce-agent/tests/replay_foreign_session.rs::replay_creates_the_dds_entities_the_real_clients_describe,
crates/xrce-agent/src/daemon/session.rs::tests::references_resolve_against_the_profile_files,
crates/xrce-agent/src/daemon/session.rs::tests::the_formats_of_each_kind_are_enforced
Status: done — Binär und XML wie beim DataWriter; die Referenz auf einen
DataReader ist nach Annex A und §7.7.3.1 nicht vorgesehen und nur mit dem
Agent-Schlüssel representation_formats: any zulässig (dritter und vierter
Test) (0429eab4fb2). Die Einleitung sagt „to publish data“ für den DataReader.
§8.4.12 Information über eine Ressource
Spec: §8.4.12, S. 83 — “An XRCE Client may use this mechanism to determine the QoS of any of the DDS proxy entities that the XRCE Agent manages on behalf of the XRCE Client. It may also be used to read QoS profiles and type declarations that are known to the XRCE Agent. […] The XRCE Agent responds with an INFO message containing an ObjectVariant. The ObjectKind of the ObjectVariant is the appropriate for the specified ObjectId.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_get_info,
object_info, ensure_predefined)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_an_object_returns_the_object_variant_it_was_created_with,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_a_missing_object_is_an_info_with_unknown_reference,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_a_data_writer_reports_its_activity,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_a_data_reader_reports_its_activity
Status: done — GET_INFO auf ein Objekt des Client ergibt ein INFO mit der
ObjectVariant, mit der es angelegt wurde (mit ObjectKind), und der Aktivität
eines DataWriter oder DataReader nach der InfoMask (ca0cf7e08bf). GET_INFO auf
die ObjectId eines QoS-Profils oder Typs aus den Definitionen des Agent legt
das Objekt für den Client an (ensure_predefined, 2ba972cd270); dieser Zweig
hat keinen eigenen Test.
§8.4.13 Ändern einer Ressource
Spec: §8.4.13, S. 84 — “An XRCE Client uses the CREATE message with the attribute reuse set to TRUE and the attribute replace set to TRUE to indicate it wants to update the Object identified by the ObjectId. […] The XRCE Agent updates the Object using the new configuration contained in the ObjectVarian t and responds with a STATUS message.”
Repo: crates/xrce/src/object_store.rs (ObjectStore::create,
CreateOutcome::Replaced); crates/xrce-agent/src/daemon/session.rs
(handle_create); crates/xrce-client/src/lib.rs (XrceClient::update_object)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_create_with_reuse_and_replace_updates_the_object,
crates/xrce-agent/src/daemon/session.rs::tests::the_update_of_a_missing_object_creates_it_or_is_refused,
crates/xrce-agent/src/daemon/session.rs::tests::a_replace_that_fails_returns_the_object_to_its_previous_configuration,
crates/xrce/src/object_store.rs::tests::create_reuse_and_replace_replaces_an_unequal_object,
crates/xrce-client/src/lib.rs::tests::update_object_sends_a_create_with_reuse_and_replace
Status: done — CREATE mit reuse und replace ersetzt ein ungleiches
Objekt (Table 5); schlägt die DDS-Seite fehl, gilt wieder die alte
Konfiguration. Das Update eines fehlenden Objekts widerspricht sich in der Spec:
§7.8.3.2 verlangt STATUS_ERR_UNKNOWN_REFERENCE, Table 5 und §8.4.13 legen es
an. Vorgabe ist Table 5; der Agent-Schlüssel update_of_missing_object: refuse
gibt STATUS_ERR_UNKNOWN_REFERENCE (3b066516f69, 70963ac46ec).
§8.4.14 Zuverlässigkeit je Stream, nur auf zuverlässigen Streams
Spec: §8.4.14, S. 84 — “Reliability is implemented separately for each Stream, and only for the reliable streams which are identified by the stream_id value being between 0x80 and 0xFF.”
Repo: crates/xrce/src/reliable.rs (ReliableStreamState::new);
crates/xrce-agent/src/daemon/session.rs (reliable je (client, stream),
handle_message)
Tests: crates/xrce/src/reliable.rs::tests::constructor_panics_on_best_effort_stream,
crates/xrce-agent/src/daemon/session.rs::tests::best_effort_messages_get_increasing_sequence_numbers
Status: done
§8.4.14 Zwei Endpunkte mit je eigener Zustandsmaschine
Spec: §8.4.14, S. 84 — “A Stream has exactly two endpoints, the sending endpoint and the receiving endpoint. […] The sender and receiver endpoint on a Stream each execute its own protocol state machine.”
Repo: crates/xrce/src/reliable.rs (ReliableStreamState: Sender
submit, pending_heartbeat, recv_acknack; Empfänger recv_data,
drain_in_order, pending_acknack)
Tests: crates/xrce/src/reliable.rs::tests::end_to_end_sender_receiver_with_loss_recovery
Status: done — beide Hälften liegen in einem Zustand je Stream; Agent und Client benutzen je Richtung eine davon.
§8.4.14 Serial Number Arithmetic
Spec: §8.4.14, S. 84 — “Sequence number arithmetic and comparisons shall use Serial Number Arithmetic as specified in clause 8.3.2.3 sequenceNr.”
Repo: crates/xrce/src/reliable.rs (serial_min_in_flight,
serial_max_in_flight); crates/xrce/src/serial_number.rs
Tests: crates/xrce/src/reliable.rs::tests::heartbeat_window_across_wrap_reports_rfc1982_order,
crates/xrce/src/reliable.rs::tests::acknack_retransmit_of_lost_sample_across_wrap
Status: done
§8.4.14.1 Zustand des Senders
Spec: §8.4.14.1, S. 85 — “The sender maintains two state variables associated with the stream. The HighestSentSequenecNumber and the HighestAcknowledgedSequenceNumber. Each time a message is sent the HighestSentSequenecNumber is increased. The reception of ACKNACK messages updates the HiguestAcknowledgedSequenceNumber.” Figure 20: “receive(ACKNACK) /save HigestAcknowledgedSeqNumber repair SequenceNumber in NACK”.
Repo: crates/xrce/src/reliable.rs (submit, recv_acknack);
crates/xrce-agent/src/daemon/session.rs (handle_acknack)
Tests: crates/xrce/src/reliable.rs::tests::submit_assigns_monotonic_seqnrs,
crates/xrce/src/reliable.rs::tests::recv_acknack_clears_acked_seqnrs,
crates/xrce-agent/src/daemon/session.rs::tests::acknack_nack_triggers_retransmission_of_the_exact_buffered_bytes
Status: done — der Sender hält die offenen Nachrichten statt zweier
Zahlen; window_base entspricht der höchsten bestätigten Nummer plus eins.
§8.4.14.1 HEARTBEAT bis zur vollständigen Bestätigung
Spec: §8.4.14.1, S. 85 — “While the HighestAcknowledgedSequenceNumber is less than the HighestSentSequenceNumber the sender sends HeartBeat messages that announce the HighestSentSequenecNumber to the receiver. These HeartBeat messages may be periodic or optimized using on vendor specific mechanism. The requirement is that they are sent at some rate until HighestAcknowledgedSequenceNumber matches the HighestSentSequenceNumber.”
Repo: crates/xrce/src/reliable.rs (pending_heartbeat,
DEFAULT_HEARTBEAT_PERIOD); crates/xrce-agent/src/daemon/session.rs
(tick); crates/xrce-client/src/lib.rs (XrceClient::tick)
Tests: crates/xrce/src/reliable.rs::tests::pending_heartbeat_fires_first_time,
crates/xrce/src/reliable.rs::tests::pending_heartbeat_silenced_until_period_elapsed,
crates/xrce/src/reliable.rs::tests::pending_heartbeat_none_when_window_empty
Status: done — alle 500 ms. Figure 20 schreibt den Übergang nach
„Initial“ mit HiguestReceivedSeqNumber, der Text mit der höchsten bestätigten
Nummer.
§8.4.14.2 Zustand des Empfängers
Spec: §8.4.14.2, S. 85–86 — “The receiver maintains two state variables associated with the stream. The HighestReceivedSequenceNumber and the HighestAnnouncedSequenceNumber. Each time a Message is received the HighestReceivedSequenceNumber may be updated (assuming all previous messages have been received). […] Each time a HEARTBEAT is received the HighestAnnouncedSequenceNumber may be adjusted.”
Repo: crates/xrce/src/reliable.rs (recv_data, drain_in_order,
pending_acknack)
Tests: crates/xrce/src/reliable.rs::tests::recv_data_buffers_in_order,
crates/xrce/src/reliable.rs::tests::pending_acknack_marks_missing_slots
Status: done — die höchste angekündigte Nummer wird nicht gespeichert; sie
geht als hint_last_seen in das ACKNACK auf den HEARTBEAT ein.
§8.4.14.2 Client sendet ACKNACK, solange Nachrichten fehlen
Spec: §8.4.14.2, S. 86 — “If the receiver is a n XRCE Client, then while the HiguestReceivedSequenceNumber is less than the HighestAnnouncedSequenceNumber, the received sends ACKNACK messages to request the messages corresponding to the missing sequence numbers. These ACKNACK messages may be periodic or optimized using on vendor specific mechanism.”
Repo: crates/xrce-client/src/lib.rs (handle_heartbeat)
Tests: crates/xrce-client/src/lib.rs::tests::heartbeat_is_answered_with_acknack
Status: done — der Client sendet ACKNACK auf jeden HEARTBEAT, nicht nach
einem eigenen Takt (Figure 21: NackPeriod); der Agent sendet HEARTBEAT alle
500 ms, solange Nachrichten offen sind.
§8.4.14.2 Agent sendet ACKNACK nur auf HEARTBEAT
Spec: §8.4.14.2, S. 86 — “If the receiver is the XRCE Agent, then it only sends ACKNACK messages in response to receiving a HEARTBEAT.”
Repo: crates/xrce-agent/src/daemon/session.rs (handle_heartbeat)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::out_of_order_reliable_messages_wait_for_the_gap_and_report_a_truthful_acknack
Status: done — wie im Item zu §8.3.5.11.
§8.5 XRCE Object Operation Traceability
§8.5 Table 14 create_client
Spec: §8.5, Table 14, S. 86 — “XRCE Root / create_client / CREATE_CLIENT / STATUS_AGENT”.
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create_client,
agent_status_reply)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::create_client_happy_path_registers_and_replies_ok,
crates/xrce-agent/src/daemon/session.rs::tests::create_client_rejects_wrong_major_version,
crates/xrce-agent/src/daemon/session.rs::tests::a_wrong_cookie_is_answered_with_a_status_agent
Status: done — ein falsches Cookie wird mit STATUS_AGENT und
STATUS_ERR_INVALID_DATA beantwortet (d7aec9c2d78). Die Überschrift der Table
14 lautet „Predefined XRCE Objects from parsing the Example XML configuration
XML file“, wie die von Table 16.
§8.5 Table 14 get_info der Root
Spec: §8.5, Table 14, S. 86 — “XRCE Root / get_info / GET_INFO / INFO”.
Repo: crates/xrce-agent/src/daemon/discovery.rs
(run_discovery_responder); crates/xrce-agent/src/daemon/session.rs
(handle_get_info)
Tests: crates/xrce-agent/src/daemon/discovery.rs::tests::discovery_responder_answers_get_info_on_agent,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_the_agent_in_a_session_returns_activity_and_representation,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_without_a_session_is_answered_for_the_agent_only,
crates/xrce-agent/src/daemon/transport.rs::tests::the_udp_listener_answers_get_info_before_a_session
Status: done
§8.5 Table 14 delete_client mit STATUS_AGENT
Spec: §8.5, Table 14, S. 86 — “XRCE Root / delete_client / DELETE / STATUS_AGENT”.
Repo: crates/xrce-agent/src/daemon/session.rs (delete_client_reply); crates/xrce-agent/src/daemon/config.rs (delete_client_reply)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::delete_client_is_answered_with_status_unless_status_agent_is_named, crates/xrce-agent/src/daemon/config.rs::tests::the_reply_to_delete_client_can_be_set
Status: done — DELETE(OBJECTID_CLIENT) wird mit STATUS beantwortet (§8.3.5.4; in der IDL von Annex A trägt nur STATUS ein ResultStatus); das STATUS_AGENT von Table 14 ist die Einstellung delete_client_reply: status_agent. Der Client nimmt ein STATUS_AGENT, das ohne ausstehendes CREATE_CLIENT eintrifft, für die Antwort auf sein DELETE. 9aeb3465b72.
### §8.5 Table 14 create
Spec: §8.5, Table 14, S. 86 — “XRCE ProxyClient / create / CREATE (flags for creation) / STATUS”.
Repo: crates/xrce-agent/src/daemon/session.rs (handle_create)
Tests: crates/xrce-agent/tests/replay_foreign_session.rs::replay_matches_the_real_agents_create_client_create_and_delete_replies
Status: done
§8.5 Table 14 update
Spec: §8.5, Table 14, S. 86 — “XRCE ProxyClient / update / CREATE (flags for reuse) / STATUS”.
Repo: crates/xrce/src/object_store.rs (ObjectStore::create);
crates/xrce-agent/src/daemon/session.rs (handle_create);
crates/xrce-client/src/lib.rs (XrceClient::update_object)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_create_with_reuse_and_replace_updates_the_object,
crates/xrce-client/src/lib.rs::tests::update_object_sends_a_create_with_reuse_and_replace,
crates/xrce/src/object_store.rs::tests::create_reuse_and_replace_replaces_an_unequal_object
Status: done — wie im Item zu §8.4.13, einschließlich der Einstellung
update_of_missing_object. Die Table nennt nur „flags for reuse“, §8.4.13 setzt
reuse und replace; der Update ist CREATE mit beiden (3b066516f69).
§8.5 Table 14 get_info des ProxyClient
Spec: §8.5, Table 14, S. 86 — “XRCE ProxyClient / get_info / GET_INFO / INFO”.
Repo: crates/xrce-agent/src/daemon/session.rs (handle_get_info,
object_info)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_an_object_returns_the_object_variant_it_was_created_with,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_a_missing_object_is_an_info_with_unknown_reference,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_a_data_writer_reports_its_activity
Status: done — GET_INFO auf ein Objekt ergibt INFO, auf eine unbekannte
ObjectId ein INFO mit STATUS_ERR_UNKNOWN_REFERENCE, ohne Recht
STATUS_ERR_DENIED (ca0cf7e08bf, d7338ca58f2).
§8.5 Table 14 delete
Spec: §8.5, Table 14, S. 86 — “XRCE ProxyClient / delete / DELETE / STATUS”.
Repo: crates/xrce-agent/src/daemon/session.rs (handle_delete)
Tests: crates/xrce-agent/tests/endpoint_client_fixtures.rs::delete_fixture_decodes_and_removes_the_object_create_added,
crates/xrce-agent/tests/replay_foreign_session.rs::replay_matches_the_real_agents_create_client_create_and_delete_replies
Status: done
§8.5 Table 14 write
Spec: §8.5, Table 14, S. 86 — “XRCE DataWriter / write / WRITE_DATA, FRAGMENT / STATUS”.
Repo: crates/xrce-agent/src/daemon/session.rs (handle_write_data,
process_message_submessages)
Tests: crates/xrce-agent/tests/e2e_udp_loopback.rs::e2e_udp_loopback_keyed_dispose_reliable_besteffort_and_fragments,
crates/xrce-agent/src/daemon/session.rs::tests::a_successful_write_is_answered_with_status_ok
Status: done — WRITE_DATA direkt und in FRAGMENT; ein erfolgreiches
WRITE_DATA ergibt STATUS mit STATUS_OK, ein Fehler den Fehlercode
(869304e6b63). Der eProsima-Agent antwortet auf ein erfolgreiches WRITE_DATA
nicht; der Agent folgt dem Text der Spec.
§8.5 Table 14 read
Spec: §8.5, Table 14, S. 86 — “XRCE DataReader / read / READ_DATA / DATA, FRAGMENT, STATUS”.
Repo: crates/xrce-agent/src/daemon/session.rs (handle_read_data,
pump_read, emit_possibly_fragmented)
Tests: crates/xrce-agent/tests/e2e_udp_loopback.rs::e2e_udp_loopback_keyed_dispose_reliable_besteffort_and_fragments,
crates/xrce-agent/src/daemon/session.rs::tests::a_sample_above_the_clients_mtu_on_a_reliable_stream_splits_into_fragments,
crates/xrce-agent/src/daemon/session.rs::tests::read_data_with_an_unhonorable_content_filter_is_rejected_not_silently_unfiltered
Status: done
§9 XRCE Agent Configuration
§9.1 Vorwissen des Agent für REPRESENTATION_BY_REFERENCE
Spec: §9.1, S. 87 — “The XRCE Agent may be configured such that it has a priori knowledge XRCE Objects. This allows XRCE Clients to reference and create XRCE Objects in a very compact manner using the representation format REPRESENTATION_BY_REFERENCE, see clause 7.7.3.3.1 REPRESENTATION_BY_REFERENCE format.”
Repo: —
Tests: —
Status: n/a (informative) — Erlaubnis. Der Abschnitt mit dem Titel
„REPRESENTATION_BY_REFERENCE format“ ist §7.7.3.1.1; §7.7.3.3.1 gehört zu
XRCE Type.
§9.1 Zwei Standardmechanismen, weitere erlaubt
Spec: §9.1, S. 87 — “This specification provides two standard mechanism s to configure the XRCE Agent. Implementations may also provide additional mechanisms: Remote configuration using the XRCE Protocol; Local file-based configuration”.
Repo: —
Tests: —
Status: n/a (informative) — Überblick; die beiden Mechanismen stehen in
den Items zu §9.2 und §9.3. Die Profildateien im Format von Fast DDS
(xml_profile_files:) sind ein zusätzlicher Mechanismus.
§9.2 ConfigurationClient mit dem gewöhnlichen Protokoll
Spec: §9.2, S. 87 — “An application may use a n XRCE Client with the only purpose of defining and creating XRCE Objects that are intended for other applications. […] The protocol used by the XRCE ConfigurationClient is the same used by any other XRCE Client. The only difference is that an XRCE ConfigurationClient never uses the READ_DATA or WRITE messages.”
Repo: —
Tests: —
Status: n/a (informative) — Beschreibung einer Rolle des Client; sie
braucht keine eigene Nachricht.
§9.2 Objekte des ConfigurationClient für andere Clients
Spec: §9.2, S. 87–88 — “Any other XRCE Client can reference XRCE Objects created by an XRCE ConfigurationClient.” Figure 22: der ConfigurationClient legt mit CREATE an, ein anderer Client mit CREATE(REPRESENTATION_BY_REFERENCE) und liest mit READ_DATA. “These XRCE Objects are later referenced by a different XRCE Client using the representation formats REPRESENTATION_BY_REFERENCE.”
Repo: crates/xrce-agent/src/daemon/definitions.rs (SystemDefinitions);
crates/xrce-agent/src/daemon/session.rs (definition_to_register,
rebuild_profiles, ensure_predefined);
crates/xrce-agent/src/daemon/profiles.rs (AgentProfiles::predefined_objects)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::what_a_configuration_client_defines_is_referenced_by_another_client,
crates/xrce-agent/src/daemon/session.rs::tests::a_client_writes_through_a_preconfigured_data_writer_without_a_create
Status: done — ein ConfigurationClient legt QosProfile, Application und
DomainParticipant mit CREATE (XML) an; ein anderer Client erzeugt sie mit
REPRESENTATION_BY_REFERENCE, solange das Objekt des ConfigurationClient
besteht (der Test deckt QosProfile und Application). Type und DomainParticipant
laufen über denselben Weg (definition_to_register), ohne eigenen Test. Ein
Domain hat keine ObjectKind (§7.7.5, Annex A) und kommt aus den Dateien.
Figure 22 nennt die Antwort auf CREATE_CLIENT STATUS_CLIENT; die Submessage
heißt STATUS_AGENT (9d5c64dc398, 2ba972cd270).
§9.2 Anderes Netz oder anderer Transport
Spec: §9.2, S. 87 — “Note that the XRCE ConfigurationClient may be communicating with the Agent using a different network or transport, which may not have the same constraints as a typical XRCE Client.”
Repo: —
Tests: —
Status: n/a (informative) — Hinweis.
§9.3 Laden einer XML-Datei nach dds-xml_system_example.xsd
Spec: §9.3, S. 88 — “The XRCE Agent shall provide a configuration or run-time option to load a n XML file formatted according to the schema defined in the [DDS-XML] machine-readable file dds-xml_system_example.xsd.”
Repo: crates/xrce-agent/src/daemon/config.rs (xml_profile_files,
qos_library_files); crates/xrce-agent/src/daemon/profiles.rs
(AgentProfiles::load, AgentProfiles::add_profiles);
crates/xrce-agent/src/daemon/definitions.rs
(SystemDefinitions::add_document)
Tests: crates/xrce-agent/src/daemon/profiles.rs::tests::types_and_qos_libraries_in_a_dds_document_are_read,
crates/xrce-agent/src/daemon/profiles.rs::tests::the_example_file_of_the_spec_defines_the_objects_of_table_16
Status: done — xml_profile_files: nimmt ein Dokument mit der Wurzel
<dds> (oder eine Bibliothek als Wurzel) und liest <types>, <qos_library>,
<domain_library>, <domain_participant_library> und <application_library>
(452ffeb7f84, 9d5c64dc398). Die Schemadatei liegt nicht im Cache; geprüft ist
gegen §9.3.1.
§9.3 Domain-, Application- und DomainParticipant-Libraries der Konfigurationsdatei
Spec: §9.3, S. 88 — wie oben.
Repo: crates/xrce-agent/src/daemon/profiles.rs
(AgentProfiles::add_profiles); crates/xrce-agent/src/daemon/definitions.rs
(add_domain_library, add_participant_library, add_application_library)
Tests: crates/xrce-agent/src/daemon/definitions.rs::tests::a_participant_library_and_inheritance,
crates/xrce-agent/src/daemon/definitions.rs::tests::the_example_file_defines_the_objects_of_table_16,
crates/xrce-agent/src/daemon/profiles.rs::tests::a_library_can_be_the_root_and_a_clash_of_ids_is_refused
Status: done — die drei Libraries werden gelesen, auch als Wurzel des
Dokuments, mit base_name-Vererbung. Andere Elemente von <dds> stehen nur im
Startprotokoll (AgentProfiles::unused) (452ffeb7f84, 9d5c64dc398).
§9.3 Ein XRCE-Objekt je Element, für alle Clients per Referenz
Spec: §9.3, S. 88 — “The XRCE Agent shall parse the XML file and for each of the elements defined in Table 15, it shall construct the corresponding XRCE Object specified in Table 15. All the created XRCE Objects shall be made available to XRCE clients such that they may refer to them using the representation format REPRESENTATION_BY_REFERENCE.”
Repo: crates/xrce-agent/src/daemon/profiles.rs
(AgentProfiles::predefined_objects); crates/xrce-agent/src/daemon/session.rs
(ensure_predefined, predefined_index); crates/xrce/src/object_id.rs
(ObjectId::from_reference)
Tests: crates/xrce-agent/src/daemon/profiles.rs::tests::the_example_file_of_the_spec_defines_the_objects_of_table_16,
crates/xrce-agent/src/daemon/profiles.rs::tests::a_library_can_be_the_root_and_a_clash_of_ids_is_refused,
crates/xrce-agent/src/daemon/session.rs::tests::a_client_writes_through_a_preconfigured_data_writer_without_a_create,
crates/xrce/src/object_id.rs::tests::from_reference_matches_the_examples_of_the_spec
Status: done — der Agent kennt jedes Element von Table 15 als Objekt mit der
ObjectId aus dem MD5 der Referenz (§9.3, Table 16); jeder Client erhält es mit
CREATE und REPRESENTATION_BY_REFERENCE oder beim ersten Zugriff auf die
ObjectId. Zwei Objekte oberster Ebene mit derselben ObjectId weist das Laden
der Datei ab (468aa0940da, 2ba972cd270).
§9.3 Table 15
Spec: §9.3, Table 15, S. 88 — “
Repo: crates/xrce-agent/src/daemon/profiles.rs (add_types,
AgentProfiles::resolve_type_ref);
crates/xrce-agent/src/daemon/entity_repr.rs (types);
crates/xrce-agent/src/daemon/session.rs (plan_dds_create, Zweig
ObjectKind::Type)
Tests: crates/xrce-agent/src/daemon/profiles.rs::tests::types_and_qos_libraries_in_a_dds_document_are_read,
crates/xrce-agent/src/daemon/profiles.rs::tests::the_example_file_of_the_spec_defines_the_objects_of_table_16,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::an_xml_type_library_compiles_to_named_complete_types,
crates/xrce-agent/src/daemon/session.rs::tests::a_configured_type_is_known_to_every_client
Status: done — die Typen sind für alle Clients unter ihrem vollständigen
Namen mit Modulen bekannt (ShapesDemoTypes::ShapeType); ein Topic findet sie
über type_name. CREATE mit OBJK_TYPE und REPRESENTATION_BY_REFERENCE nimmt
einen bekannten Namen an (plan_dds_create, ohne eigenen Test). Verweise eines
<types> auf andere bekannte Typen: Item zu §7.7.3.3.2 (452ffeb7f84,
9d5c64dc398).
§9.3 Table 15
Spec: §9.3, Table 15, S. 88 — “
Repo: crates/xrce-agent/src/daemon/profiles.rs
(AgentProfiles::qos_profile, AgentProfiles::predefined_objects);
crates/xrce-agent/src/daemon/entity_repr.rs (apply_qos_profile);
crates/xrce-agent/src/daemon/session.rs (plan_dds_create, Zweig
ObjectKind::QosProfile)
Tests: crates/xrce-agent/src/daemon/profiles.rs::tests::types_and_qos_libraries_in_a_dds_document_are_read,
crates/xrce-agent/src/daemon/profiles.rs::tests::the_example_file_of_the_spec_defines_the_objects_of_table_16,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_qos_profile_reference_applies_the_profile,
crates/xrce-agent/src/daemon/session.rs::tests::what_a_configuration_client_defines_is_referenced_by_another_client
Status: done — ein Endpunkt nennt das Profil mit Bibliothek::Profil;
CREATE mit OBJK_QOSPROFILE legt ein Profil an, das spätere CREATE benutzen
(9d5c64dc398). Die Zeile schreibt „XRCE Types“ für das QosProfile.
§9.3 Table 15
Spec: §9.3, Table 15, S. 89 — “
Repo: crates/xrce-agent/src/daemon/definitions.rs (DomainDef,
SystemDefinitions::add_domain_library, SystemDefinitions::domain);
crates/xrce-agent/src/daemon/entity_repr.rs (participant: domain_ref,
domain_reference)
Tests: crates/xrce-agent/src/daemon/definitions.rs::tests::a_participant_library_and_inheritance,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_domain_reference_is_resolved_against_the_domain_libraries,
crates/xrce-agent/src/daemon/profiles.rs::tests::the_example_file_of_the_spec_defines_the_objects_of_table_16
Status: done — <domain_library> wird gelesen; ein Domain ist unter
Bibliothek::Domain benannt und wird von domain_ref (XML) und
domain_reference (binär) eines DomainParticipant aufgelöst. Der Domain hat
keine ObjectKind (§7.7.5, Annex A): ein CREATE kann ihn nicht nennen, er hat
keine ObjectId (452ffeb7f84, 0b67c04800c).
§9.3 Table 15 in
Spec: §9.3, Table 15, S. 89 — “
Repo: crates/xrce-agent/src/daemon/definitions.rs (DomainDef::topics,
SystemDefinitions::scope_of, ParticipantScope::topic)
Tests: crates/xrce-agent/src/daemon/definitions.rs::tests::a_participant_library_and_inheritance
Status: done — die Topics eines Domain stehen im Geltungsbereich jedes
DomainParticipant, der den Domain nennt (§7.7.3.7.1); ein DataWriter oder
DataReader findet sie unter ihrem Namen, auch über base_name eines Domain
(9d5c64dc398).
§9.3 Table 15
Spec: §9.3, Table 15, S. 89 — “
Repo: crates/xrce-agent/src/daemon/definitions.rs
(SystemDefinitions::add_application_library, application);
crates/xrce-agent/src/daemon/profiles.rs
(AgentProfiles::predefined_objects); crates/xrce/src/object_id.rs
(ObjectId::from_reference)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::what_a_configuration_client_defines_is_referenced_by_another_client,
crates/xrce-agent/src/daemon/session.rs::tests::a_create_client_makes_the_objects_configured_for_the_client,
crates/xrce-agent/src/daemon/definitions.rs::tests::the_example_file_defines_the_objects_of_table_16
Status: done — Commits 452ffeb7f84, 2ba972cd270. <application_library> wird
gelesen, auch als Wurzel einer Datei. Die Application ist unter
„Bibliothek::Application“ bekannt (Beispiel „Apps::App“), ihre ObjectId stammt
aus dem MD5 dieser Zeichenkette. Ein anderer Client erzeugt sie mit
REPRESENTATION_BY_REFERENCE, solange das Objekt besteht, das sie definiert hat.
§9.3 Table 15
Spec: §9.3, Table 15, S. 89 — “
Repo: crates/xrce-agent/src/daemon/definitions.rs
(SystemDefinitions::add_participant_library, participant,
plan_participant); crates/xrce-agent/src/daemon/session.rs (create_nested,
ensure_predefined)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_participant_definition_creates_the_objects_inside_it,
crates/xrce-agent/src/daemon/definitions.rs::tests::a_participant_library_and_inheritance,
crates/xrce-agent/src/daemon/profiles.rs::tests::a_library_can_be_the_root_and_a_clash_of_ids_is_refused,
crates/xrce-agent/src/daemon/definitions.rs::tests::the_example_file_defines_the_objects_of_table_16
Status: done — Commits 452ffeb7f84, 9d5c64dc398, 2ba972cd270.
<domain_participant_library> wird gelesen, auch als Wurzel einer Datei. Der
Participant ist unter „Bibliothek::Participant“ bekannt, in einer Application
unter „Bibliothek::Application::Participant“ (Table 16:
„MyApplications::ShapesDemoApp::MyParticipant“); seine ObjectId stammt aus dem
MD5 der Zeichenkette. Die Form <participant profile_name="…"> einer
Profildatei im Format von Fast DDS bleibt daneben lesbar.
§9.3 Table 15 in
Spec: §9.3, Table 15, S. 89 — “
Repo: crates/xrce-agent/src/daemon/definitions.rs (plan_participant: die
Topics des Participant und seiner Domain);
crates/xrce-agent/src/daemon/session.rs (create_nested)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_topic_is_created_by_name_or_by_register_type_ref,
crates/xrce-agent/src/daemon/definitions.rs::tests::the_example_file_defines_the_objects_of_table_16,
crates/xrce-agent/src/daemon/definitions.rs::tests::a_participant_library_and_inheritance
Status: done — Commits 9d5c64dc398, b97657ef4ec. Ein Topic im Participant ist
ein Objekt mit der ObjectId seines Namens (Beispiel „Square“ {0xce, 0xb2}). Die
Objekte desselben Participant nennen es mit diesem Namen (topic_ref="Square"
eines DataWriter wird zur ObjectId des Topic); ein Name, den der Participant
nicht hält, wird abgewiesen. Die Form <topic profile_name="…"> im Format von
Fast DDS bleibt daneben lesbar.
§9.3 Table 15 und
Spec: §9.3, Table 15, S. 89 — “
Repo: crates/xrce-agent/src/daemon/definitions.rs (plan_participant);
crates/xrce-agent/src/daemon/session.rs (create_nested);
crates/xrce-agent/src/daemon/dcps_bridge.rs (container_for prüft, dass Topic
und Publisher/Subscriber zum selben Participant gehören)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_publisher_with_nested_data_writers_creates_them,
crates/xrce-agent/src/daemon/definitions.rs::tests::the_example_file_defines_the_objects_of_table_16,
crates/xrce-agent/src/daemon/definitions.rs::tests::what_cannot_be_planned_is_refused
Status: done — Commits 9d5c64dc398, b97657ef4ec. Publisher und Subscriber
sind Objekte mit der ObjectId ihres Namens (Beispiel „MyPublisher“ {0x13,
0xe3}), ohne Bibliothek davor, und gelten im Bereich ihres Participant. Zwei
Participants desselben Client, die eine Entität gleichen Namens definieren,
leiten dieselbe ObjectId ab (die Spec leitet nur aus dem Namen ab); die zweite
ist STATUS_ERR_ALREADY_EXISTS (Befund aus dem Code, nicht durch einen Test
belegt).
§9.3 Table 15 und
Spec: §9.3, Table 15, S. 89 — “
Repo: crates/xrce-agent/src/daemon/session.rs (create_embedded,
create_nested, ensure_predefined);
crates/xrce-agent/src/daemon/definitions.rs (plan_participant)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_publisher_with_nested_data_writers_creates_them,
crates/xrce-agent/src/daemon/session.rs::tests::a_client_writes_through_a_preconfigured_data_writer_without_a_create,
crates/xrce-agent/src/daemon/session.rs::tests::a_client_reads_through_a_preconfigured_data_reader_without_a_create,
crates/xrce-agent/src/daemon/definitions.rs::tests::the_example_file_defines_the_objects_of_table_16
Status: done — Commits 9d5c64dc398, b97657ef4ec, 2ba972cd270. DataWriter
und DataReader sind Objekte mit der ObjectId ihres Namens (Beispiel
„MySquareWriter“ {0x1c, 0xc5}) und hängen unter ihrem Publisher oder Subscriber
(§9.3.1; Table 15 nennt <domain_participant> als Elternelement). Ein Client
schreibt und liest über sie ohne CREATE.
§9.3 ObjectId aus dem MD5 der Referenz
Spec: §9.3, S. 89 — “The XRCE Objects created from the file-based configuration shall have their ObjectId automatically derived from the REPRESENTATION_BY_REFERENCE string. Specifically, the ObjectIdPrefix (see 7.7.6) shall be set to the first 2 bytes of the MD5 hash computed on the REPRESENTATION_BY_REFERENCE string. The MD5 treats each string character as a byte and does not include the NUL terminating character of the string.” Beispiel: “MyWriter”, MD5 0x03e26181adfef529038bf0dce7cab871, ObjectIdPrefix {0x03, 0xe2}.
Repo: crates/xrce/src/object_id.rs (ObjectId::from_reference: MD5 der
Zeichenkette ohne NUL, die ersten zwei Bytes, die unteren 4 Bit durch die
ObjectKind ersetzt)
Tests: crates/xrce/src/object_id.rs::tests::from_reference_matches_the_examples_of_the_spec
Status: done — Commits 468aa0940da. „MyWriter“ ergibt den MD5
0x03e26181adfef529038bf0dce7cab871 (Test mit dem Crate md-5; nachgerechnet
auch mit Python hashlib, gemessen), das ObjectIdPrefix {0x03, 0xe2} und mit
der Art DataWriter die ObjectId {0x03, 0xe5}. Der letzte Satz der Spec schreibt
„The ObjectIdPrefix shall be computed by combining the ObjectIdPrefix with the
ObjectKind“; gemeint ist die ObjectId. Der Kommentar in
crates/xrce/src/xml_config.rs verweist auf ObjectId::from_reference.
§9.3.1 Beispieldatei
Spec: §9.3.1, S. 90–91 — “The following XML file could be used to configure
an XRCE Agent.” <types> mit Modul ShapesDemoTypes, <qos_library name="MyQosLibrary">, <application_library name="MyApplications"> mit
<application name="ShapesDemoApp">, Participant MyParticipant, drei Topics,
MyPublisher mit MySquareWriter und MyCircleWriter, MySubscriber mit
MyTriangleRdr.
Repo: crates/xrce-agent/src/daemon/profiles.rs
(AgentProfiles::add_profiles liest die Datei)
Tests: crates/xrce-agent/src/daemon/profiles.rs::tests::the_example_file_of_the_spec_defines_the_objects_of_table_16
Status: n/a (informative) — Beispiel. Der Test lädt die Datei mit
ergänzter Domain und ergänztem Typ. domain_ref nennt
„ShapesDomainLibrary::ShapesDomain“, das die Datei nicht definiert;
register_type type_ref="ShapeType" nennt den Typ ohne sein Modul
ShapesDemoTypes.
§9.3.1 Table 16 vordefinierte Objekte
Spec: §9.3.1, Table 16, S. 92 — “An XRCE Agent loading the above configuration file would have the pre-defined XRCE Objects shown in Table 16.” Zwölf Zeilen mit Referenz, ObjectPrefix und ObjectId, z. B. „ShapesDemoTypes::ShapeType“ {0x59, 0x51} {0x59, 0x5a}.
Repo: crates/xrce/src/object_id.rs (ObjectId::from_reference);
crates/xrce-agent/src/daemon/profiles.rs (AgentProfiles::predefined_objects)
Tests: crates/xrce/src/object_id.rs::tests::from_reference_matches_the_examples_of_the_spec,
crates/xrce-agent/src/daemon/profiles.rs::tests::the_example_file_of_the_spec_defines_the_objects_of_table_16,
crates/xrce-agent/src/daemon/definitions.rs::tests::the_example_file_defines_the_objects_of_table_16
Status: done — Commits 468aa0940da, 452ffeb7f84. Der Test in object_id.rs
rechnet alle zwölf Zeilen der Table 16 aus ihrer eigenen Zeichenkette nach
(Prefix, ObjectId, Art im unteren Halbbyte). Die Tests des Agent prüfen die
ObjectIds der Objekte, die er aus der Datei ableitet. Zwei Zeichenketten der
Table 16 weichen von der Datei in §9.3.1 ab:
„MyApplications::SimpleShapesDemoApplication“ statt
„MyApplications::ShapesDemoApp“ (MD5-Prefix von „ShapesDemoApp“: {0xeb, 0x1d})
und „MyTriangleReader“ statt „MyTriangleRdr“ (MD5-Prefix von „MyTriangleRdr“:
{0x50, 0x38}). Der Agent leitet nach der Regel aus §9.3 aus den Namen der Datei
ab; die ObjectIds dieser beiden Zeilen weichen deshalb von der Tabelle ab. Ein
Schalter für die andere Lesart besteht nicht. Der Participant heißt
„MyApplications::ShapesDemoApp::MyParticipant“, nicht nach dem Muster der Table
15.
§10 XRCE Deployments
§10 Operationen mit einem Agent, Austausch über DDS
Spec: §10, S. 93 — “All the operations described in the DDS-XRCE PIM pertain to the interaction of a client application with a single DDS-XRCE Agent. […] client applications may interact with each other despite connecting to different DDS-XRCE Agents. These interactions would happen as a consequence of the DDS-XRCE Agents creating and performing operations on DDS DomainParticipant entities”.
Repo: —
Tests: —
Status: n/a (informative) — Beschreibung.
§10.1 Client über den Agent zu jedem DDS-Participant
Spec: §10.1, S. 93 — “The DDS DomainParticipant will discover the proxy DDS Entities that the XRCE Agent creates on behalf of the Client and with use the standard DDS-RTPS Interoperability protocol to communicate wit the Agent. The XRCE Client will communicate with the XRCE Agent using the XRCE Protocol. Using this protocol it can direct the XRCE Agent to create new DDS entities and use these entities to read and write data on the DDS Global Data Space.”
Repo: crates/xrce-agent/src/daemon/dcps_bridge.rs (RealDdsPort Z. 310,
runtime_for Z. 396)
Tests: crates/xrce-agent/tests/e2e_udp_loopback.rs::e2e_udp_loopback_keyed_dispose_reliable_besteffort_and_fragments,
crates/xrce-agent/src/daemon/dcps_bridge.rs::tests::full_chain_against_a_real_leased_domain
Status: done — der erste Test schreibt und liest gegen einen eigenen DCPS-Participant im selben Prozess.
§10.2 Clients an verschiedenen Agents über DDS
Spec: §10.2, S. 93 — “XRCE Agents appear as DDS DomainParticipants in the DDS Dom ain. For this reason XRCE Client applications that are connected to different XRCE Agents will communicate with each other without the need for further configuration.”
Repo: crates/xrce-agent/src/daemon/dcps_bridge.rs (runtime_instance, runtime_for)
Tests: crates/xrce-agent/tests/two_agents.rs::two_clients_on_two_agents_exchange_a_sample_through_dds
Status: done — zwei Daemons in einer Domain, ein DataWriter über den ersten, ein DataReader über den zweiten: das Sample kommt mit gleichen Bytes an. Die GUID-Präfixe der Runtimes waren aus Domain und Host allein abgeleitet, zwei Agents auf einem Host entdeckten sich nicht; sie tragen Prozess und Zähler (a03a6c8cbc2). Der Test ist geschrieben, nicht ausgeführt. ### §10.3 Mehrere Clients an einem Agent wie mit eigenen Entitäten
Spec: §10.3, S. 94 — “Multiple XRCE Client applications may be connected to the same XRCE Agent. In it up to the implementation of the XRCE Agent whether the DDS Entities it creates are exclusive to each XRCE Client or alternatively are shared across XRCE Clients. However, the behavior observable by the XRCE Client shall be as if the DDS XRCE Agent creates separate DDS Objects exclusive to each XRCE Client. […] If the XRCE Agent shares DDS entities among different XRCE Clients, then the requiremen t to behave ‘as if’ each had its own separate entities requires that the local DDS DataWriter entities discover and match the local DDS DataReader entities in the same DomainParticipant.”
Repo: crates/xrce-agent/src/daemon/dcps_bridge.rs (runtime_for Z. 396:
ein DcpsRuntime je Domain für alle Clients, ein weiterer je Domain und
USER_DATA über own_runtime_slot; create_writer Z. 654, create_reader Z.
716)
Tests: crates/xrce-agent/src/daemon/dcps_bridge.rs::tests::two_large_samples_reach_a_default_reader_on_the_same_agent
Status: done — der Writer eines Client erreicht den Reader eines anderen
Client im selben DcpsRuntime. Eigene GUID und QoS des Participant sind je
Client nicht geprüft; ein Participant mit eigenem USER_DATA bekommt nach dem
Code einen eigenen DcpsRuntime (gelesen, nicht durch einen Test belegt).
§10.3 Abkürzung zwischen lokalem Writer und Reader
Spec: §10.3, S. 94 — “An implementation of an XRCE Agent may choose to create faster communication path between the local XRCE DataWriter and DataReader objects […]. This ‘shortcut’ can be implemented as an optimization”.
Repo: —
Tests: —
Status: n/a (informative) — Erlaubnis; der Agent geht über den
DcpsRuntime.
§10.4 Föderation von Agents
Spec: §10.4, S. 95 — “The specification supports federated deployments where XRCE Agents appear as Clients to other XRCE Agents. In other to support these deployments the XRCE Agent implementation must implement the client -side of the XRCE Protocol in addition to the server part. Supporting this kind of deployment is an implementation decision”.
Repo: —
Tests: —
Status: open — eine optionale Bereitstellung, die eine Client-Seite im Agent verlangt; crates/xrce-agent hat keine Seite als Client.
§10.5 Direkte Kommunikation zwischen Anwendungen
Spec: §10.5, S. 96 — “The specification supports applications having direct communications using only the XRCE Protoco l. In order to do this each application must implement both the XRCE Client and the XRCE Agent part of the protocol.”
Repo: —
Tests: —
Status: n/a (informative) — Möglichkeit der Bereitstellung.
§10.6 Kombinierte Bereitstellung
Spec: §10.6, S. 97–98 — “Figure 28 below illustrates a scenario where the different deployments are combined into a single system.”
Repo: —
Tests: —
Status: n/a (informative) — Abbildung.
§11 Transport Mappings
§11.1 Nicht an einen Transport gebunden
Spec: §11.1, S. 99 — “The XRCE protocol is not limited to any specific transports. It can be mapped to most existing network transports such as UDP, TCP and low bandwidth transports such as Bluetooth, ZigBee and 6LoWPAN.”
Repo: —
Tests: —
Status: n/a (informative) — Beschreibung; ZeroDDS hat UDP, TCP und eine
serielle Leitung (Items zu §11.2, §11.3 und Annex C).
§11.1 Erwartete Eigenschaften (1) bis (4)
Spec: §11.1, S. 99 — “To run without additional overhead, it is expected that the transport supports the following functionality: (1) Deliver messages of at least 64 bytes. (2) Handle the integrity of messages, dropping any messages that are corru pted. […] (3) Provide the size of the received message as well as the source address. […] (4) Support bi-directional communication.”
Repo: —
Tests: —
Status: n/a (informative) — Erwartung an den Transport. Die serielle
Leitung ergänzt Länge, Adressen und CRC (Items zu Annex C).
§11.1 Erwartete Eigenschaft (5) Sicherheit
Spec: §11.1, S. 99 — “(5) Provide transport-level security, specifically the means for the Client to authenticate the Agent and the means for secure (encrypted and authenticated) message exchange. Alternatively , the XRCE Agent and Client can be deployed on top of a secure network layer (e.g. an encrypted VPN).”
Repo: crates/xrce-agent/src/daemon/transport/secure.rs
(run_tls_listener, run_dtls_listener);
crates/xrce-agent/src/daemon/config.rs (ListenerConfig::Tls,
ListenerConfig::Dtls)
Tests: crates/xrce-agent/tests/secure_listeners.rs::tls::a_client_that_trusts_the_agents_certificate_opens_a_session,
crates/xrce-agent/tests/secure_listeners.rs::dtls::a_client_that_trusts_the_agents_certificate_opens_a_session
Status: n/a (informative) — Erwartung an den Transport. Der Agent hat
unter den Features tls und dtls die Listener kind: tls und kind: dtls
mit Zertifikat und Schlüssel des Agent (eb44fbbf575): der Client prüft den
Agent, die Nachrichten laufen verschlüsselt (Item zu §8.3.2.4 „Schutz des
ClientKey durch den Transport“). Die Listener udp, tcp und serial sind
nicht gesichert. Die Tests laufen nur mit dem jeweiligen Feature.
§11.1 Nicht verlangt: Zuverlässigkeit, Reihenfolge, Meldung von Verlusten
Spec: §11.1, S. 99 — “The following functionality is explicitly not required from the transport: (1) It does not need to provide reliability. […] (2) It does not need to provide ordering. […] (3) It does not need to provide notification of dropped messages.”
Repo: —
Tests: —
Status: n/a (informative) — Erlaubnis; Zuverlässigkeit und Reihenfolge
stehen in den Items zu §8.3.2.3 und §8.4.14.
§11.1 Hülle für fehlende Eigenschaften
Spec: §11.1, S. 99 — “Transports that do not meet some of the above pre-requisites may still be used by adding the missing information as an envelope around the XRCE message. […] If the transport does not support integrity a CRC suffix could be added to the XRCE message.”
Repo: —
Tests: —
Status: n/a (informative) — Möglichkeit; die Hüllen für TCP und die
serielle Leitung stehen in den Items zu §11.3.3 und Annex C.
§11.2 UDP ohne Sicherheit, DTLS oder VPN
Spec: §11.2, S. 99 — “The UDP transport meets all the functionality listed in clause 11.1. Except that it does not provide security. For applications requiring security there is the ‘Datagram Transport Layer Security’ (DTLS) standard [DTLS] that provides security in top of UDP/IP. Alternatively, UDP mat be deployed on a private network (VPN)”.
Repo: crates/xrce-agent/src/daemon/transport/secure.rs
(run_dtls_listener); crates/xrce/src/transport_dtls.rs (WebrtcDtls,
WebrtcDtlsServer)
Tests: crates/xrce-agent/tests/secure_listeners.rs::dtls::a_client_that_trusts_the_agents_certificate_opens_a_session,
crates/xrce-agent/tests/secure_listeners.rs::dtls::a_plain_text_create_client_on_the_dtls_port_is_not_answered,
crates/xrce/tests/dtls_e2e.rs::dtls_handshake_and_roundtrip
Status: n/a (informative) — Hinweis. Der Agent hat unter dem Feature
dtls den Listener kind: dtls (DTLS 1.2 mit dem Zertifikat des Agent,
eb44fbbf575); ein CREATE_CLIENT im Klartext auf diesem Port wird nicht
beantwortet. Die Tests laufen nur mit diesem Feature.
§11.2.1 UDP v4 mit ADDRESS_FORMAT_MEDIUM
Spec: §11.2.1, S. 99 — “When XRCE is mapped to the UDP v4, the TransportLocator union shall use the TransportLocatorFormat discriminator ADDRESS_FORMAT_MEDIUM. This selects the member medium_locator of type TransportLocatorMedium […] struct TransportLocatorMedium { octet address[4]; unsigned short port; };”
Repo: crates/xrce-agent/src/daemon/server.rs (listener_locators Z. 438);
crates/xrce/src/transport_locator.rs (TransportLocatorMedium,
TransportLocator::encode_member)
Tests: crates/xrce-agent/src/daemon/server.rs::tests::listener_locators_maps_udp_tcp_and_ipv6,
crates/xrce/src/transport_locator.rs::tests::medium_has_a_padding_octet_and_a_port_in_the_byte_order_of_the_flag,
crates/xrce/src/transport_locator.rs::tests::a_udp_locator_carries_the_default_agent_port
Status: done — Commits 299b3a41398. ein UDP-Listener mit IPv4-Adresse wird als
TransportLocator::Medium (Diskriminator ADDRESS_FORMAT_MEDIUM) gemeldet: vier
Oktette Adresse, ein Füllbyte, der Port als unsigned short in der
Byte-Reihenfolge des E-Flags.
§11.2.1 UDP v6 mit ADDRESS_FORMAT_LARGE
Spec: §11.2.1, S. 99–100 — “When XRCE is mapped to the UDP v6, the TransportLocator union shall use the TransportLocatorFormat discriminator ADDRESS_FORMAT_LARGE. […] struct TransportLocatorLarge { octet address[16]; unsigned long port; }; The address field shall contain the IP v6 address and the port field shall contain the UDP/IP v6 port number.”
Repo: crates/xrce-agent/src/daemon/server.rs (listener_locators Z. 438);
crates/xrce/src/transport_locator.rs (TransportLocatorLarge,
TransportLocator::encode_member)
Tests: crates/xrce-agent/src/daemon/server.rs::tests::listener_locators_maps_udp_tcp_and_ipv6,
crates/xrce/src/transport_locator.rs::tests::large_has_three_padding_octets_and_a_32_bit_port
Status: done — Commits 299b3a41398. ein UDP-Listener mit IPv6-Adresse wird als
TransportLocator::Large gemeldet: 16 Oktette Adresse, drei Füllbytes, der Port
als unsigned long.
§11.2.2 Agent als UDP-Server, Client als UDP-Client
Spec: §11.2.2, S. 100 — “The UDP Server sends replies back the Client using the address and port received in the message. […] When communicating over UDP the XRCE Agent shall behave as an UDP Server and the XRCE Client as the UDP Client.”
Repo: crates/xrce-agent/src/daemon/transport.rs (run_udp_listener Z.
428, PeerTable, Route::Udp); crates/xrce/src/transport_udp.rs
(XrceUdpSender::bind Z. 54)
Tests: crates/xrce-agent/src/daemon/transport.rs::tests::udp_listener_answers_create_client_over_loopback,
crates/xrce-agent/src/daemon/transport.rs::tests::a_client_registering_again_is_answered_at_its_new_address
Status: done — die Antwort geht an die Adresse, unter der sich der Client zuletzt mit CREATE_CLIENT gemeldet hat; ohne Eintrag an die Quelladresse.
§11.2.2 Port des Agent vorkonfiguriert
Spec: §11.2.2, S. 100 — “The XRCE Agent shall be pre-configured with the port number it shall listen to.”
Repo: crates/xrce-agent/src/daemon/config.rs (ListenerConfig::Udp,
Vorgabe 0.0.0.0:2018)
Tests: crates/xrce-agent/src/daemon/config.rs::tests::default_config_has_one_udp_listener_on_2018,
crates/xrce-agent/src/daemon/config.rs::tests::a_listener_can_be_written_as_one_string
Status: done — die Spec nennt keinen Standardport. agent_default_port
in crates/xrce/src/transport_udp.rs (Z. 27) rechnet 7400 + 4 · Domain; der
Agent benutzt die Funktion nicht.
§11.2.2 Adresse und Port des Agent im Client vorkonfiguriert
Spec: §11.2.2, S. 100 — “The XRCE Client shall be pre-configured with the UDP/IP address and port of the XRCE Agent.”
Repo: crates/xrce/src/transport_udp.rs (XrceUdpSender::bind Z. 54);
crates/xrce-client/src/lib.rs (ClientTransport Z. 89)
Tests: crates/xrce/src/transport_udp.rs::tests::loopback_roundtrip_create_client,
crates/xrce-agent/tests/e2e_udp_loopback.rs::e2e_udp_loopback_keyed_dispose_reliable_besteffort_and_fragments
Status: done — XrceClient bekommt die Adresse über seinen
ClientTransport; crates/xrce-client selbst hat keinen UDP-Transport, der
Test baut ihn in e2e_udp_loopback.rs.
§11.2.3 Keine Hülle, genau eine Nachricht je Datagramm
Spec: §11.2.3, S. 100 — “The mapping of the XRCE Protocol to UDP/IP does not add any additional envelopes around the XRCE message. The UDP/IP payload shall contain exactly one XRCE message.”
Repo: crates/xrce/src/transport_udp.rs (send_message Z. 67,
recv_message Z. 89)
Tests: crates/xrce/src/transport_udp.rs::tests::rfc768_udp_delivers_one_datagram_per_message_with_boundaries_intact,
crates/xrce/src/transport_udp.rs::tests::rfc768_datagram_larger_than_udp_payload_limit_is_rejected
Status: done
§11.2.4 Multicast-Adresse und Port des Agent
Spec: §11.2.4, S. 100 — “XRCE Agent discovery may be done using UDP/IP multicast. The XRCE Agents shall be pre-configured with the multicast address and port number they shall listen to. By default, they shall be the address 239.255.0.2 and the port 7400.”
Repo: crates/xrce/src/discovery.rs (XRCE_DISCOVERY_GROUP,
XRCE_DISCOVERY_PORT); crates/xrce-agent/src/daemon/discovery.rs
(bind_discovery_socket Z. 146); crates/xrce-agent/src/daemon/config.rs
(discovery_address, discovery_port)
Tests: crates/xrce/src/discovery.rs::tests::discovery_constants_match_spec,
crates/xrce/src/discovery.rs::tests::the_discovery_port_is_bound_shared,
crates/xrce-agent/src/daemon/discovery.rs::tests::the_discovery_group_is_the_one_given,
crates/xrce-agent/src/daemon/config.rs::tests::the_discovery_group_can_be_set
Status: done — Commits fd2e9a5bcfd. Vorgabe Gruppe 239.255.0.2 und Port 7400;
discovery.address: und discovery.port: stellen beide ein (Item unten).
§11.2.4 Einstellung der Multicast-Adresse
Spec: §11.2.4, S. 100 — wie oben.
Repo: crates/xrce-agent/src/daemon/config.rs (discovery_address,
Schlüssel discovery.address); crates/xrce-agent/src/daemon/discovery.rs
(bind_discovery_socket Z. 146); crates/xrce-agent/src/daemon/server.rs
(Aufruf Z. 400)
Tests: crates/xrce-agent/src/daemon/config.rs::tests::the_discovery_group_can_be_set,
crates/xrce-agent/src/daemon/discovery.rs::tests::the_discovery_group_is_the_one_given
Status: done — Commits fd2e9a5bcfd. der Agent tritt der eingestellten Gruppe
bei; eine Adresse, die keine IPv4-Multicast-Adresse ist, lehnen die
Konfiguration und bind_discovery_socket ab. Beim Client ist die
Multicast-Adresse ein Eintrag der Kandidatenliste von discover_over_udp.
§11.2.4 Periodisches GET_INFO des Client an die Multicast-Adresse
Spec: §11.2.4, S. 100 — “To discover Agents via multicast the XRCE Client shall send the GET_INFO message (see 8.3.5.3) periodically to the configured multicast address and port. […] The XRCE Client shall stop sending the periodic message once it receives a suitable response from an Agent.”
Repo: crates/xrce-client/src/discovery.rs (AgentDiscovery::poll,
on_datagram, discover_over_udp); crates/xrce/src/discovery.rs
(MulticastDiscovery::send_multicast)
Tests: crates/xrce-client/src/discovery.rs::tests::get_info_goes_to_the_candidates_every_period,
crates/xrce-client/src/discovery.rs::tests::a_suitable_answer_ends_the_search,
crates/xrce-client/src/discovery.rs::tests::the_search_over_udp_finds_the_agent_that_answers
Status: done — Commits fd2e9a5bcfd. GET_INFO(OBJECTID_AGENT) ohne Sitzung und
ohne ClientKey geht beim ersten Aufruf und danach je Periode an alle Adressen
der Liste (Multicast-Adresse und Port oder Unicast-Kandidaten); eine passende
Antwort (INFO mit STATUS_OK und gleicher Hauptversion) beendet das Senden, ein
STATUS_ERR_INCOMPATIBLE oder eine andere Hauptversion nicht. Der Test mit
Sockets sendet an Unicast-Kandidaten auf Loopback; der Empfang an einer echten
Multicast-Gruppe ist nicht geprüft.
§11.2.4 Antwort des Agent mit seinen TransportLocators
Spec: §11.2.4, S. 100 — “This message shall invoke the get_info operation (see 7.8.2.2) on the XRCE Agent, which shall respond and include its TransportLocators.”
Repo: crates/xrce-agent/src/daemon/discovery.rs (run_discovery_responder
Z. 43, build_info_reply Z. 107); crates/xrce-agent/src/daemon/server.rs
(listener_locators Z. 438)
Tests: crates/xrce-agent/src/daemon/discovery.rs::tests::discovery_responder_answers_get_info_on_agent,
crates/xrce-agent/src/daemon/server.rs::tests::listener_locators_maps_udp_tcp_and_ipv6
Status: done — Commits ca0cf7e08bf, 299b3a41398. INFO mit
AGENT_ActivityInfo.address_seq als TransportLocatorSeq der UDP- und
TCP-Listener (Medium für IPv4, Large für IPv6) und mit der
AGENT_Representation. Listener mit DTLS oder TLS und die serielle Leitung
meldet der Agent nicht; Annex A hat dafür kein TransportLocatorFormat.
§11.2.4 Unicast-Discovery über eine Liste von Adressen
Spec: §11.2.4, S. 100 — “XRCE Agent discovery may be done using UDP/IP unicast. The XRCE Clients shall be pre-configured with a list of candidate UDP addresses and ports where XRCE Agents may be located. To discover Agents via unicast the XRCE Client shall send the GET_INFO message (see 8.3.5.3) periodically to the configured addresses and ports. […] The XRCE Client shall stop sending the periodic message once it receives a suitable response from an Agent.”
Repo: crates/xrce-client/src/discovery.rs
(AgentDiscovery::new(candidates, period), discover_over_udp)
Tests: crates/xrce-client/src/discovery.rs::tests::get_info_goes_to_the_candidates_every_period,
crates/xrce-client/src/discovery.rs::tests::the_search_over_udp_finds_the_agent_that_answers
Status: done — Commits fd2e9a5bcfd. der Client bekommt eine Liste von
Kandidatenadressen, sendet GET_INFO periodisch an alle und hört bei einer
passenden Antwort auf.
§11.3 TCP ohne Sicherheit und Länge, TLS oder VPN
Spec: §11.3, S. 100–101 — “The TCP transport meets all the functionality listed in clause 11.1. except it does not provide security nor information on the message size. For applications requiring security there is the ‘Transport Layer Security (TLS)’ standard [TLS] […]. The message size shall be added as a prefix ahead of the XRCE message as defined in 11.3.3.”
Repo: crates/xrce-agent/src/daemon/transport/secure.rs
(run_tls_listener); crates/xrce/src/transport_tls.rs (RustlsTlsClient,
RustlsTlsServer)
Tests: crates/xrce-agent/tests/secure_listeners.rs::tls::a_client_that_trusts_the_agents_certificate_opens_a_session,
crates/xrce-agent/tests/secure_listeners.rs::tls::a_plain_text_create_client_on_the_tls_port_is_not_answered,
crates/xrce/tests/tls_e2e.rs::tls_handshake_and_message_roundtrip
Status: n/a (informative) — Hinweis; die Länge steht im Item zu §11.3.3.
Der Agent hat unter dem Feature tls den Listener kind: tls (TLS mit dem
Zertifikat des Agent, eb44fbbf575); das 2-Byte-Längenpräfix steht im
verschlüsselten Strom. Die Tests laufen nur mit diesem Feature.
§11.3.1 TCP v4 mit ADDRESS_FORMAT_MEDIUM
Spec: §11.3.1, S. 101 — “When XRCE is mapped to the TCP/IP version 4, the TransportLocator union shall use the TransportLocatorFormat discriminator ADDRESS_FORMAT_MEDIUM.”
Repo: crates/xrce-agent/src/daemon/server.rs (listener_locators Z. 438);
crates/xrce/src/transport_locator.rs (TransportLocatorMedium)
Tests: crates/xrce-agent/src/daemon/server.rs::tests::listener_locators_maps_udp_tcp_and_ipv6,
crates/xrce/src/transport_locator.rs::tests::medium_has_a_padding_octet_and_a_port_in_the_byte_order_of_the_flag
Status: done — Commits 299b3a41398. ein TCP-Listener mit IPv4-Adresse wird als
TransportLocator::Medium (ADDRESS_FORMAT_MEDIUM) gemeldet; der Diskriminator
0x04 besteht nicht mehr.
§11.3.1 TCP v6 mit ADDRESS_FORMAT_LARGE
Spec: §11.3.1, S. 101 — “When XRCE is mapped to the TCP/IP version 6, the TransportLocator union shall use the TransportLocatorFormat discriminator ADDRESS_FORMAT_LARGE. […] The address field shall contain the IP v6 address and the port field shall contain the TCP/IP v6 port number.”
Repo: crates/xrce-agent/src/daemon/server.rs (listener_locators Z. 438);
crates/xrce/src/transport_locator.rs (TransportLocatorLarge)
Tests: crates/xrce-agent/src/daemon/server.rs::tests::listener_locators_maps_udp_tcp_and_ipv6,
crates/xrce/src/transport_locator.rs::tests::large_has_three_padding_octets_and_a_32_bit_port
Status: done — Commits 299b3a41398. ein TCP-Listener mit IPv6-Adresse wird als
TransportLocator::Large gemeldet, mit der Portnummer in locator_port.
§11.3.2 Agent als TCP-Server, Client als TCP-Client
Spec: §11.3.2, S. 101 — “The TCP Server accepts the connection from the Client. This establishes a bi-directional communication channel. […] The TCP Server can send and receive messages to and from the Client. When communicating over TCP the XRCE Agent shall behave as a TCP Server and the XRCE Client as the TCP Client.”
Repo: crates/xrce/src/transport_tcp.rs (XrceTcpServer::accept Z. 160,
XrceTcpClient::connect Z. 52); crates/xrce-agent/src/daemon/transport.rs
(run_tcp_listener Z. 550, run_tcp_connection Z. 485)
Tests: crates/xrce/src/transport_tcp.rs::tests::tcp_loopback_create_client_roundtrip,
crates/xrce/src/transport_tcp.rs::tests::tcp_loopback_three_message_chain,
crates/xrce-agent/src/daemon/transport.rs::tests::a_tcp_client_gets_the_messages_of_the_agent_over_its_connection
Status: done — die Rollen sind im Transport und am TCP-Listener des Agent geprüft; der Agent sendet über die Verbindung auch ohne Anfrage (Items unten).
§11.3.2 TCP-Listener des Agent
Spec: §11.3.2, S. 101 — wie oben.
Repo: crates/xrce-agent/src/daemon/transport.rs (run_tcp_listener Z.
550, run_tcp_connection Z. 485)
Tests: crates/xrce-agent/src/daemon/transport.rs::tests::a_tcp_client_gets_the_messages_of_the_agent_over_its_connection
Status: done — der Test startet den Listener, registriert einen Client über
TCP und erhält STATUS_AGENT. XrceTcpServer benutzt der Agent nicht.
§11.3.2 Nachrichten des Agent ohne Anfrage über TCP
Spec: §11.3.2, S. 101 — “The TCP Server can send and receive messages to and from the Client.”
Repo: crates/xrce-agent/src/daemon/transport.rs (run_ticker Z. 410,
deliver Z. 367, Route)
Tests: crates/xrce-agent/src/daemon/transport.rs::tests::a_tcp_client_gets_the_messages_of_the_agent_over_its_connection
Status: done — Commits d1cfe57959b. ein Thread (run_ticker, transport.rs
Z. 410) ruft tick für alle Listener auf; deliver (Z. 367) sendet jede
Nachricht über den Weg, auf dem sich ihr Client registriert hat: den Socket
eines UDP-Listeners oder die Warteschlange des Schreibers einer TCP-Verbindung
oder seriellen Leitung. Mit der Verbindung gehen ihre Wege. Der Test erhält
über die Verbindung eine Nachricht, die der Agent ohne Anfrage sendet.
§11.3.2 Port des Agent vorkonfiguriert
Spec: §11.3.2, S. 101 — “The XRCE Agent shall be pre-configured with the port number it shall listen to.”
Repo: crates/xrce-agent/src/daemon/config.rs (ListenerConfig::Tcp)
Tests: crates/xrce-agent/src/daemon/config.rs::tests::a_listener_can_be_written_as_one_string
Status: done
§11.3.2 Adresse und Port des Agent im Client vorkonfiguriert
Spec: §11.3.2, S. 101 — “The XRCE Client shall be pre-configured with the TCP/IP address and port of the XRCE Agent.”
Repo: crates/xrce/src/transport_tcp.rs (XrceTcpClient::connect Z. 52);
crates/xrce-client/src/discovery.rs (TcpTransport, connect_over_tcp)
Tests: crates/xrce/src/transport_tcp.rs::tests::tcp_loopback_create_client_roundtrip,
crates/xrce-client/src/discovery.rs::tests::the_search_over_tcp_connects_to_the_agent_that_accepts
Status: done — Commits fd2e9a5bcfd. crates/xrce-client hat mit TcpTransport
einen ClientTransport über TCP (Feature std); connect_over_tcp verbindet
sich mit den vorkonfigurierten Adressen und sendet CREATE_CLIENT.
§11.3.3 Länge in zwei Byte, little-endian
Spec: §11.3.3, S. 101 — “The mapping of the XRCE Protocol to TCP/IP adds a 2-byte prefix as an envelope the XRCE message. The 2-byte prefix shall contain the length of the XRCE message that follows encoded as little endian.”
Repo: crates/xrce/src/transport_tcp.rs (TCP_LENGTH_PREFIX_SIZE Z. 37,
XrceTcpClient::send_message Z. 70, recv_message Z. 103)
Tests: crates/xrce/src/transport_tcp.rs::tests::tcp_length_prefix_size_constant,
crates/xrce/src/transport_tcp.rs::tests::rfc793_byte_stream_is_delimited_by_the_length_prefix_not_by_writes,
crates/xrce/src/transport_tcp.rs::tests::rfc793_frame_split_across_two_writes_is_reassembled
Status: done
§11.3.3 Genau eine Nachricht, Ausrichtung unverändert
Spec: §11.3.3, S. 101 — “After the 2-byte envelope the TCP/IP payload shall contain exactly one XRCE message. The alignment of the XRCE message shall not be changed by the added 2-byte prefix. Stated differently the XRCE message shall consider its first byte to be aligned to an 8-byte (XCDR maximum alignment) boundary.”
Repo: crates/xrce/src/transport_tcp.rs (send_message: msg.encode()
vor der Länge)
Tests: crates/xrce/src/transport_tcp.rs::tests::tcp_loopback_three_message_chain,
crates/xrce/src/submessages/mod.rs::tests::message_two_submessages_padded_correctly
Status: done — die Nachricht wird ohne Kenntnis der Länge kodiert. §8.2.1 nennt für den Anfang der Nachricht eine Ausrichtung auf 16 Byte, §11.3.3 eine auf 8 Byte.
§11.3.4 Multicast-Discovery auch für TCP
Spec: §11.3.4, S. 102 — “XRCE Agent discovery may be done using UDP/IP multicast even if the communication will be over TCP. The XRCE Agents may be pre-configured with the multicast address and port number they shall listen to. By default they shall be the address 239.255.0.2 and the port 7400.”
Repo: crates/xrce-agent/src/daemon/server.rs (Responder unabhängig von der
Art der Listener); crates/xrce-agent/src/daemon/discovery.rs
(bind_discovery_socket Z. 146)
Tests: crates/xrce-agent/src/daemon/discovery.rs::tests::discovery_responder_answers_get_info_on_agent,
crates/xrce/src/discovery.rs::tests::discovery_constants_match_spec
Status: done — der Locator eines TCP-Listener in der Antwort ist im Item zu §11.3.1 behandelt.
§11.3.4 Periodisches GET_INFO des Client für TCP
Spec: §11.3.4, S. 102 — “To discover Agents via multicast the XRCE Client shall send the GET_INFO message (see 8.3.5.3) periodically to the configured multicast address and port. […] The XRCE Client shall stop sending the periodic message once it receives a suitable response from an Agent.”
Repo: crates/xrce-client/src/discovery.rs (AgentDiscovery,
discover_over_udp)
Tests: crates/xrce-client/src/discovery.rs::tests::get_info_goes_to_the_candidates_every_period,
crates/xrce-client/src/discovery.rs::tests::a_suitable_answer_ends_the_search,
crates/xrce-client/src/discovery.rs::tests::the_search_over_udp_finds_the_agent_that_answers
Status: done — Commits fd2e9a5bcfd. wie im Item zu §11.2.4: der Client sucht
den Agent mit GET_INFO an die Multicast-Adresse und verbindet sich danach über
TCP (Item unten).
§11.3.4 Discovery über TCP-Verbindungen zu einer Liste von Adressen
Spec: §11.3.4, S. 102 — “The XRCE Clients shall be pre-configured with a list of candidate TCP addresses and ports where XRCE Agents may be located. To discover Agents via unicast the XRCE Client shall periodically attempt to establish TCP connections to the configured addresses and ports. One a connection is established it shall send the CREATE_CLIENT message […]. The XRCE Client shall stop making periodic connection attempts once it receives a suitable response from an Agent.”
Repo: crates/xrce-client/src/discovery.rs (connect_over_tcp)
Tests: crates/xrce-client/src/discovery.rs::tests::the_search_over_tcp_connects_to_the_agent_that_accepts
Status: done — Commits fd2e9a5bcfd. der Client versucht je Periode, sich mit
jeder Adresse der Liste zu verbinden; auf eine Verbindung sendet er
CREATE_CLIENT und hört bei einem STATUS_AGENT mit STATUS_OK auf.
§11.4 Weitere Transporte
Spec: §11.4, S. 102 — “The XRCE Protocol is well suited to be mapped to other transports […]. it is expected that future revisions of this specification will provide additional transport mappings. An example Serial Transport mapping can be found in Annex C.1”
Repo: —
Tests: —
Status: n/a (informative) — Ausblick; die serielle Leitung steht in den
Items zu Annex C.
Annex A IDL Types
Annex A Typen, die §7.7 und §8.3.5 gleichen
Spec: Annex A, S. 103–120 — “module dds { module xrce { […] }; };” mit ClientKey, ObjectKind, ObjectId, XrceCookie, XrceVersion, XrceVendorId, Time_t, SessionId, StreamId, RepresentationFormat und den Repräsentationen der Objekte, CreationMode, RequestId, StatusValue, ResultStatus, InfoMask, den ActivityInfo-Typen, ObjectInfo, BaseObjectRequest, BaseObjectReply, DataFormat, DataDeliveryControl, ReadSpecification, SampleInfoFlags, SampleInfoDelta, SampleData, Sample, SampleDelta, PackedSamples, DataRepresentation, den Payloads der Submessages und SubmessageId.
Repo: —
Tests: —
Status: n/a (informative) — Zuordnung: wo Annex A dieselbe Form hat wie
§7.7 oder §8.3.5, steht die Anforderung im Item dort. Abweichende und
zusätzliche Formen stehen in den folgenden Items. Annex A schreibt
SESSIONID_NONE_WITH_CLIENT_KEY, §8.3.2.1 SESSION_ID_NONE_WITH_CLIENT_KEY;
Annex A schreibt STREAMID_BUILTIN_BEST_EFFORTS.
Annex A Typen ohne @extensibility
Spec: Annex A, S. 104–112, S. 119 — “struct Time_t { long seconds; unsigned long nanoseconds; };”, “struct TransportLocatorMedium { […] };”, “struct Property { string name; string value; };”, “struct ResultStatus { StatusValue status; octet implementation_status; };”, “struct ACKNACK_Payload { […] };” ohne Annotation; DDS-XTypes 1.3 §7.3.1.2.1.8, S. 96: “In the event that the representation of a given type does not indicate the type’s extensibility kind, the type shall be considered appendable.”
Repo: crates/xrce/src/encoding.rs (UnannotatedTypes,
with_unannotated_types, begin_unannotated, end_unannotated);
crates/xrce-agent/src/daemon/config.rs (unannotated_types)
Tests: crates/xrce/tests/unannotated_types.rs::the_default_is_appendable_with_a_dheader,
crates/xrce/tests/unannotated_types.rs::the_final_setting_writes_the_reference_implementations_octets,
crates/xrce/tests/unannotated_types.rs::both_forms_are_read_in_either_setting,
crates/xrce/tests/unannotated_types.rs::the_reference_implementations_octets_are_read_in_the_default_setting,
crates/xrce/src/transport_locator.rs::tests::by_default_the_union_and_its_case_have_a_dheader,
crates/xrce-agent/src/daemon/config.rs::tests::the_extensibility_of_unannotated_types_can_be_set
Status: done — Commits 7f85e76debd, 220857a1e90, 5f31939a719. Ohne
@extensibility gilt APPENDABLE (DDS-XTypes 1.3 §7.3.1.2.1.8): Time_t,
ResultStatus, Property, TransportLocator und ACKNACK_Payload tragen in
XCDR2 einen DHEADER; das ist die Vorgabe. Die Oktette des Mitschnitts von
eProsima (STATUS 6 Byte Payload, ACKNACK 5 Byte, aus
tools/wire-capture/xrce-sessions/agent-to-client.hex gelesen) sind die
benannte Einstellung FINAL: Agent-Schlüssel unannotated_types: final, Rust-API
zerodds_xrce::encoding::UnannotatedTypes::Final; jedes SDK hat die Option
„unannotated types“ (82fa0a977e2). Die Leser nehmen beide Formen an.
Annex A OBJK_OTHER = 0x0F
Spec: Annex A, S. 103 — “const ObjectKind OBJK_OTHER = 0x0F;”
Repo: crates/xrce/src/object_kind.rs (OBJK_OTHER Z. 43,
ObjectKind::Other, ObjectKind::from_u8)
Tests: crates/xrce/src/object_kind.rs::tests::all_spec_kinds_roundtrip,
crates/xrce/src/object_kind.rs::tests::raw_const_values_match_spec
Status: done — Commits daf2a618f74. der Wert 0x0F heißt OBJK_OTHER wie in
Annex A; OBJK_DOMAIN besteht nicht mehr. Die Spec gibt der Domain keine
ObjectKind (Item zu §7.7.3.4).
Annex A OBJECTID_AGENT {0xFF, 0xFD}
Spec: Annex A, S. 103 — “#define OBJECTID_AGENT {0xFF,0xFD}”
Repo: crates/xrce/src/object_id.rs (OBJECTID_AGENT Z. 44)
Tests: crates/xrce/src/object_id.rs::tests::agent_singleton_has_kind_agent,
crates/xrce-agent/src/daemon/discovery.rs::tests::discovery_responder_answers_get_info_on_agent
Status: done
Annex A OBJECTID_SESSION {0xFF, 0xFF}
Spec: Annex A, S. 103 — “#define OBJECTID_SESSION {0xFF,0xFF}”
Repo: crates/xrce/src/object_id.rs (OBJECTID_SESSION Z. 42,
OBJECTID_INVALID Z. 40)
Tests: crates/xrce/src/object_id.rs::tests::session_object_id_is_all_ones,
crates/xrce/src/object_id.rs::tests::reserved_object_ids_per_spec_7_6_and_annex_a
Status: done — Commits daf2a618f74. OBJECTID_SESSION ist {0xFF, 0xFF};
OBJECTID_INVALID ist {0x00, 0x00} (§7.6). Die Spec sagt nicht, wofür
OBJECTID_SESSION steht; der Code benutzt die Konstante nicht.
Annex A XRCE_VENDOR_INVALID
Spec: Annex A, S. 104 — “typedef octet XrceVendorId[2]; #define XRCE_VENDOR_INVALID1 0x00 #define XRCE_VENDOR_INVALID1 0x00”
Repo: —
Tests: —
Status: n/a (informative) — Konstanten ohne Regel. Die Zeile steht
zweimal mit demselben Namen; gemeint sind vermutlich die beiden Oktette eines
ungültigen Vendor.
Annex A TransportLocatorFormat
Spec: Annex A, S. 104 — “@bit_bound(8) enum TransportLocatorFormat { ADDRESS_FORMAT_SMALL, ADDRESS_FORMAT_MEDIUM, ADDRESS_FORMAT_LARGE, ADDRESS_FORMAT_STRING };” und S. 105 “union TransportLocator switch (TransportLocatorFormat) { […] case ADDRESS_FORMAT_LARGE: TransportLocatorLarge medium_locator; […] };”
Repo: crates/xrce/src/transport_locator.rs (fmt_disc Z. 50,
TransportLocator::encode_into, decode_at)
Tests: crates/xrce/src/transport_locator.rs::tests::medium_has_a_padding_octet_and_a_port_in_the_byte_order_of_the_flag,
crates/xrce/src/transport_locator.rs::tests::large_has_three_padding_octets_and_a_32_bit_port,
crates/xrce/src/transport_locator.rs::tests::small_is_two_address_octets_and_a_one_octet_port,
crates/xrce/src/transport_locator.rs::tests::string_length_is_aligned_to_four,
crates/xrce/src/transport_locator.rs::tests::unknown_discriminator_rejected
Status: done — Commits 299b3a41398. die vier Werte 0 bis 3; der Diskriminator
ist ein Oktett vor dem Member, in der Vorgabe hinter dem DHEADER der Union (Item
zu Annex A „Typen ohne @extensibility“). Annex A nennt das Member für LARGE
medium_locator; auf der Leitung hat der Name keine Wirkung.
Annex A Diskriminatoren 0x04 und 0x05
Spec: Annex A, S. 104 — wie oben.
Repo: crates/xrce/src/transport_locator.rs (fmt_disc hat nur 0x00 bis
0x03)
Tests: crates/xrce/src/transport_locator.rs::tests::unknown_discriminator_rejected
Status: done — Commits 299b3a41398. fmt_disc::TCP und fmt_disc::SERIAL
sowie TransportLocator::Tcp und Serial sind entfernt; der Test weist die
Diskriminatoren 4 und 5 ab. TCP-Listener werden als Medium oder Large gemeldet,
die serielle Leitung gar nicht.
Annex A TransportLocatorSmall
Spec: Annex A, S. 104–105 — “struct TransportLocatorSmall { octet address[2]; octet locator_port; };”
Repo: crates/xrce/src/transport_locator.rs (TransportLocatorSmall:
address: [u8; 2], port: u8)
Tests: crates/xrce/src/transport_locator.rs::tests::small_is_two_address_octets_and_a_one_octet_port
Status: done — Commits 299b3a41398. zwei Oktette Adresse und ein Oktett Port,
ohne Füllbytes.
Annex A TransportLocatorMedium
Spec: Annex A, S. 105 — “struct TransportLocatorMedium { octet address[4]; unsigned short locator_port; };”
Repo: crates/xrce/src/transport_locator.rs (TransportLocatorMedium,
encode_member)
Tests: crates/xrce/src/transport_locator.rs::tests::medium_has_a_padding_octet_and_a_port_in_the_byte_order_of_the_flag,
crates/xrce/src/transport_locator.rs::tests::a_udp_locator_carries_the_default_agent_port
Status: done — Commits 299b3a41398. wie im Item zu §11.2.1: ein Füllbyte nach
der Adresse, der Port als Zahl in der Byte-Reihenfolge des E-Flags.
Annex A TransportLocatorLarge
Spec: Annex A, S. 105 — “struct TransportLocatorLarge { octet address[16]; unsigned long locator_port; };”
Repo: crates/xrce/src/transport_locator.rs (TransportLocatorLarge,
TransportLocator::encode_into, TransportLocator::decode_at)
Tests: crates/xrce/src/transport_locator.rs::tests::large_has_three_padding_octets_and_a_32_bit_port,
crates/xrce/src/transport_locator.rs::tests::a_locator_sequence_is_a_count_and_aligned_locators
Status: done — Commits 299b3a41398, 7f85e76debd. 16 Adressoktette, drei
Füllbytes, der Port als unsigned long in der Byte-Reihenfolge des E-Flags.
Union und Struktur des Falls tragen ohne @extensibility je einen DHEADER
(APPENDABLE nach DDS-XTypes 1.3 §7.3.1.2.1.8); der Agent-Schlüssel
unannotated_types: final schreibt sie ohne. Der Test der Füllbytes läuft in
der Einstellung Final, der Test der Folge in der Vorgabe.
Annex A TransportLocatorString
Spec: Annex A, S. 105 — “struct TransportLocatorString { string value; };”
Repo: crates/xrce/src/transport_locator.rs (TransportLocator::String,
TRANSPORT_LOCATOR_STRING_MAX, TransportLocator::encode_into)
Tests: crates/xrce/src/transport_locator.rs::tests::string_length_is_aligned_to_four,
crates/xrce/src/transport_locator.rs::tests::a_long_string_locator_is_not_cut_at_256,
crates/xrce/src/transport_locator.rs::tests::a_string_without_its_nul_is_refused
Status: done — Commits 299b3a41398. die Länge ist ein unsigned long, auf 4
ausgerichtet und in der Byte-Reihenfolge des E-Flags; danach die Zeichen mit
NUL. Die Obergrenze beträgt 65 535 Byte (die Größe einer Submessage), nicht
mehr 256.
Annex A Property und PropertySeq
Spec: Annex A, S. 105 — “struct Property { string name; string value; };
typedef sequence
Repo: crates/xrce/src/handshake.rs (Property, encode_properties,
decode_properties, decode_property, MAX_PROPERTIES)
Tests: crates/xrce/src/handshake.rs::tests::a_property_has_a_dheader_by_default,
crates/xrce/src/handshake.rs::tests::a_big_endian_client_representation_with_properties_reads_back,
crates/xrce/src/handshake.rs::tests::a_big_endian_agent_representation_with_properties_reads_back,
crates/xrce/src/handshake.rs::tests::padding_counts_from_the_start_of_the_payload,
crates/xrce/src/handshake.rs::tests::max_properties_cap_enforced_on_decode,
crates/xrce/src/handshake.rs::tests::a_malformed_property_seq_is_an_error_not_absent_properties,
crates/xrce-agent/src/daemon/session.rs::tests::an_unreadable_property_seq_is_refused_with_invalid_data
Status: done — Commits ca0cf7e08bf, 7f85e76debd, b9255734bfb. die Zahl der
Elemente und die Längen der Zeichenketten sind unsigned long, ab dem Anfang
der Payload auf 4 ausgerichtet; die Zahl liegt in CLIENT_Representation auf
Versatz 16. Jede Property trägt ohne @extensibility einen DHEADER (Vorgabe),
unannotated_types: final schreibt sie ohne; beide Formen werden gelesen. Die
Byte-Reihenfolge folgt dem E-Flag. Eine Folge, die sich nicht lesen lässt, ist
ein Fehler und gilt nicht als nicht vorhanden; der Agent antwortet darauf mit
STATUS_ERR_INVALID_DATA. Obergrenze beim Lesen: 64 Elemente.
Annex A CLIENT_Representation
Spec: Annex A, S. 105–106 — “@extensibility(FINAL) struct CLIENT_Representation { XrceCookie xrce_cookie; XrceVersion xrce_version; XrceVendorId xrce_vendor_id; ClientKey client_key; SessionId session_id; @optional PropertySeq properties; };”
Repo: crates/xrce/src/handshake.rs (ClientRepresentation, encode_with,
decode_with, encode_into, decode_at)
Tests: crates/xrce/src/handshake.rs::tests::client_representation_decodes_the_captured_create_client_prefix,
crates/xrce/src/handshake.rs::tests::client_representation_roundtrip_with_properties,
crates/xrce/src/handshake.rs::tests::by_default_the_representations_have_no_timestamp,
crates/xrce/src/handshake.rs::tests::the_prose_form_has_a_time_t_after_the_vendor_id
Status: done — Commits ca0cf7e08bf, b9255734bfb, f8bdf3cd878. der Code folgt
der Form von Annex A; @optional ist ein Oktett 0 oder 1, properties liegt
wie im Item oben. Der Text in §7.8.2.1 nennt zusätzlich ein Time_t client_timestamp hinter xrce_vendor_id; IDL und Bytes von Annex B.1 haben es
nicht. Die Form von Annex A ist die Vorgabe; die Form des Textes ist die
benannte Einstellung RepresentationTimestamps::Present (Agent-Schlüssel
representation_timestamps: present, XrceClient::set_representation_timestamps,
Option representation timestamps in jedem SDK). Die zwei Oktette nach
properties (requested_mtu) sind eine Erweiterung von eProsima, auf 2
ausgerichtet.
Annex A AGENT_Representation
Spec: Annex A, S. 106 — “@extensibility(FINAL) struct AGENT_Representation { XrceCookie xrce_cookie; XrceVersion xrce_version; XrceVendorId xrce_vendor_id; @optional PropertySeq properties; };”
Repo: crates/xrce/src/handshake.rs (AgentRepresentation, encode_with,
decode_with, encode_into, decode_at)
Tests: crates/xrce/src/handshake.rs::tests::agent_representation_decodes_the_captured_status_agent_body,
crates/xrce/src/handshake.rs::tests::agent_representation_roundtrip_no_properties,
crates/xrce/src/handshake.rs::tests::the_agent_representation_follows_the_setting_the_same_way
Status: done — Commits ca0cf7e08bf, b9255734bfb, f8bdf3cd878. die Form mit
agent_timestamp (§7.8.2.1) ist dieselbe benannte Einstellung wie bei
CLIENT_Representation (representation_timestamps, Vorgabe absent nach
Annex A).
Annex A OBJK_DomainParticipant_Binary
Spec: Annex A, S. 109 — “@extensibility(APPENDABLE) struct OBJK_DomainParticipant_Binary { @optional string<128> domain_reference; @optional string<128> qos_profile_reference; };”
Repo: crates/xrce-agent/src/daemon/binary_forms.rs (participant,
ParticipantBinary); crates/xrce-agent/src/daemon/entity_repr.rs
(participant)
Tests: crates/xrce-agent/src/daemon/binary_forms.rs::tests::participant_binary_in_both_forms,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_spec_binary_participant_is_read,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_domain_reference_is_resolved_against_the_domain_libraries,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_participant_qos_profile_reference_is_applied
Status: done — Commits f548fee2522, 0b67c04800c. der Blob wird als XCDR2 gelesen:
Annex A (DHEADER, zwei @optional-Referenzen), dann die Form von §7.7.3.6.3
(long domain_id zuerst), dann die zwei Referenzen ohne DHEADER, die der
Client von eProsima sendet. domain_reference wird gegen die Domains der
<domain_library>-Dateien aufgelöst (STATUS_ERR_UNKNOWN_REFERENCE für einen
Namen in keiner Bibliothek; die domain_id der Domain muss mit der der
Darstellung übereinstimmen). qos_profile_reference wendet die
Teilnehmer-QoS des Profils an (USER_DATA, ENTITY_FACTORY; jede andere Richtlinie
ergibt STATUS_ERR_INCOMPATIBLE).
Annex A OBJK_Topic_Binary als APPENDABLE
Spec: Annex A, S. 109 — “@extensibility(APPENDABLE) struct OBJK_Topic_Binary { string<256> topic_name; @optional string<256> type_reference; @optional DDS:XTypes::TypeIdentifier type_identifier; };”
Repo: crates/xrce-agent/src/daemon/binary_forms.rs (topic,
TopicBinary, Form::AnnexA, Form::Clauses); crates/xrce-agent/src/daemon/entity_repr.rs
(topic)
Tests: crates/xrce-agent/src/daemon/binary_forms.rs::tests::annex_a_topic_has_a_dheader,
crates/xrce-agent/src/daemon/binary_forms.rs::tests::the_36_octet_example_of_the_clause_is_a_topic,
crates/xrce-agent/src/daemon/binary_forms.rs::tests::a_topic_with_a_type_identifier_reads_it_and_one_without_a_type_is_refused,
crates/xrce-agent/src/daemon/binary_forms.rs::tests::string_bounds_are_checked,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_spec_binary_topic_names_its_topic_and_type
Status: done — Commits f548fee2522. gelesen wird die Form von Annex A (DHEADER
vor den Elementen) und die FINAL-Form von §7.7.3.7.3 (ohne DHEADER, die 36
Oktette des Beispiels in §7.7.3.1.3); §7.7.3.7.3 gibt keine Erweiterbarkeit an.
string<256> wird geprüft. Ein type_identifier hat Vorrang vor
type_reference; fehlen beide, antwortet der Agent mit
STATUS_ERR_INVALID_DATA.
Annex A OBJK_Publisher_Binary als APPENDABLE
Spec: Annex A, S. 109 — “@extensibility(FINAL) struct
OBJK_Publisher_Binary_Qos { @optional sequence
Repo: crates/xrce-agent/src/daemon/binary_forms.rs (container,
ContainerBinary); crates/xrce-agent/src/daemon/entity_repr.rs (container)
Tests: crates/xrce-agent/src/daemon/binary_forms.rs::tests::publisher_binary_of_annex_a,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::an_annex_a_binary_publisher_gives_its_partitions,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_captured_binary_publisher_has_default_qos
Status: done — Commits f548fee2522. die Form von Annex A (DHEADER, publisher_name,
qos mit partitions und group_data) wird gelesen; scheitert sie, liest
container die Form ohne DHEADER von §7.7.3.8.2, die der Client von eProsima
sendet. Der Name der QoS-Struktur lautet in §7.7.3.8.2
OBJK_PUBLISHER_QosBinary; auf der Leitung hat das keine Wirkung.
Annex A OBJK_Subscriber_Binary als APPENDABLE
Spec: Annex A, S. 109 — “@extensibility(APPENDABLE) struct OBJK_Subscriber_Binary { @optional string subscriber_name; @optional OBJK_Subscriber_Binary_Qos qos; };”
Repo: crates/xrce-agent/src/daemon/binary_forms.rs (container,
ContainerBinary); crates/xrce-agent/src/daemon/entity_repr.rs (container
mit element = subscriber)
Tests: crates/xrce-agent/src/daemon/binary_forms.rs::tests::publisher_binary_of_annex_a,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::an_annex_a_binary_publisher_gives_its_partitions
Status: done — Commits f548fee2522. dieselbe Funktion und dasselbe Layout wie beim
Publisher; die Tests lesen den Blob des Publishers, ein Test mit einem eigenen
Blob des Subscribers fehlt.
Annex A EndpointQosFlags mit is_history_keep_all
Spec: Annex A, S. 110 — “@bit_bound(16) bitmask EndpointQosFlags { @position(0) is_reliable, @position(1) is_history_keep_all, […] };”
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (apply_endpoint_binary,
spec_flags, flags); crates/xrce-agent/src/daemon/binary_forms.rs
(EndpointBinary::bit1_is_keep_all)
Tests: crates/xrce-agent/src/daemon/binary_forms.rs::tests::writer_binary_of_annex_a_with_qos,
crates/xrce-agent/src/daemon/binary_forms.rs::tests::reader_binary_of_the_clause,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::an_annex_a_binary_writer_names_its_topic_and_qos,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_clause_binary_reader_names_its_topic_and_qos,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_captured_binary_writer_is_reliable_keep_last_transient_local
Status: done — Commits f548fee2522. Annex A (Bit 1 = is_history_keep_all) und
§7.7.3.10.2 (Bit 1 = is_history_keep_last) widersprechen sich. Das Bit wird
nach der Form gelesen, in der der Blob lesbar ist: Form von Annex A zuerst, dann
die Form der Klausel; die klassische CDR-Struktur von eProsima (qos_flags
0x000b im Mitschnitt) liest Bit 1 als KEEP_LAST. Bits außerhalb von
EndpointQosFlags und mehrere Durability-Bits ergeben
STATUS_ERR_INVALID_DATA.
Annex A OBJK_DataWriter_Binary_Qos
Spec: Annex A, S. 110 — “@extensibility(FINAL) struct OBJK_DataWriter_Binary_Qos : OBJK_Endpoint_Binary_Qos { @optional unsigned long ownership_strength; };”
Repo: crates/xrce-agent/src/daemon/binary_forms.rs (endpoint_qos)
Tests: crates/xrce-agent/src/daemon/binary_forms.rs::tests::writer_binary_of_annex_a_with_ownership_strength, crates/xrce-agent/src/daemon/binary_forms.rs::tests::writer_binary_of_annex_a_with_qos
Status: done — die XCDR2-Formen lesen ownership_strength als unsigned long; die klassische CDR-Struktur von eProsima liest 64 Bit. Der Test liest ein vorhandenes ownership_strength in einem XCDR2-Blob in beiden Byte-Reihenfolgen (ffa5e2770b1).
### Annex A OBJK_DataReader_Binary_Qos
Spec: Annex A, S. 110 — “@extensibility(FINAL) struct OBJK_DataReader_Binary_Qos : OBJK_Endpoint_Binary_Qos { @optional unsigned long timebasedfilter_msec; @optional string contentbased_filter; };”
Repo: crates/xrce-agent/src/daemon/binary_forms.rs (endpoint_qos,
EndpointQosBinary::timebasedfilter_msec, contentbased_filter);
crates/xrce-agent/src/daemon/entity_repr.rs (apply_endpoint_binary)
Tests: crates/xrce-agent/src/daemon/binary_forms.rs::tests::reader_binary_of_the_clause,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_clause_binary_reader_names_its_topic_and_qos,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_annex_b_binary_examples_read_as_their_qos
Status: done — Commits f548fee2522, b91241aebb1. timebasedfilter_msec wird als
unsigned long gelesen (Wert 50 im Test), contentbased_filter als string
(„x>100“ im Beispiel B.2.7). Die klassische CDR-Struktur von eProsima bleibt
als Rückfall.
Annex A OBJK_DataWriter_Binary
Spec: Annex A, S. 110–111 — “@extensibility(APPENDABLE) struct OBJK_DataWriter_Binary { string topic_name; @optonal OBJK_DataWriter_Binary_Qos qos; };”
Repo: crates/xrce-agent/src/daemon/binary_forms.rs (endpoint,
EndpointBinary); crates/xrce-agent/src/daemon/entity_repr.rs (endpoint)
Tests: crates/xrce-agent/src/daemon/binary_forms.rs::tests::writer_binary_of_annex_a_with_qos,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::an_annex_a_binary_writer_names_its_topic_and_qos,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_captured_binary_writer_is_reliable_keep_last_transient_local,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_blob_of_no_form_is_refused_naming_each_reading
Status: done — Commits f548fee2522, b91241aebb1. gelesen werden drei Formen in
dieser Reihenfolge: Annex A (DHEADER, topic_name, @optional qos), die Form
von §7.7.3.10.2 (ohne DHEADER, endpoint_qos als Pflichtfeld) und die
klassische CDR-Struktur von eProsima (ObjectId des Topics statt topic_name).
Ein Blob in keiner Form wird abgewiesen; die Meldung nennt das Ergebnis jeder
Form.
Annex A OBJK_DataReader_Binary
Spec: Annex A, S. 110 — “@extensibility(APPENDABLE) struct OBJK_DataReader_Binary { string topic_name; @optional OBJK_DataReader_Binary_Qos qos; };”
Repo: crates/xrce-agent/src/daemon/binary_forms.rs (endpoint mit
writer = false); crates/xrce-agent/src/daemon/entity_repr.rs (endpoint)
Tests: crates/xrce-agent/src/daemon/binary_forms.rs::tests::reader_binary_of_the_clause,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_clause_binary_reader_names_its_topic_and_qos,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_annex_b_binary_examples_read_as_their_qos,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_captured_binary_reader_is_reliable_keep_last_transient_local
Status: done — Commits f548fee2522, b91241aebb1. dieselben drei Formen wie beim
DataWriter; Annex A mit Filter ist durch B.2.7 gelesen, die Form der Klausel
durch den Test mit Tiefe 5 und timebasedfilter_msec 50.
Annex A ObjectVariant mit OBJK_AGENT und OBJK_CLIENT
Spec: Annex A, S. 111 — “@extensibility(FINAL) union ObjectVariant switch(ObjectKind) { // case OBJK_INVALID : indicates default or selected by Agent. No data. case OBJK_AGENT : AGENT_Representation client; case OBJK_CLIENT : CLIENT_Representation client; […] };”
Repo: crates/xrce/src/object_info.rs (ObjectConfig::Agent,
ObjectConfig::Client, ObjectInfo::config); crates/xrce-agent/src/daemon/session.rs
(agent_object_info, client_object_info)
Tests: crates/xrce/src/object_info.rs::tests::the_config_of_the_agent_is_its_agent_representation,
crates/xrce/src/submessages/get_info.rs::tests::client_info_follows_the_info_mask,
crates/xrce-agent/src/daemon/session.rs::tests::get_info_of_the_agent_checks_the_version_in_client_info
Status: done — Commits ca0cf7e08bf. die Fälle OBJK_AGENT und OBJK_CLIENT
stehen in ObjectConfig, dem config von ObjectInfo (INFO) und dem
client_info von GET_INFO; Kind-Oktett und Darstellung folgen aufeinander.
Die Aufzählung ObjectVariant für CREATE hat diese zwei Fälle nicht: eine
Darstellung mit Art Agent oder Client wird dort nicht gelesen. Beide Member
heißen in der IDL client; auf der Leitung hat das keine Wirkung.
Annex A ActivityInfoVariant mit case OBJECTID_AGENT
Spec: Annex A, S. 113 — “@extensibility(FINAL) union ActivityInfoVariant switch (ObjectKind) { case OBJECTID_AGENT : AGENT_ActivityInfo agent; case OBJK_DATAWRITER : […] case OBJK_DATAREADER : […] };”
Repo: crates/xrce/src/object_info.rs (ActivityInfoVariant,
ActivityInfoVariant::discriminator: Agent 0x0D, DataWriter 0x05, DataReader
0x06)
Tests: crates/xrce/src/object_info.rs::tests::agent_activity_info_has_a_dheader_and_a_locator_sequence,
crates/xrce/src/object_info.rs::tests::data_reader_activity_info_is_a_dheader_and_a_short,
crates/xrce/src/object_info.rs::tests::data_writer_activity_info_is_a_dheader_a_long_long_and_a_short
Status: done — Commits ca0cf7e08bf. der Diskriminator ist ein ObjectKind
(ein Oktett); OBJECTID_AGENT ist eine ObjectId aus zwei Oktetten und kein
Wert von ObjectKind, der Text von Annex A lässt sich nicht wörtlich nehmen.
Der Fall des Agent hat den Diskriminator OBJK_AGENT (0x0D). Die Member
tragen den DHEADER (AGENT_ActivityInfo: availability, address_seq als
TransportLocatorSeq).
Annex A FORMAT_MASK = 0x0E
Spec: Annex A, S. 114 — “const DataFormat FORMAT_MASK = 0x0E; // 0b0000 1110”
Repo: crates/xrce/src/submessages/write_data.rs
(DataFormat::FORMAT_MASK, DataFormat::from_flag_bits)
Tests: crates/xrce/src/submessages/write_data.rs::tests::write_data_rejects_reserved_format,
crates/xrce/src/submessages/write_data.rs::tests::data_format_raw_roundtrip,
crates/xrce/src/submessages/read_data.rs::tests::the_data_format_octet_has_the_values_of_annex_a
Status: done
Annex A SampleInfo mit SampleInfoDetail
Spec: Annex A, S. 114–115 — “typedef octet SampleInfoFormat; const SampleInfoFormat FORMAT_EMPTY = 0x00; […] FORMAT_SEQNUM = 0x01; […] FORMAT_TIMESTAMP = 0x02; […] FORMAT_SEQN_TIMS = 0x03; […] struct SeqNumberAndTimestamp { unsigned long sequence_number; unsigned long session_time_offset; }; union SampleInfoDetail switch(SampleInfoFormat) { case FORMAT_EMPTY: case FORMAT_SEQNUM: unsigned long sequence_number; case FORMAT_TIMESTAMP: unsigned long session_time_offset; case FORMAT_TIMESTAMP: SeqNumberAndTimestamp seqnum_n_timestamp; }; struct SampleInfo { SampleInfoFlags state; SampleInfoDetail detail; };”
Repo: crates/xrce/src/sample_info.rs (SampleInfo, info_format); crates/xrce/src/encoding.rs (SampleInfoForm)
Tests: crates/xrce/src/sample_info.rs::tests::the_union_of_annex_a_is_read_by_its_discriminator, crates/xrce/src/sample_info.rs::tests::the_flat_form_ignores_the_padding_octet
Status: done — SampleInfo ist der state mit der SampleInfoDetail-Union von Annex A: FORMAT_EMPTY, FORMAT_SEQNUM, FORMAT_TIMESTAMP, FORMAT_SEQN_TIMS. Die Union gibt den Fall FORMAT_TIMESTAMP zweimal an und lässt FORMAT_EMPTY in FORMAT_SEQNUM durchfallen; gelesen wird die gemeinte Form (nichts, Sequenznummer, Versatz, beide). FORMAT_SEQN_TIMS sind die 12 Oktette der flachen Struktur von §7.7.1 und der Bilder von Annex B.5.3 bis B.5.5, der Diskriminator im ersten Füll-Oktett. Vorgabe SampleInfoForm::AnnexA; die flache Form (sample_info: flat) ist für einen Client, der Nullen als Füllung sendet (die Union liest sie als FORMAT_EMPTY). 5c2466a4563.
### Annex A ACKNACK_Payload mit unsigned short
Spec: Annex A, S. 119 — “struct ACKNACK_Payload { unsigned short first_unacked_seq_num; octet nack_bitmap[2]; octet stream_id; };”
Repo: crates/xrce/src/submessages/acknack.rs (AckNackPayload,
encode_body, decode_body)
Tests: crates/xrce/src/submessages/acknack.rs::tests::acknack_le_roundtrip,
crates/xrce/src/submessages/acknack.rs::tests::acknack_be_roundtrip,
crates/xrce/tests/unannotated_types.rs::the_default_is_appendable_with_a_dheader,
crates/xrce/tests/unannotated_types.rs::the_final_setting_writes_the_reference_implementations_octets,
crates/xrce/src/reliable.rs::tests::acknack_retransmit_of_lost_sample_across_wrap
Status: done — Commits 7f85e76debd. §8.3.5.11.2 schreibt short; die Bytes des
Feldes sind gleich. Die Struktur trägt in Annex A kein @extensibility: sie
ist APPENDABLE und hat in der Vorgabe einen DHEADER (9 Oktette); die 5 Oktette
des Referenzagenten schreibt unannotated_types: final, beide Formen werden
gelesen. Der Code hält das Feld als i16 und rechnet mit SerialNumber16.
Annex A HEARTBEAT_Payload mit unsigned short
Spec: Annex A, S. 119 — “@extensibility(FINAL) struct HEARTBEAT_Payload { unsigned short first_unacked_seq_num; unsigned short last_unacked_seq_num; octet stream_id; };”
Repo: crates/xrce/src/submessages/heartbeat.rs (HeartbeatPayload,
encode_body, decode_body)
Tests: crates/xrce/src/submessages/heartbeat.rs::tests::heartbeat_le_roundtrip,
crates/xrce/src/submessages/heartbeat.rs::tests::heartbeat_be_roundtrip,
crates/xrce/src/reliable.rs::tests::heartbeat_window_across_wrap_reports_rfc1982_order
Status: done — die Struktur ist ausdrücklich @extensibility(FINAL), der
Rumpf hat 5 Oktette ohne DHEADER. §8.3.5.12.2 schreibt short first_unacked_seq_nr
und short last_unacked_seq_nr; die Bytes sind gleich.
Annex B Example Messages (Non-Normative)
Annex B.1 CREATE_CLIENT
Spec: Annex B.1, S. 121–122 — CREATE_CLIENT von vendor_id {0x0F, 0x0F},
client_key {0x22, 0x33, 0x44, 0x55}, session_id 0xDD; Header {0x80, 0x00,
0x00, 0x00}, Bytes 8–21 CLIENT_Representation, Byte 21 “properties? =
FALSE”.
Repo: crates/xrce/src/handshake.rs (ClientRepresentation::encode);
crates/xrce/src/submessages/create_client.rs (CreateClientPayload)
Tests: crates/xrce/src/submessages/create_client.rs::tests::annex_b_1_create_client_example_bytes,
crates/xrce/src/handshake.rs::tests::the_prose_form_has_a_time_t_after_the_vendor_id
Status: done — Commits be97b3247a6, f8bdf3cd878. der Test bildet Header und die
Bytes 8–21 nach. Der Text nennt request_id und client_timestamp, die das
Layout nicht enthält; mit der Einstellung representation_timestamps: present
schreibt der Code das Time_t des Textes, der zweite Test prüft diese Form mit
den Werten des Beispiels. Die Flags 0x07 („reuse, replace“) hat CREATE_CLIENT
nicht; submessageLength lautet „26 = 0x001B“, der Rumpf hat 14 Byte.
Annex B.2.1 DomainParticipant mit REPRESENTATION_BY_REFERENCE
Spec: Annex B.2.1, S. 123–125 — CREATE mit OBJK_PARTICIPANT,
REPRESENTATION_BY_REFERENCE, Referenz „MyLibrary::MyParticipant“ (25 Byte mit
NUL), domain_id 0.
Repo: crates/xrce/src/object_repr.rs (ObjectVariant::encode_for_kind,
ObjectVariant::decode_for_kind_at)
Tests: crates/xrce/src/object_repr.rs::tests::participant_representation_matches_the_captured_create_bytes
Status: n/a (informative) — Beispiel. Der Test prüft die Form aus dem
Mitschnitt von eProsima: Länge auf Byte 16–19, Zeichen ab Byte 20. Das Beispiel
setzt die Länge auf Byte 16–19 und die Zeichen auf Byte 24–48; Byte 20–23 sind
nicht erklärt, die Bytes des Beispiels liest der Code nicht. submessageLength
lautet 26, die Payload hat 44 Byte. Der Text verweist auf Table 20 statt
Table 18.
Annex B.2.2 DomainParticipant mit REPRESENTATION_IN_BINARY
Spec: Annex B.2.2, S. 125–127 — “Bytes 16-19 DHEADER of
OBJK_DomainParticipant_Binary (because extensibility is APPENDABLE) Encodes the
endianness and length […] 0x80000002 = {0x02, 0x00, 0x00, 0x80}”, danach zwei
Oktette für die @optional und domain_id.
Repo: crates/xrce/src/object_repr.rs (ObjectVariant::decode_for_kind_at);
crates/xrce-agent/src/daemon/binary_forms.rs (participant)
Tests: crates/xrce/src/object_repr.rs::tests::annex_b_2_2_participant_variant,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::a_spec_binary_participant_is_read
Status: done — Commits b91241aebb1, f548fee2522. der DHEADER 0x80000002 steht
an der Stelle, an der eProsima die Länge von binary_representation sendet;
der Code liest ihn dort als DHEADER (Bit 31 ist kein Teil der Länge), die zwei
@optional-Oktette und die domain_id danach.
Annex B.2.3 DataWriter mit REPRESENTATION_IN_BINARY
Spec: Annex B.2.3, S. 127–129 — DHEADER 0x8000000C, topic_name „Square“
(7 Byte mit NUL), qos? = 0, publisher_id {0xBB, 0xB3}.
Repo: crates/xrce/src/object_repr.rs (ObjectVariant::decode_for_kind_at);
crates/xrce-agent/src/daemon/binary_forms.rs (endpoint)
Tests: crates/xrce/src/object_repr.rs::tests::annex_b_2_3_writer_variant_reads_as_the_blob_and_its_publisher,
crates/xrce-agent/src/daemon/binary_forms.rs::tests::writer_binary_of_annex_a_with_qos
Status: done — Commits f548fee2522. der Blob mit topic_name und qos? = 0 und
die publisher_id danach werden gelesen. Der Text nennt den Publisher
subscriber_id.
Annex B.2.4 DataWriter mit QoS
Spec: Annex B.2.4, S. 129–132 — “RELIABILITY policy set to BEST_EFFORT,
HISTORY policy set to KEEP_ALL and DEADLINE policy set to a period of 2
minutes”; “qos_flags = 0x0003 Indicates the flags for is_reliable and
is_history_keep_all are both set.”; Byte 34 history_depth?, Byte 35
Füllung, Byte 36–39 deadline = 120000.
Repo: crates/xrce/src/object_repr.rs (ObjectVariant::decode_for_kind_at);
crates/xrce-agent/src/daemon/entity_repr.rs (endpoint)
Tests: crates/xrce/src/object_repr.rs::tests::annex_b_2_4_writer_with_qos_in_both_readings_of_the_padding,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_annex_b_binary_examples_read_as_their_qos,
crates/xrce-agent/src/daemon/binary_forms.rs::tests::writer_binary_of_annex_a_with_qos
Status: done — Commits b91241aebb1. gelesen als XCDR2 der gedruckten IDL. Byte 35,
das die Tabelle Füllung nennt, ist das Oktett für @optional deadline_msec
(1); der Wert beginnt auf Byte 36. Das Füllbyte 43 vor publisher_id wird
sowohl im DHEADER gezählt (24) als auch außerhalb (23) gelesen. Der Text nennt
BEST_EFFORT, qos_flags 0x0003 und die Tabelle setzen is_reliable; gelesen
werden die Bytes.
Annex B.2.5 DataWriter mit REPRESENTATION_AS_XML_STRING
Spec: Annex B.2.5, S. 132–134 — <data_writer name="MyWriter" topic_ref="Square"><data_writer_qos base_name="MyQosLib::MyProfile"> <deadline>[...]</deadline></data_writer_qos></data_writer>, Länge 181,
publisher_id auf Byte 201–202.
Repo: crates/xrce-agent/src/daemon/entity_repr.rs (endpoint_from_xml:
topic_ref als Name, <data_writer_qos> und <datawriter_qos> mit
base_name)
Tests: crates/xrce-agent/src/daemon/session.rs::tests::a_data_writer_states_its_qos_over_a_profile
Status: n/a (informative) — Beispiel. Der Code löst topic_ref="Square"
als Name auf und liest <data_writer_qos base_name="…"> über einem Profil des
Agenten (9d5c64dc398); der Test hat die Form des Beispiels, nicht seine Bytes.
Im Bild ist der Diskriminator 0x01, in Table 22 0x02; der Text nennt 180 und 181
Zeichen und „MyQosLib:MyProfile“ mit einem Doppelpunkt.
Annex B.2.6 DataReader mit REPRESENTATION_IN_BINARY
Spec: Annex B.2.6, S. 134–136 — DataReader „Square“ mit DHEADER,
topic_name, qos? = 0, subscriber_id {0xCC, 0xC4}.
Repo: crates/xrce/src/object_repr.rs (ObjectVariant::decode_for_kind_at);
crates/xrce-agent/src/daemon/entity_repr.rs (endpoint)
Tests: crates/xrce/src/object_repr.rs::tests::annex_b_2_6_reader_with_default_qos,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_annex_b_binary_examples_read_as_their_qos
Status: done — Commits b91241aebb1. gelesen wird der DHEADER 12 (0x8000000C
wie bei B.2.3). Der Text druckt den DHEADER als {0xB5, 0x00, 0x00, 0x00}; das
passt nicht zu den 26 Oktetten der Nachricht, der Code weist den gedruckten Wert
ab. Table 23 setzt den Diskriminator auf 0x05 (OBJK_DATAWRITER) für
OBJK_DATAREADER (0x06) und führt Byte 24–30 zweimal.
Annex B.2.7 DataReader mit QoS und Filter
Spec: Annex B.2.7, S. 136–139 — “HISTORY policy set to KE EP_ALL and
DEADLINE policy set to a period of 5 minutes”, qos_flags 0x0002, deadline
180000, contentbased_filter „x>100“.
Repo: crates/xrce/src/object_repr.rs (ObjectVariant::decode_for_kind_at);
crates/xrce-agent/src/daemon/entity_repr.rs (endpoint)
Tests: crates/xrce/src/object_repr.rs::tests::annex_b_2_7_reader_with_qos_and_filter,
crates/xrce-agent/src/daemon/entity_repr.rs::tests::the_annex_b_binary_examples_read_as_their_qos
Status: done — Commits b91241aebb1. gelesen als XCDR2 der gedruckten IDL; Byte 35
ist das Oktett für deadline_msec, vor der subscriber_id steht kein Füllbyte.
180000 ms sind 3 Minuten (gelesen), der Text nennt 5; Bild und Table 24 nennen
am Ende publisher_id statt subscriber_id.
Annex B.3.1 WRITE_DATA mit einem Sample
Spec: Annex B.3.1, S. 139–141 — flags 0x01, submessageLength 6, Byte 8–13
{0xAA, 0x01, 0x44, 0x05, 0x19, 0x00}.
Repo: crates/xrce/src/submessages/write_data.rs (WriteDataPayload)
Tests: crates/xrce/src/submessages/write_data.rs::tests::write_data_matches_the_annex_b_example
Status: done — der Test bildet flags, Länge und Rumpf Byte für Byte nach.
Table 25 heißt „READ_DATA (single sample)“.
Annex B.3.2 WRITE_DATA mit einer Folge ohne SampleInfo
Spec: Annex B.3.2, S. 141–143 — flags 0x09, data_seq.length = 4, vier
short {0x14, 0x00}, {0x11, 0x00}, {0x1A, 0x00}, {0x24, 0x00}.
Repo: crates/xrce/src/submessages/write_data.rs; crates/xrce/src/submessages/data.rs; crates/xrce/src/submessages/read_data.rs; crates/xrce/src/sample_info.rs
Tests: crates/xrce/tests/annex_b_examples.rs::b_3_2_write_data_with_a_sequence_without_sample_info
Status: done — das Beispiel ist mit seinen Bytes getestet: Kennung 0x07, flags 0x09, Länge 16 (das Bild nennt die Länge 6 von B.3.1), vier Werte 20, 17, 26, 36 (5c2466a4563). ### Annex B.3.3 WRITE_DATA mit Zeitstempel
Spec: Annex B.3.3, S. 143–146 — “Byte 12 info.state = 0x00 […] Byte 13 info.detail.discriminator = FORMAT_TIMESTAMP Bytes 14-15 padding Bytes 16-19 info. Detail.session_time_offset Bytes 20-21 serialized_data”.
Repo: —
Tests: —
Status: n/a (informative) — Beispiel in der Form von Annex A mit
SampleInfoDetail. Die Form von Annex A ist im Item „Annex A SampleInfo mit
SampleInfoDetail“ geführt. submessageLength lautet „13 = 0x000D“ mit {0x06, 0x00},
der Rumpf hat 14 Byte.
Annex B.3.4 WRITE_DATA mit einem disposed Sample
Spec: Annex B.3.4, S. 146–148 — “Byte 12 info.state = 0x02 […] Byte 13 Info.detail.discriminator = FORMAT_NONE […] Bytes 14-19 Serialized_data”.
Repo: —
Tests: —
Status: n/a (informative) — Beispiel in der Form von Annex A (wie B.3.3). Bild und Table nennen FORMAT_EMPTY und
FORMAT_NONE; submessageLength lautet 6, der Rumpf hat 12 Byte.
Annex B.4.1 READ_DATA für ein Sample
Spec: Annex B.4.1, S. 148–150 — “submessageId = READ_DATA = 0x07”, flags
0x01, “submessageLength = 7”, Byte 12 preferred_stream_id 0x00, Byte 13
data_format 0x00, Byte 14 und 15 die Oktette für @optional = 0.
Repo: crates/xrce/src/submessages/write_data.rs; crates/xrce/src/submessages/data.rs; crates/xrce/src/submessages/read_data.rs; crates/xrce/src/sample_info.rs
Tests: crates/xrce/tests/annex_b_examples.rs::b_4_1_read_data_for_a_sample
Status: done — das Beispiel ist mit allen acht Oktetten der Payload getestet; Kennung 0x08 (das Bild nennt 0x07), Länge 8 (das Bild nennt 7) (5c2466a4563). ### Annex B.4.2 READ_DATA mit Filter und DataDeliveryControl
Spec: Annex B.4.2, S. 150–153 — data_format 0x08, content_filter
„x>100“ mit Länge 6, DHEADER 0x80000008, max_samples 100,
max_elapsed_time 30000, max_rate 1024 „{0x00, 0x40}“, min_pace_period
1000.
Repo: crates/xrce/src/submessages/read_data.rs (ReadDataPayload,
ReadSpecification, DataDeliveryControl)
Tests: crates/xrce/src/submessages/read_data.rs::tests::annex_b_4_2_read_data_with_filter_and_delivery_control,
crates/xrce/src/submessages/read_data.rs::tests::the_content_filter_is_a_string_with_a_nul_and_an_aligned_length
Status: done — Commits b589558e671. data_format 0x08 (FORMAT_DATA_SEQ),
content_filter_expression als XCDR2-String, DataDeliveryControl mit DHEADER;
der Test liest die Bytes des Bildes (Bit 31 des DHEADER zählt nicht zur Länge)
und schreibt den einfachen DHEADER 8. Table 30 legt DHEADER und max_samples
beide auf Byte 28–29; für 1024 druckt der Text {0x00, 0x40}, little-endian ist
es {0x00, 0x04}; Byte 14 und Byte 26 heißen „set to FALSE indicating there it
is present“. Die Form ohne
DHEADER schreibt XrceClient::set_delivery_control_form(DeliveryControlForm::Bare).
Annex B.5.1 DATA mit einem Sample
Spec: Annex B.5.1, S. 154–155 — flags 0x00 (big-endian),
submessageLength 8, FooType.count = 19 als {0x00, 0x00, 0x00, 0x13}.
Repo: crates/xrce/src/submessages/write_data.rs; crates/xrce/src/submessages/data.rs; crates/xrce/src/submessages/read_data.rs; crates/xrce/src/sample_info.rs
Tests: crates/xrce/tests/annex_b_examples.rs::b_5_1_data_with_one_sample
Status: done — das Beispiel (Big-Endian, flags 0x00) ist mit seinen Bytes dekodiert und erneut kodiert (5c2466a4563).
### Annex B.5.2 DATA mit einer Folge ohne SampleInfo
Spec: Annex B.5.2, S. 155–157 — submessageLength 16, data_seq.length = 2,
zwei long.
Repo: crates/xrce/src/submessages/write_data.rs; crates/xrce/src/submessages/data.rs; crates/xrce/src/submessages/read_data.rs; crates/xrce/src/sample_info.rs
Tests: crates/xrce/tests/annex_b_examples.rs::b_5_2_data_with_a_sequence_without_sample_info
Status: done — das Beispiel ist getestet: Kennung 0x09 (das Bild nennt 0x08), flags 0x08 (E-Flag gelöscht, FORMAT_DATA_SEQ; das Bild nennt 0x00), sequenceNr {0x0A,0x00} = 10 (der Text nennt 1), request_id {AA,01} nach der Tabelle (der Text nennt {AA,02}) (5c2466a4563).
### Annex B.5.3 DATA mit einem Sample und SampleInfo
Spec: Annex B.5.3, S. 157–159 — IDL mit SampleInfoDetail; Bild: “info.state
| info.sequence_number | info.session_time_offset | XCDR_Serialization(foo)”.
Repo: crates/xrce/src/submessages/data.rs (DataPayloadSample);
crates/xrce/src/sample_info.rs (SampleInfo)
Tests: crates/xrce/src/submessages/data.rs::tests::data_sample_matches_annex_b_5_3_layout,
crates/xrce/src/sample_info.rs::tests::sample_info_matches_annex_b_5_3_layout,
crates/xrce-agent/src/daemon/session.rs::tests::a_read_for_sample_is_answered_with_a_sample_each
Status: done — die Tests bilden das Bild des Beispiels nach. Das Bild hat
die Form von §7.7.1, die IDL darüber die von Annex A (Item „Annex A
SampleInfo mit SampleInfoDetail“).
Annex B.5.4 DATA mit einer Folge mit SampleInfo
Spec: Annex B.5.4, S. 159–161 — submessageLength 40, sample_seq.length
= 2, je Element info (12 Byte) und data (4 Byte).
Repo: crates/xrce/src/submessages/write_data.rs; crates/xrce/src/submessages/data.rs; crates/xrce/src/submessages/read_data.rs; crates/xrce/src/sample_info.rs
Tests: crates/xrce/tests/annex_b_examples.rs::b_5_4_data_with_a_sequence_with_sample_info
Status: done — das Beispiel ist mit den 12 Oktetten der SampleInfo je Element getestet (Länge 40; flags 0x0A statt 0x00; SampleInfoForm::Flat) (5c2466a4563).
### Annex B.5.5 DATA mit PackedSamples
Spec: Annex B.5.5, S. 161–163 — submessageLength 36, info_base (12
Byte), sample_delta_seq.length = 2, je Element info_delta (4 Byte) und
data (4 Byte).
Repo: crates/xrce/src/submessages/write_data.rs; crates/xrce/src/submessages/data.rs; crates/xrce/src/submessages/read_data.rs; crates/xrce/src/sample_info.rs
Tests: crates/xrce/tests/annex_b_examples.rs::b_5_5_data_with_packed_samples
Status: done — das Beispiel ist nach dem Bild getestet: request_id/object_id, info_base (12), Anzahl, zwei SampleInfoDelta mit Daten, 36 Oktette; Table 34 listet info_base auf Byte 8 bis 19 ohne request_id und object_id, was zu keinem von beiden passt (5c2466a4563).
Annex C Additional Transport Mappings
Annex C.1 Rahmen nach RFC 1662 für serielle Leitungen
Spec: Annex C.1, S. 165 — “This section normalizes the communication over serial protocols such as SPI, I2C or RS-232. For this propose, the XRCE Messages are framed using an HDLC-like framing similar to [IETF RFC-1662]. This framing is designed to meet all the functionality listen in clause 11.1, except that it does not provide security.”
Repo: crates/xrce/src/transport_serial.rs (encode_frame_with, SerialFramer);
crates/xrce-agent/src/daemon/transport.rs (SerialLine::take_frame, serial::run_serial_listener,
Feature serial)
Tests: crates/xrce/src/transport_serial.rs::tests::the_framer_takes_frames_split_and_back_to_back_and_skips_noise,
crates/xrce-agent/src/daemon/transport.rs::tests::the_clients_of_a_serial_line_are_told_apart_by_their_address
Status: done — Commits 8dae8498ba1. Rahmen nach C.1.1 bis C.1.3 in
zerodds-xrce, im Agent und in den Endpoint-SDKs (C, C++, Java, Python,
Ada-native). Micro-XRCE-DDS 3.0.1 rahmt ebenso, rechnet frameCheck aber als
CRC-16/ARC nur über die Payload (StreamFramingProtocol.cpp,
stream_framing_protocol.c, aus dem Quelltext gelesen); der Agent nimmt und
erzeugt diese Rahmen mit frame_check: crc16-arc-payload
(FrameCheck::Crc16ArcPayload). Nicht gegen einen Micro-XRCE-DDS-Client über
eine Leitung gemessen.
Annex C.1.1 Aufbau des Rahmens
Spec: Annex C.1.1, S. 165 — “flag | sourceAddress | remoteAddress |
payloadLength | payload (up to 64KB) | frameCheck”, je ein Oktett für flag und
die beiden Adressen, 16 Bit für payloadLength und frameCheck.
Repo: crates/xrce/src/transport_serial.rs (encode_frame_with, FrameAssembler::push)
Tests: crates/xrce/src/transport_serial.rs::tests::a_frame_carries_the_addresses_the_length_and_a_little_endian_check
Status: done — 7E | sourceAddress | remoteAddress | payloadLength | payload | frameCheck; der Rahmen endet nach payloadLength Oktetten Payload
und zwei Oktetten frameCheck.
Annex C.1.1.1 BEGIN_FLAG 0x7E
Spec: Annex C.1.1.1, S. 165 — “Each frame begins with a BEGIN_FLAG byte which has a hexadecimal value of 0x7E.”
Repo: crates/xrce/src/transport_serial.rs (FLAG_BYTE, encode_frame_with)
Tests: crates/xrce/src/transport_serial.rs::tests::a_frame_carries_the_addresses_the_length_and_a_little_endian_check
Status: done
Annex C.1.1.2 sourceAddress
Spec: Annex C.1.1.2, S. 165 — “The sourceAddress indicates the address of the frame sender.”
Repo: crates/xrce/src/transport_serial.rs (SerialFrame::source); crates/xrce-agent/src/daemon/transport.rs (PeerTable::resolve_on_line,
bind_line)
Tests: crates/xrce-agent/src/daemon/transport.rs::tests::the_clients_of_a_serial_line_are_told_apart_by_their_address
Status: done — der Agent sendet mit seiner Adresse (address:, Vorgabe 0,
die Adresse, an die die Micro-XRCE-DDS-Beispiele senden). Ein Rahmen gehört dem
Client, den sein Header oder CREATE_CLIENT nennt, sonst dem, der sich von seiner
sourceAddress registriert hat.
Annex C.1.1.3 remoteAddress
Spec: Annex C.1.1.3, S. 165 — “The remoteAddress indicates the address of the frame recipient.”
Repo: crates/xrce/src/transport_serial.rs (SerialFrame::remote); crates/xrce-agent/src/daemon/transport.rs (SerialLine::take_frame,
Route::Serial)
Tests: crates/xrce-agent/src/daemon/transport.rs::tests::the_clients_of_a_serial_line_are_told_apart_by_their_address
Status: done — der Agent nimmt nur Rahmen an seine Adresse; seine Nachrichten an einen Client tragen dessen Adresse.
Annex C.1.1.4 payloadLength little-endian
Spec: Annex C.1.1.4, S. 166 — “The payloadLength indicates the length of the payload field in bytes, that is, the XRCE Message. The payloadLength shall be encoded using little endian format.”
Repo: crates/xrce/src/transport_serial.rs (encode_frame_with, FrameAssembler::push)
Tests: crates/xrce/src/transport_serial.rs::tests::a_frame_carries_the_addresses_the_length_and_a_little_endian_check
Status: done
Annex C.1.1.5 payload ist eine XRCE-Nachricht
Spec: Annex C.1.1.5, S. 166 — “The payload shall contain an XRCE Message.”
Repo: crates/xrce/src/transport_serial.rs (encode_message, decode_frame,
SerialFramer::push_bytes)
Tests: crates/xrce/src/transport_serial.rs::tests::the_framer_takes_frames_split_and_back_to_back_and_skips_noise,
crates/xrce/src/transport_serial.rs::tests::decode_frame_returns_the_rest_after_the_frame
Status: done — die Grenze ist 65 535 Oktette, was payloadLength fasst;
eine längere Payload weist encode_frame mit FrameTooLong ab.
Annex C.1.1.6 frameCheck nach RFC 1662
Spec: Annex C.1.1.6, S. 166 — “The frameCheck shall contain the 16-bits cyclic redundancy check (CRC) of the original frame without including the BEGIN_FLAG or transparency stuffing. The frameCheck shall be computed as it is described in [IETF RFC-1662] using the polynomials: x 16 + x 12 + x 5 + 1.”
Repo: crates/xrce/src/transport_serial.rs (fcs16, FrameCheck::compute)
Tests: crates/xrce/src/transport_serial.rs::tests::the_frame_check_is_the_fcs16_of_rfc_1662,
crates/xrce/src/transport_serial.rs::tests::a_frame_carries_the_addresses_the_length_and_a_little_endian_check
Status: done — FCS-16 nach RFC 1662 (gespiegelt 0x8408, Init 0xFFFF,
komplementiert) über Adressen, payloadLength und Payload; 0x906E für
„123456789“, der Prüfwert aus RFC 1662 Anhang C.
Annex C.1.1.6 frameCheck little-endian
Spec: Annex C.1.1.6, S. 166 — “The frameCheck shall be encoded using little endian format.”
Repo: crates/xrce/src/transport_serial.rs (encode_frame_with)
Tests: crates/xrce/src/transport_serial.rs::tests::a_frame_carries_the_addresses_the_length_and_a_little_endian_check
Status: done
Annex C.1.2 Stopfen mit ESCAPE_FLAG und XOR_FLAG
Spec: Annex C.1.2, S. 166 — “The ESCAPE_FLAG has a hexadecimal value of 0x7D. Each byte inside the frame which value matches with the BEGIN_FLAG or the ESCAPE_FLAG is replaced by two bytes: the ESCAPE_FLAG followed by the original byte XOR with the XOR_FLAG which has a value of 0x20. […] each ESCAPE_FLAG found shall be discarded and an XOR with the XOR_FLAG operator shall be applied on the next byte.”
Repo: crates/xrce/src/transport_serial.rs (ESCAPE_BYTE, STUFF_XOR, encode_frame_with,
FrameAssembler::push)
Tests: crates/xrce/src/transport_serial.rs::tests::flag_and_escape_octets_are_stuffed_everywhere_after_the_flag,
crates/xrce/src/transport_serial.rs::tests::escape_errors_and_short_frames_are_refused
Status: done — gestopft wird alles nach dem Flag, auch Adressen, Länge und
frameCheck. Nach 0x7D weist der Code jedes Byte ab, das nicht zu 0x7E oder
0x7D wird; die Spec verlangt das nicht.
Annex C.1.3 Verwerfen bei falscher CRC
Spec: Annex C.1.3, S. 166 — “A frame shall be dropped in the following cases: When the frameCheck attached to the frame is not the same as the computed CRC.”
Repo: crates/xrce/src/transport_serial.rs (FrameAssembler::push); crates/xrce-agent/src/daemon/transport.rs
(run_serial_listener: Meldung „frame dropped“ mit dem Grund)
Tests: crates/xrce/src/transport_serial.rs::tests::a_frame_with_a_wrong_check_is_refused,
crates/xrce/src/transport_serial.rs::tests::the_frame_check_of_micro_xrce_dds_is_taken_when_chosen
Status: done
Annex C.1.3 Verwerfen bei BEGIN_FLAG vor dem Ende der Payload
Spec: Annex C.1.3, S. 166 — “When a (non escaped) BEGIN_FLAG is found before the payload is completely read.”
Repo: crates/xrce/src/transport_serial.rs (SerialFramer::push_bytes, decode_frame_inner_with)
Tests: crates/xrce/src/transport_serial.rs::tests::a_begin_flag_inside_a_frame_drops_it_and_begins_the_next
Status: done — der Rahmen wird mit BeginFlagInFrame verworfen, und das
Flag beginnt den nächsten Rahmen.
Audit-Status
490 done / 0 partial / 2 open / 0 blocked / 77 n/a (informative).
Formen anderer DDS-Produkte in DDS-XML: die Leser von crates/xml folgen den Schemas von DDS-XML 1.0 und weisen eine fremde Form ab (<domainparticipant_qos>, das Attribut qos_profile_ref, baseType, die IDL-Namen long und octet als type, und weitere), mit einem Fehler, der die Form und die der Spec nennt. Die Agent-Einstellung vendor_forms: accept liest sie (nötig für Profildateien von eProsima) und listet beim Start jede gelesene Form; Standard ist refuse. Geprüft ist das nur durch Lesen des Codes und der Tests; kein Lauf auf diesem Rechner.
Offene Punkte: dds-xrce-1.0.open.md.