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
use serde::{Deserialize, Serialize}; use uuid::Uuid; #[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Hash)] pub struct ServiceList { pub trusted: Vec<String>, pub untrusted: Vec<String>, } #[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Hash)] pub struct Address { pub address: String, } #[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Hash)] pub struct PingResponse { pub ack: bool, } #[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Hash)] pub struct RegisterResponse { pub session: Option<Session>, } #[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Hash)] pub struct Session { pub token: Uuid, } #[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Hash)] pub struct ServiceIdentity { pub protocol: String, pub address: String, } #[cfg(feature = "discover")] pub mod discover { use super::{PingResponse, RegisterResponse, ServiceIdentity}; use reqwest; use reqwest::Client; use std::thread::sleep; use std::time::Duration; pub fn get_peers(api_path: &str, protocol: &str) -> Result<super::ServiceList, reqwest::Error> { reqwest::get(&format!("{}/discover/{}", api_path, protocol))?.json() } #[derive(Debug)] pub enum RegisterError { RegisterRefused, RegisterExpired, RequestError(reqwest::Error), } impl std::fmt::Display for RegisterError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match &self { RegisterError::RegisterRefused => write!(f, "register refused"), RegisterError::RegisterExpired => write!(f, "register revoked by server"), RegisterError::RequestError(e) => write!(f, "request failed: {}", e), } } } impl std::error::Error for RegisterError {} impl From<reqwest::Error> for RegisterError { fn from(err: reqwest::Error) -> RegisterError { RegisterError::RequestError(err) } } pub fn register(api_path: &str, id: ServiceIdentity) -> Result<(), RegisterError> { let client = Client::new(); let (address, protocol) = ( super::Address { address: id.address, }, id.protocol, ); let session: RegisterResponse = client .post(&format!("{}/discover/{}", api_path, protocol)) .json(&address) .send()? .json()?; let session = match session.session { Some(s) => s, None => return Err(RegisterError::RegisterRefused), }; loop { let resp: PingResponse = client .put(&format!("{}/ping/{}", api_path, session.token)) .send()? .json()?; if !resp.ack { return Err(RegisterError::RegisterExpired); } sleep(Duration::from_secs(50)); } } }