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