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::{Debug, 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 ToString for AddrRepresentation {
21    fn to_string(&self) -> String {
22        match self {
23            AddrRepresentation::NetworkInterface => String::from(NETWORKINTERFACE),
24            AddrRepresentation::Connector => String::from(GOSSIP),
25            AddrRepresentation::Key(id) => id.clone(),
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!("Could not resolve Recipient '{}' for RemoteMessage. Is this receiver a RemoteActor? Message is abandoned.", msg.identifier);
157        }
158    }
159}
160
161impl Handler<AddrRequest> for AddrResolver {
162    type Result = Result<AddrResponse, ()>;
163
164    fn handle(&mut self, msg: AddrRequest, _ctx: &mut Context<Self>) -> Self::Result {
165        match msg {
166            AddrRequest::Register(rec, identifier) => {
167                let is_new = self.rec2str.get(&rec).is_none();
168
169                if is_new {
170                    self.str2rec.insert(identifier.clone(), rec.clone());
171                    self.rec2str.insert(rec, identifier.clone());
172                    debug!("Actor '{}' registered", identifier);
173                    Ok(AddrResponse::Register)
174                } else {
175                    debug!("Recipient is already added");
176                    Err(())
177                }
178            }
179            AddrRequest::ResolveStr(id) => {
180                let rec = self.resolve_str(id);
181                match rec {
182                    Ok(r) => Ok(AddrResponse::ResolveStr((*r).clone())),
183                    Err(_) => Err(()),
184                }
185            }
186            AddrRequest::ResolveRec(rec) => {
187                let id = self.resolve_rec(&rec);
188                match id {
189                    Ok(i) => Ok(AddrResponse::ResolveRec(i.clone())),
190                    Err(_) => Err(()),
191                }
192            }
193        }
194    }
195}
196
197impl Supervised for AddrResolver {}
198impl SystemService for AddrResolver {}