Skip to main content

actix_telepathy/remote/addr/
resolver.rs

1use crate::remote::RemoteWrapper;
2use actix::prelude::*;
3use log::*;
4use serde::{Deserialize, Serialize};
5use std::collections::HashMap;
6use std::fmt::{self, Debug, Display, Formatter};
7use std::hash::{Hash, Hasher};
8use std::str::FromStr;
9
10const NETWORKINTERFACE: &str = "networkinterface";
11const GOSSIP: &str = "gossip";
12
13#[derive(Serialize, Deserialize, Debug)]
14pub enum AddrRepresentation {
15    NetworkInterface,
16    Connector,
17    Key(String),
18}
19
20impl Display for AddrRepresentation {
21    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
22        match self {
23            AddrRepresentation::NetworkInterface => f.write_str(NETWORKINTERFACE),
24            AddrRepresentation::Connector => f.write_str(GOSSIP),
25            AddrRepresentation::Key(id) => f.write_str(id),
26        }
27    }
28}
29
30impl FromStr for AddrRepresentation {
31    type Err = ();
32
33    fn from_str(s: &str) -> Result<Self, Self::Err> {
34        Ok(match s {
35            NETWORKINTERFACE => AddrRepresentation::NetworkInterface,
36            GOSSIP => AddrRepresentation::Connector,
37            _ => AddrRepresentation::Key(String::from(s)),
38        })
39    }
40}
41
42impl Clone for AddrRepresentation {
43    fn clone(&self) -> Self {
44        AddrRepresentation::from_str(&self.to_string()).unwrap()
45    }
46}
47
48impl PartialEq for AddrRepresentation {
49    fn eq(&self, other: &Self) -> bool {
50        let self_key = self.to_string();
51        (self_key == other.to_string() && self_key != "Key")
52            || (self_key == "Key"
53                && match self {
54                    AddrRepresentation::Key(key) => match other {
55                        AddrRepresentation::Key(other_key) => key == other_key,
56                        _ => false,
57                    },
58                    _ => false,
59                })
60    }
61}
62
63impl Eq for AddrRepresentation {}
64
65impl Hash for AddrRepresentation {
66    fn hash<H: Hasher>(&self, state: &mut H) {
67        self.to_string().hash(state);
68    }
69}
70
71#[derive(Message)]
72#[rtype(result = "Result<AddrResponse, ()>")]
73pub enum AddrRequest {
74    Register(Recipient<RemoteWrapper>, String),
75    ResolveStr(String),
76    ResolveRec(Recipient<RemoteWrapper>),
77}
78
79pub enum AddrResponse {
80    Register,
81    ResolveStr(Recipient<RemoteWrapper>),
82    ResolveRec(String),
83}
84
85#[derive(Default)]
86pub struct AddrResolver {
87    str2rec: HashMap<String, Recipient<RemoteWrapper>>,
88    rec2str: HashMap<Recipient<RemoteWrapper>, String>,
89}
90
91pub struct NotAvailableError {}
92
93impl Debug for NotAvailableError {
94    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
95        f.debug_struct("NotAvailableError").finish()
96    }
97}
98
99/// A system actor that can resolve `ACTOR_ID`s to [actix::Addr](https://docs.rs/actix/latest/actix/struct.Addr.html)s
100/// by sending an [AddrRequest](./enum.AddrRequest.html).
101impl AddrResolver {
102    pub fn new() -> Self {
103        AddrResolver::default()
104    }
105
106    pub fn resolve_str(
107        &mut self,
108        id: String,
109    ) -> Result<&Recipient<RemoteWrapper>, NotAvailableError> {
110        match self.str2rec.get(&id) {
111            Some(rec) => Ok(rec),
112            None => {
113                error!("ID {} is not registered", id);
114                Err(NotAvailableError {})
115            }
116        }
117    }
118
119    pub fn resolve_rec(
120        &mut self,
121        rec: &Recipient<RemoteWrapper>,
122    ) -> Result<&String, NotAvailableError> {
123        match self.rec2str.get(rec) {
124            Some(str) => Ok(str),
125            None => {
126                error!("Recipient is not registered");
127                Err(NotAvailableError {})
128            }
129        }
130    }
131
132    pub fn resolve_rec_from_addr_representation(
133        &mut self,
134        addr_representation: AddrRepresentation,
135    ) -> Result<&Recipient<RemoteWrapper>, NotAvailableError> {
136        self.resolve_str(addr_representation.to_string())
137    }
138}
139
140impl Actor for AddrResolver {
141    type Context = Context<Self>;
142
143    fn started(&mut self, _ctx: &mut Context<Self>) {
144        debug!("AddressResolver actor started");
145    }
146}
147
148impl Handler<RemoteWrapper> for AddrResolver {
149    type Result = ();
150
151    fn handle(&mut self, msg: RemoteWrapper, _ctx: &mut Context<Self>) -> Self::Result {
152        if let Ok(recipient) = self.resolve_rec_from_addr_representation(msg.destination.id.clone())
153        {
154            recipient.do_send(msg);
155        } else {
156            warn!(
157                "Could not resolve Recipient '{}' for RemoteMessage. Is this receiver a RemoteActor? Message is abandoned.",
158                msg.identifier
159            );
160        }
161    }
162}
163
164impl Handler<AddrRequest> for AddrResolver {
165    type Result = Result<AddrResponse, ()>;
166
167    fn handle(&mut self, msg: AddrRequest, _ctx: &mut Context<Self>) -> Self::Result {
168        match msg {
169            AddrRequest::Register(rec, identifier) => {
170                let is_new = !self.rec2str.contains_key(&rec);
171
172                if is_new {
173                    self.str2rec.insert(identifier.clone(), rec.clone());
174                    self.rec2str.insert(rec, identifier.clone());
175                    debug!("Actor '{}' registered", identifier);
176                    Ok(AddrResponse::Register)
177                } else {
178                    debug!("Recipient is already added");
179                    Err(())
180                }
181            }
182            AddrRequest::ResolveStr(id) => {
183                let rec = self.resolve_str(id);
184                match rec {
185                    Ok(r) => Ok(AddrResponse::ResolveStr((*r).clone())),
186                    Err(_) => Err(()),
187                }
188            }
189            AddrRequest::ResolveRec(rec) => {
190                let id = self.resolve_rec(&rec);
191                match id {
192                    Ok(i) => Ok(AddrResponse::ResolveRec(i.clone())),
193                    Err(_) => Err(()),
194                }
195            }
196        }
197    }
198}
199
200impl Supervised for AddrResolver {}
201impl SystemService for AddrResolver {}