message_io/network/
endpoint.rs

1use super::resource_id::{ResourceId};
2
3use std::net::{SocketAddr};
4
5/// Information to identify the remote endpoint.
6/// The endpoint is used mainly as a connection identified.
7#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
8pub struct Endpoint {
9    resource_id: ResourceId,
10    addr: SocketAddr,
11}
12
13impl Endpoint {
14    /// Creates a new Endpoint to use in non connection oriented protocols.
15    ///
16    /// For non connection-oriented protocols, as *UDP*, the endpoint can be created manually
17    /// from a **listener resource** to send messages to different address without
18    /// creating a connection.
19    ///
20    /// For connection oriented protocol, creating manually an endpoint is not allowed.
21    ///
22    /// # Example
23    /// ```rust
24    /// use message_io::node::{self, NodeEvent};
25    /// use message_io::network::{Transport, Endpoint, NetEvent};
26    ///
27    /// let (handler, listener) = node::split::<()>();
28    /// handler.signals().send_with_timer((), std::time::Duration::from_secs(1)); //timeout
29    ///
30    /// let listen_addr = "127.0.0.1:0";
31    /// let (receiver_id_1, addr_1) = handler.network().listen(Transport::Udp, listen_addr).unwrap();
32    /// let (receiver_id_2, addr_2) = handler.network().listen(Transport::Udp, listen_addr).unwrap();
33    /// let (sender_id, _) = handler.network().listen(Transport::Udp, listen_addr).unwrap();
34    ///
35    /// //addr_1 and addr_2 contain the addresses with the listening ports.
36    /// handler.network().send(Endpoint::from_listener(sender_id, addr_1), &[23]);
37    /// handler.network().send(Endpoint::from_listener(sender_id, addr_2), &[42]);
38    ///
39    /// let (mut msg_1, mut msg_2) = (0, 0);
40    /// listener.for_each(|event| match event {
41    ///     NodeEvent::Signal(_) => handler.stop(),
42    ///     NodeEvent::Network(net_event) => match net_event {
43    ///         NetEvent::Message(endpoint, message) => match endpoint.resource_id() {
44    ///             id if id == receiver_id_1 => msg_1 = message[0],
45    ///             id if id == receiver_id_2 => msg_2 = message[0],
46    ///             _ => unreachable!(),
47    ///         }
48    ///         _ => unreachable!(),
49    ///     }
50    /// });
51    ///
52    /// assert_eq!((msg_1, msg_2), (23, 42));
53    /// ```
54    pub fn from_listener(id: ResourceId, addr: SocketAddr) -> Self {
55        // Only local resources allowed
56        assert_eq!(id.resource_type(), super::resource_id::ResourceType::Local);
57
58        // Only non connection-oriented transport protocols allowed
59        assert!(!super::transport::Transport::from(id.adapter_id()).is_connection_oriented());
60
61        Endpoint::new(id, addr)
62    }
63
64    pub(crate) fn new(resource_id: ResourceId, addr: SocketAddr) -> Self {
65        Self { resource_id, addr }
66    }
67
68    /// Returns the inner network resource id used by this endpoint.
69    /// It is not necessary to be unique for each endpoint if some of them shared the resource
70    /// (an example of this is the different endpoints generated by when you listen by udp).
71    pub fn resource_id(&self) -> ResourceId {
72        self.resource_id
73    }
74
75    /// Returns the peer address of the endpoint.
76    pub fn addr(&self) -> SocketAddr {
77        self.addr
78    }
79}
80
81impl std::fmt::Display for Endpoint {
82    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
83        write!(f, "{} {}", self.resource_id, self.addr)
84    }
85}
86
87#[cfg(test)]
88mod tests {
89    use super::*;
90    use crate::network::resource_id::{ResourceType, ResourceIdGenerator};
91    use crate::network::transport::{Transport};
92
93    #[test]
94    fn from_local_non_connection_oriented() {
95        let addr = "0.0.0.0:0".parse().unwrap();
96        let generator = ResourceIdGenerator::new(Transport::Udp.id(), ResourceType::Local);
97        Endpoint::from_listener(generator.generate(), addr);
98    }
99}