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}