rsomeip/endpoint/command.rs
1use crate::{
2 endpoint::{Error, Result},
3 someip::Message,
4};
5use std::net::SocketAddr;
6use tokio::sync::mpsc;
7
8#[cfg(test)]
9mod tests;
10
11/// Provides asynchronous control over a SOME/IP endpoint.
12pub struct Controller {
13 tx: mpsc::Sender<Command>,
14}
15
16impl Controller {
17 /// Creates a new [`Controller`].
18 pub fn new(sender: mpsc::Sender<Command>) -> Self {
19 Self { tx: sender }
20 }
21
22 /// Requests that the endpoint connects to the given target.
23 ///
24 /// # Errors
25 ///
26 /// Returns an error if the endpoint failed to connect to the target.
27 pub async fn connect(&self, target: SocketAddr) -> Response {
28 self.request(Request::Connect(target)).await
29 }
30
31 /// Requests that the endpoint disconnects from the given target.
32 ///
33 /// # Errors
34 ///
35 /// Returns an error if the endpoint failed to disconnect from the target.
36 pub async fn disconnect(&self, target: SocketAddr) -> Response {
37 self.request(Request::Disconnect(target)).await
38 }
39
40 /// Requests that the endpoint sends the message to the destination.
41 ///
42 /// # Errors
43 ///
44 /// Returns an error if the message could not be sent, either from a serialization error or
45 /// connection issue.
46 pub async fn send(&self, msg: Message, dst: SocketAddr) -> Response {
47 self.request(Request::Send { msg, dst }).await
48 }
49
50 /// Requests that the endpoint relay messages with the given message id.
51 ///
52 /// # Errors
53 ///
54 /// Returns an error if the relay could not be set.
55 pub async fn relay(&self, id: u32, tx: mpsc::Sender<Result<Message>>) -> Response {
56 self.request(Request::Relay { id, tx }).await
57 }
58
59 /// Requests the endpoint to shut down.
60 ///
61 /// # Errors
62 ///
63 /// Returns an error if the endpoint failed to shutdown.
64 pub async fn shutdown(&self) -> Response {
65 self.request(Request::Shutdown).await
66 }
67
68 /// Sends a request to the endpoint and awaits the response.
69 ///
70 /// # Errors
71 ///
72 /// Returns an error if the request could not be sent to the endpoint, or if the response could
73 /// not be received.
74 async fn request(&self, request: Request) -> Response {
75 let (tx, mut rx) = mpsc::channel(1);
76 self.tx
77 .send(Command { request, tx })
78 .await
79 .map_err(|_| Error::Failure("could not send request"))?;
80 rx.recv()
81 .await
82 .ok_or(Error::Failure("could not receive response"))?
83 }
84}
85
86/// Encapsulates a Request with a channel for sending the Response.
87pub struct Command {
88 request: Request,
89 tx: mpsc::Sender<Response>,
90}
91
92impl Command {
93 /// Consumes the command to return the response channel and the request.
94 pub fn into_parts(self) -> (Request, mpsc::Sender<Response>) {
95 (self.request, self.tx)
96 }
97}
98
99/// Operations that an endpoint can be requested to perform.
100#[derive(Debug)]
101pub enum Request {
102 /// Requests that the endpoint connects to the given address.
103 Connect(SocketAddr),
104 /// Requests that the endpoint disconnects from the given address.
105 Disconnect(SocketAddr),
106 /// Requests that the endpoint sends the message to the destination.
107 Send { msg: Message, dst: SocketAddr },
108 /// Requests that the endpoint relay messages with the given message id.
109 Relay {
110 id: u32,
111 tx: mpsc::Sender<Result<Message>>,
112 },
113 /// Requests the endpoint to shut down.
114 Shutdown,
115}
116
117/// A response to a [`Request`].
118pub type Response = Result<()>;