1use super::*;
5use crate::network_port::{
6 Bip6Bind, Bip6PortConfig, BipPortConfig, NetworkPortObject, PortAddress, PortBind,
7};
8use bacnet_types::bip_port::BipPortMode;
9use std::sync::Weak;
10
11pub(super) struct NetworkPortRegistration {
12 oid: ObjectIdentifier,
13 lease: Weak<()>,
14 configured: PortAddress,
16 published: bool,
17}
18
19impl ObjectDatabase {
20 fn builtin_network_port_mut(
21 &mut self,
22 oid: &ObjectIdentifier,
23 ) -> Option<&mut NetworkPortObject> {
24 self.objects
26 .get_mut(oid)?
27 .as_mut()
28 .as_stored_any_mut(crate::traits::ObjectStorageAccess(()))
29 .downcast_mut::<NetworkPortObject>()
30 .filter(|port| port.object_identifier() == *oid)
31 }
32
33 #[doc(hidden)]
35 pub fn configured_bip_port_internal(
36 &mut self,
37 oid: &ObjectIdentifier,
38 ) -> Option<BipPortConfig> {
39 self.builtin_network_port_mut(oid)?
40 .configuration_internal()
41 .cloned()
42 }
43
44 fn configured_bip6_port_internal(&mut self, oid: &ObjectIdentifier) -> Option<Bip6PortConfig> {
46 self.builtin_network_port_mut(oid)?
47 .bip6_configuration_internal()
48 .cloned()
49 }
50
51 #[doc(hidden)]
55 pub fn reserve_bip_port_internal(
56 &mut self,
57 oid: ObjectIdentifier,
58 ip: [u8; 4],
59 udp: u16,
60 ) -> Result<(BipPortConfig, Arc<()>), Error> {
61 let lease = self.reserve_port(oid, PortAddress::V4(ip, udp))?;
62 let configured = self
63 .configured_bip_port_internal(&oid)
64 .expect("reserved B/IP port");
65 Ok((configured, lease))
66 }
67
68 #[doc(hidden)]
72 pub fn reserve_bip6_port_internal(
73 &mut self,
74 oid: ObjectIdentifier,
75 ip: [u8; 16],
76 udp: u16,
77 ) -> Result<(Bip6PortConfig, Arc<()>), Error> {
78 let lease = self.reserve_port(oid, PortAddress::V6(ip, udp))?;
79 let configured = self
80 .configured_bip6_port_internal(&oid)
81 .expect("reserved B/IPv6 port");
82 Ok((configured, lease))
83 }
84
85 fn reserve_port(
86 &mut self,
87 oid: ObjectIdentifier,
88 address: PortAddress,
89 ) -> Result<Arc<()>, Error> {
90 if oid.object_type() != ObjectType::NETWORK_PORT
91 || !(1..=255).contains(&oid.instance_number())
92 {
93 return Err(invalid("registered Network Port instance must be 1..255"));
94 }
95 if self
96 .network_port
97 .as_ref()
98 .is_some_and(|port| port.lease.strong_count() != 0)
99 {
100 return Err(invalid("database already has a live registered port owner"));
101 }
102 let authority = self
103 .builtin_network_port_mut(&oid)
104 .ok_or_else(|| invalid("registration requires the selected built-in Network Port"))?;
105 let configured = match authority.configured_address_internal() {
106 Some(configured) if configured == address => configured,
107 Some(configured) if configured.same_family(address) => {
108 return Err(invalid(
109 "Network Port configuration differs from transport interface/UDP",
110 ))
111 }
112 _ => {
113 return Err(invalid(match address {
114 PortAddress::V4(..) => "registration requires an IPV4 port",
115 PortAddress::V6(..) => "registration requires an IPV6 port",
116 }))
117 }
118 };
119 let lease = Arc::new(());
120 authority.reserve_internal(&lease)?;
121 self.network_port = Some(NetworkPortRegistration {
122 oid,
123 lease: Arc::downgrade(&lease),
124 configured,
125 published: false,
126 });
127 Ok(lease)
128 }
129
130 #[doc(hidden)]
134 pub fn publish_bip_port_internal(
135 &mut self,
136 oid: ObjectIdentifier,
137 ip: [u8; 4],
138 udp: u16,
139 capacity: u32,
140 mode: BipPortMode,
141 ) -> Result<(), Error> {
142 self.publish_port(oid, PortBind::V4(ip, udp), capacity, mode)
143 }
144
145 #[doc(hidden)]
150 #[allow(clippy::too_many_arguments)] pub fn publish_bip6_port_internal(
152 &mut self,
153 oid: ObjectIdentifier,
154 ip: [u8; 16],
155 udp: u16,
156 vmac: [u8; 3],
157 multicast: [u8; 16],
158 capacity: u32,
159 mode: BipPortMode,
160 ) -> Result<(), Error> {
161 let bind = Bip6Bind {
162 ip,
163 udp,
164 vmac,
165 multicast,
166 };
167 self.publish_port(oid, PortBind::V6(bind), capacity, mode)
168 }
169
170 fn publish_port(
171 &mut self,
172 oid: ObjectIdentifier,
173 bind: PortBind,
174 capacity: u32,
175 mode: BipPortMode,
176 ) -> Result<(), Error> {
177 let registration = self
178 .network_port
179 .as_ref()
180 .filter(|port| port.oid == oid)
181 .ok_or_else(|| invalid("missing Network Port reservation"))?;
182 let lease = registration
183 .lease
184 .upgrade()
185 .ok_or_else(|| invalid("Network Port owner expired"))?;
186 let actual = bind.address();
187 let configured = registration.configured;
188 if registration.published
189 || !configured.same_ip(actual)
190 || actual.udp() == 0
191 || (configured.udp() != 0 && configured.udp() != actual.udp())
192 {
193 return Err(invalid("post-bind Network Port identity mismatch"));
194 }
195 self.builtin_network_port_mut(&oid)
196 .ok_or_else(|| invalid("selected Network Port authority disappeared"))?
197 .reconcile_internal(&lease, bind, capacity, mode)?;
198 self.network_port
199 .as_mut()
200 .expect("validated registration")
201 .published = true;
202 Ok(())
203 }
204
205 #[doc(hidden)]
207 pub fn registered_port_internal(&self) -> Option<ObjectIdentifier> {
208 self.network_port
209 .as_ref()
210 .filter(|port| port.published && port.lease.strong_count() != 0)
211 .map(|port| port.oid)
212 }
213
214 #[doc(hidden)]
217 pub fn network_number_internal(
218 &mut self,
219 oid: ObjectIdentifier,
220 announcement: Option<(u16, u8)>,
221 ) -> Option<bacnet_types::network_number::NetworkNumber> {
222 if self.registered_port_internal() != Some(oid) {
223 return None;
224 }
225 Some(
226 self.builtin_network_port_mut(&oid)?
227 .network_number_internal(announcement),
228 )
229 }
230
231 #[doc(hidden)]
235 pub fn set_network_port_activation_internal(
236 &mut self,
237 oid: ObjectIdentifier,
238 activation: bool,
239 ) -> Result<(), Error> {
240 self.builtin_network_port_mut(&oid)
241 .ok_or_else(|| invalid("selected Network Port authority disappeared"))?
242 .set_activation_internal(activation);
243 Ok(())
244 }
245
246 #[doc(hidden)]
253 pub fn set_network_port_multicast_internal(
254 &mut self,
255 oid: ObjectIdentifier,
256 multicast: Option<std::sync::Arc<dyn bacnet_types::bip_port::IpMulticast>>,
257 ) -> Result<(), Error> {
258 self.builtin_network_port_mut(&oid)
259 .ok_or_else(|| invalid("selected Network Port authority disappeared"))?
260 .set_multicast_internal(multicast);
261 Ok(())
262 }
263
264 fn network_port_oids(&self) -> Vec<ObjectIdentifier> {
266 self.objects
267 .keys()
268 .filter(|oid| oid.object_type() == ObjectType::NETWORK_PORT)
269 .copied()
270 .collect()
271 }
272
273 pub fn check_network_port_changes(&mut self) -> Result<(), Error> {
277 for oid in self.network_port_oids() {
278 if let Some(port) = self.builtin_network_port_mut(&oid) {
279 port.check_pending_changes()?;
280 }
281 }
282 Ok(())
283 }
284
285 pub fn activate_network_port_changes(&mut self) -> Result<usize, Error> {
294 let ports = self.network_port_oids();
295 let mut activated = 0;
296 let mut first_error = None;
297 for oid in ports {
298 let Some(port) = self.builtin_network_port_mut(&oid) else {
299 continue;
300 };
301 match port.activate_changes() {
302 Ok(true) => activated += 1,
303 Ok(false) => {}
304 Err(error) => {
305 first_error.get_or_insert(error);
306 }
307 }
308 }
309 first_error.map_or(Ok(activated), Err)
310 }
311
312 pub(super) fn check_network_port_membership(
313 &self,
314 oid: &ObjectIdentifier,
315 ) -> Result<(), Error> {
316 if self
317 .network_port
318 .as_ref()
319 .is_some_and(|port| port.oid == *oid && port.lease.strong_count() != 0)
320 {
321 return Err(Error::Protocol {
322 class: ErrorClass::OBJECT,
323 code: ErrorCode::OBJECT_DELETION_NOT_PERMITTED,
324 });
325 }
326 Ok(())
327 }
328}
329fn invalid(message: &str) -> Error {
330 Error::Encoding(message.into())
331}