zoe_app_primitives/relay.rs
1use std::net::SocketAddr;
2
3use serde::{Deserialize, Serialize};
4use zoe_wire_protocol::Ed25519VerifyingKey;
5
6use crate::Metadata;
7
8/// Relay endpoint information for group participants
9///
10/// Contains the network address and public key needed to connect to a relay server.
11/// Multiple relay endpoints can be provided to a group participant for redundancy,
12/// with the list order indicating priority preference.
13#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
14pub struct RelayEndpoint {
15 /// Network address of the relay server
16 ///
17 /// This is the socket address (IP:port) where the relay server
18 /// can be reached for QUIC connections.
19 pub address: SocketAddr,
20
21 /// Ed25519 public key of the relay server
22 ///
23 /// Used to verify the relay server's identity during the QUIC TLS handshake.
24 /// This prevents man-in-the-middle attacks and ensures the client is
25 /// connecting to the correct relay server.
26 pub public_key: Ed25519VerifyingKey,
27
28 /// Optional human-readable name for the relay
29 ///
30 /// Can be used for display purposes or debugging. Examples:
31 /// "Primary Relay", "EU West", "Backup Server", etc.
32 pub name: Option<String>,
33
34 /// Additional relay metadata
35 ///
36 /// Can store information like geographic region, performance metrics,
37 /// supported features, or other relay-specific data.
38 pub metadata: Vec<Metadata>,
39}
40
41impl RelayEndpoint {
42 /// Create a new relay endpoint with minimal required fields
43 pub fn new(address: SocketAddr, public_key: Ed25519VerifyingKey) -> Self {
44 Self {
45 address,
46 public_key,
47 name: None,
48 metadata: Vec::new(),
49 }
50 }
51
52 /// Set a human-readable name for this relay
53 pub fn with_name(mut self, name: String) -> Self {
54 self.name = Some(name);
55 self
56 }
57
58 /// Add metadata to this relay endpoint
59 pub fn with_metadata(mut self, metadata: Metadata) -> Self {
60 self.metadata.push(metadata);
61 self
62 }
63
64 /// Get the relay's display name (name if set, otherwise address)
65 pub fn display_name(&self) -> String {
66 self.name
67 .clone()
68 .unwrap_or_else(|| self.address.to_string())
69 }
70}