1use fuchsia_sync::Mutex;
6use std::collections::HashSet;
7use {fidl_fuchsia_net as net, fidl_fuchsia_net_ext as net_ext};
8
9pub type ServerList = Vec<net::SocketAddress>;
13
14#[derive(Debug)]
16struct ServerConfigInner {
17 servers: ServerList,
18}
19
20#[derive(Debug)]
22pub struct ServerConfigState(Mutex<ServerConfigInner>);
23
24#[derive(Debug, PartialEq, Eq)]
26pub enum UpdateServersResult {
27 Updated(ServerList),
29 NoChange,
31 InvalidsServers,
33}
34
35impl ServerConfigState {
36 pub fn new() -> Self {
38 Self(Mutex::new(ServerConfigInner { servers: Vec::new() }))
39 }
40
41 pub fn servers(&self) -> ServerList {
43 let Self(current) = self;
44 let inner = current.lock();
45 inner.servers.clone()
46 }
47
48 pub fn update_servers(&self, mut servers: ServerList) -> UpdateServersResult {
50 let Self(current) = self;
51
52 if servers.iter().any(|s| {
53 let net_ext::SocketAddress(sockaddr) = From::from(*s);
55 let ip = sockaddr.ip();
56 ip.is_multicast() || ip.is_unspecified()
57 }) {
58 return UpdateServersResult::InvalidsServers;
59 }
60
61 let mut set = HashSet::new();
62 let () = servers.retain(|s| set.insert(*s));
63 let mut inner = current.lock();
64 if inner.servers == servers {
65 return UpdateServersResult::NoChange;
66 }
67 inner.servers = servers.clone();
68 UpdateServersResult::Updated(servers)
69 }
70}
71
72#[cfg(test)]
73mod tests {
74 use super::*;
75 use crate::test_util::*;
76 use net_declare::fidl_socket_addr;
77
78 #[test]
79 fn test_config_state() {
80 let state = ServerConfigState::new();
81 assert_eq!(state.servers(), []);
82
83 let values = [DHCP_SERVER, NDP_SERVER];
85 assert_eq!(
86 state.update_servers(values.to_vec()),
87 UpdateServersResult::Updated(values.to_vec())
88 );
89 assert_eq!(state.servers(), values);
90
91 assert_eq!(
93 state.update_servers(vec![DHCP_SERVER, DHCP_SERVER, NDP_SERVER]),
94 UpdateServersResult::NoChange
95 );
96 assert_eq!(state.servers(), values);
97
98 for addr in [
100 fidl_socket_addr!("0.0.0.0:1111"),
101 fidl_socket_addr!("[::]:2222"),
102 fidl_socket_addr!("224.0.0.1:3333"),
103 fidl_socket_addr!("[ff02::1]:4444"),
104 ] {
105 assert_eq!(state.update_servers(vec![addr]), UpdateServersResult::InvalidsServers);
106 }
107 assert_eq!(state.servers(), values);
108
109 assert_eq!(state.update_servers(vec![]), UpdateServersResult::Updated(vec![]));
111 assert_eq!(state.servers(), []);
112 }
113}