ara_com/transport.rs
1use crate::error::AraComError;
2use crate::types::*;
3use async_trait::async_trait;
4use bytes::Bytes;
5
6/// SOME/IP message header carrying routing metadata.
7///
8/// Every message exchanged over a [`Transport`] is paired with a header that
9/// identifies the target service, method, and instance. The transport layer
10/// uses this information to route the message and correlate request/response
11/// pairs via `session_id`.
12#[derive(Debug, Clone)]
13pub struct MessageHeader {
14 /// Target service identifier.
15 pub service_id: ServiceId,
16 /// Target method or event identifier.
17 pub method_id: MethodId,
18 /// Target service instance.
19 pub instance_id: InstanceId,
20 /// Session identifier for request/response correlation.
21 /// Transports typically assign this automatically; set to `0` in
22 /// outgoing calls and let the transport fill it in.
23 pub session_id: u16,
24 /// Discriminates request, response, notification, and error frames.
25 pub message_type: MessageType,
26 /// SOME/IP return code (meaningful in responses and errors).
27 pub return_code: ReturnCode,
28}
29
30/// SOME/IP message type discriminator (PRS_SOMEIP_00055).
31#[derive(Debug, Clone, Copy, PartialEq, Eq)]
32pub enum MessageType {
33 /// Client-to-server request expecting a [`Response`](MessageType::Response).
34 Request,
35 /// Client-to-server fire-and-forget (no response expected).
36 RequestNoReturn,
37 /// Server-to-client event notification (unsolicited).
38 Notification,
39 /// Server-to-client response to a [`Request`](MessageType::Request).
40 Response,
41 /// Server-to-client error response.
42 Error,
43}
44
45/// SOME/IP return code (PRS_SOMEIP_00058).
46///
47/// Carried in response and error messages to indicate success or the reason
48/// for failure.
49#[derive(Debug, Clone, Copy, PartialEq, Eq)]
50#[repr(u8)]
51pub enum ReturnCode {
52 /// No error.
53 Ok = 0x00,
54 /// Unspecified error.
55 NotOk = 0x01,
56 /// The requested service is not known.
57 UnknownService = 0x02,
58 /// The requested method/event is not known.
59 UnknownMethod = 0x03,
60 /// The service is registered but not yet ready.
61 NotReady = 0x04,
62 /// The service instance is not reachable (network-level).
63 NotReachable = 0x05,
64 /// The request timed out on the server side.
65 Timeout = 0x06,
66 /// Protocol version mismatch.
67 WrongProtocolVersion = 0x07,
68 /// Interface version mismatch.
69 WrongInterfaceVersion = 0x08,
70 /// The message payload could not be parsed.
71 MalformedMessage = 0x09,
72 /// The message type is not valid in this context.
73 WrongMessageType = 0x0A,
74}
75
76/// Serialization trait for AUTOSAR-compatible wire format encoding.
77///
78/// All primitive types, `String`, and `Vec<T>` implement this trait using
79/// big-endian byte order and SOME/IP length-prefix conventions.
80/// Generated struct types receive an implementation from `cargo-arxml`.
81pub trait AraSerialize: Send + Sync {
82 /// Append the wire-format bytes of `self` to `buf`.
83 fn ara_serialize(&self, buf: &mut Vec<u8>) -> Result<(), AraComError>;
84 /// Return the exact number of bytes that [`ara_serialize`](AraSerialize::ara_serialize)
85 /// will append.
86 fn serialized_size(&self) -> usize;
87}
88
89/// Deserialization trait for AUTOSAR-compatible wire format decoding.
90///
91/// Counterpart to [`AraSerialize`]. Implementations consume bytes from the
92/// front of `buf` and return the decoded value.
93pub trait AraDeserialize: Sized + Send + Sync {
94 /// Decode a value from the beginning of `buf`.
95 fn ara_deserialize(buf: &[u8]) -> Result<Self, AraComError>;
96}
97
98/// Async transport backend trait.
99///
100/// This is the primary extension point of `ara-com`. Transport backends
101/// (such as `ara-com-someip`) implement this trait to provide the actual
102/// network I/O. Generated proxy and skeleton code interacts with the
103/// transport exclusively through this interface.
104///
105/// # Instance binding invariant
106///
107/// A transport enforces **one instance per service per transport**: once a
108/// service ID is bound to an instance (via [`offer_service`](Transport::offer_service),
109/// [`find_service`](Transport::find_service), or
110/// [`subscribe_event_group`](Transport::subscribe_event_group)), attempting
111/// to bind a *different* instance for the same service on the same transport
112/// must return an error.
113#[async_trait]
114pub trait Transport: Send + Sync + 'static {
115 /// Send a request and wait for a response
116 async fn send_request(
117 &self,
118 header: MessageHeader,
119 payload: Bytes,
120 ) -> Result<(MessageHeader, Bytes), AraComError>;
121
122 /// Send a fire-and-forget message
123 async fn send_fire_and_forget(
124 &self,
125 header: MessageHeader,
126 payload: Bytes,
127 ) -> Result<(), AraComError>;
128
129 /// Send a notification/event
130 async fn send_notification(
131 &self,
132 header: MessageHeader,
133 payload: Bytes,
134 ) -> Result<(), AraComError>;
135
136 /// Offer a service instance (skeleton side)
137 async fn offer_service(
138 &self,
139 service_id: ServiceId,
140 instance_id: InstanceId,
141 major_version: MajorVersion,
142 minor_version: MinorVersion,
143 ) -> Result<(), AraComError>;
144
145 /// Stop offering a service
146 async fn stop_offer_service(
147 &self,
148 service_id: ServiceId,
149 instance_id: InstanceId,
150 ) -> Result<(), AraComError>;
151
152 /// Find a service instance (proxy side)
153 async fn find_service(
154 &self,
155 service_id: ServiceId,
156 instance_id: InstanceId,
157 major_version: MajorVersion,
158 minor_version: MinorVersion,
159 ) -> Result<ServiceInstanceId, AraComError>;
160
161 /// Register a handler for incoming requests (skeleton side)
162 async fn register_request_handler(
163 &self,
164 service_id: ServiceId,
165 instance_id: InstanceId,
166 handler: Box<
167 dyn Fn(
168 MessageHeader,
169 Bytes,
170 )
171 -> futures_core::future::BoxFuture<'static, Result<Bytes, AraComError>>
172 + Send
173 + Sync,
174 >,
175 ) -> Result<(), AraComError>;
176
177 /// Subscribe to an event group
178 async fn subscribe_event_group(
179 &self,
180 service_id: ServiceId,
181 instance_id: InstanceId,
182 event_group_id: EventGroupId,
183 ) -> Result<(), AraComError>;
184
185 /// Unsubscribe from an event group
186 async fn unsubscribe_event_group(
187 &self,
188 service_id: ServiceId,
189 instance_id: InstanceId,
190 event_group_id: EventGroupId,
191 ) -> Result<(), AraComError>;
192}