Skip to main content

opcua_server/node_manager/memory/
mod.rs

1//! The implementation of [InMemoryNodeManager], a generic node manager that keeps
2//! all its nodes in memory, and delegates implementing
3//! details to a type implementing [InMemoryNodeManagerImpl].
4
5mod memory_mgr_impl;
6mod simple;
7
8#[cfg(feature = "generated-address-space")]
9mod core;
10
11#[cfg(feature = "generated-address-space")]
12pub use core::{CoreNodeManager, CoreNodeManagerBuilder, CoreNodeManagerImpl};
13
14pub use memory_mgr_impl::*;
15use opcua_core::{trace_read_lock, trace_write_lock};
16pub use simple::*;
17use tracing::warn;
18
19use std::{
20    collections::{HashSet, VecDeque},
21    sync::Arc,
22};
23
24use async_trait::async_trait;
25use hashbrown::HashMap;
26
27use crate::{
28    address_space::{
29        read_node_value, user_access_level, AccessLevel, EventNotifier, NodeType,
30        ReferenceDirection,
31    },
32    diagnostics::NamespaceMetadata,
33    subscriptions::CreateMonitoredItem,
34    SubscriptionCache,
35};
36use opcua_core::sync::RwLock;
37use opcua_types::{
38    argument::Argument, AttributeId, BrowseDescriptionResultMask, BrowseDirection, DataEncoding,
39    DataValue, DateTime, ExpandedNodeId, MonitoringMode, NodeClass, NodeId, NumericRange,
40    ReadAnnotationDataDetails, ReadAtTimeDetails, ReadEventDetails, ReadProcessedDetails,
41    ReadRawModifiedDetails, ReferenceDescription, ReferenceTypeId, StatusCode, TimestampsToReturn,
42    Variant,
43};
44
45use super::{
46    build::NodeManagerBuilder,
47    view::{AddReferenceResult, ExternalReference, ExternalReferenceRequest, NodeMetadata},
48    AddNodeItem, AddReferenceItem, BrowseNode, BrowsePathItem, DefaultTypeTree, DeleteNodeItem,
49    DeleteReferenceItem, DynNodeManager, HistoryNode, HistoryUpdateDetails, HistoryUpdateNode,
50    MethodCall, MonitoredItemRef, MonitoredItemUpdateRef, NodeManager, ReadNode, RegisterNodeItem,
51    RequestContext, ServerContext, WriteNode,
52};
53
54use crate::address_space::AddressSpace;
55
56#[derive(Default)]
57struct BrowseContinuationPoint {
58    nodes: VecDeque<ReferenceDescription>,
59}
60
61/// A node manager that stores its nodes in an in-memory [AddressSpace]. This
62/// only supports a static list of namespaces, and a attributes stored in memory.
63///
64/// Implementations of custom behavior are provided with a type implementing
65/// [InMemoryNodeManagerImpl].
66pub struct InMemoryNodeManager<TImpl> {
67    address_space: Arc<RwLock<AddressSpace>>,
68    namespaces: HashMap<u16, String>,
69    inner: TImpl,
70}
71
72/// Builder for the in-memory node manager.
73pub struct InMemoryNodeManagerBuilder<T> {
74    impl_builder: T,
75}
76
77impl<T: InMemoryNodeManagerImplBuilder> InMemoryNodeManagerBuilder<T> {
78    /// Create a new in memory node manager builder with the given
79    /// builder for the [InMemoryNodeManagerImpl].
80    pub fn new(impl_builder: T) -> Self {
81        Self { impl_builder }
82    }
83}
84
85impl<T: InMemoryNodeManagerImplBuilder> NodeManagerBuilder for InMemoryNodeManagerBuilder<T> {
86    fn build(self: Box<Self>, context: ServerContext) -> Arc<DynNodeManager> {
87        let mut address_space = AddressSpace::new();
88        let inner = self.impl_builder.build(context, &mut address_space);
89        Arc::new(InMemoryNodeManager::new(inner, address_space))
90    }
91}
92
93impl<TImpl: InMemoryNodeManagerImpl> InMemoryNodeManager<TImpl> {
94    pub(crate) fn new(inner: TImpl, address_space: AddressSpace) -> Self {
95        Self {
96            namespaces: address_space.namespaces().clone(),
97            address_space: Arc::new(RwLock::new(address_space)),
98            inner,
99        }
100    }
101
102    /// Return the inner [InMemoryNodeManagerImpl].
103    pub fn inner(&self) -> &TImpl {
104        &self.inner
105    }
106
107    /// Get the address space.
108    pub fn address_space(&self) -> &Arc<RwLock<AddressSpace>> {
109        &self.address_space
110    }
111
112    /// Get a reference to the namespaces managed by this node manager,
113    /// by namespace index.
114    pub fn namespaces(&self) -> &HashMap<u16, String> {
115        &self.namespaces
116    }
117
118    /// Set the attributes given in `values` and notify any subscriptions
119    /// about the changes.
120    ///
121    /// To set values, use [InMemoryNodeManager::set_values].
122    pub fn set_attributes<'a>(
123        &self,
124        subscriptions: &SubscriptionCache,
125        values: impl Iterator<Item = (&'a NodeId, AttributeId, Variant)>,
126    ) -> Result<(), StatusCode> {
127        let mut address_space = trace_write_lock!(self.address_space);
128        let mut output = Vec::new();
129
130        for (id, attribute_id, value) in values {
131            let Some(node) = address_space.find_mut(id) else {
132                return Err(StatusCode::BadNodeIdUnknown);
133            };
134
135            let node_mut = node.as_mut_node();
136            node_mut.set_attribute(attribute_id, value)?;
137            // Don't notify on changes to event notifier, subscribing to that
138            // specific attribute means subscribing to events.
139            if attribute_id != AttributeId::EventNotifier {
140                output.push((id, attribute_id));
141            }
142        }
143
144        subscriptions.maybe_notify(
145            output.into_iter(),
146            |node_id, attribute_id, index_range, data_encoding| {
147                let node = address_space.find(node_id)?;
148                let node_ref = node.as_node();
149
150                node_ref.get_attribute(
151                    TimestampsToReturn::Both,
152                    attribute_id,
153                    index_range,
154                    data_encoding,
155                )
156            },
157        );
158
159        Ok(())
160    }
161
162    /// Set the attribute given by `attribute_id` on the node with ID `id` to
163    /// `value`.
164    pub fn set_attribute(
165        &self,
166        subscriptions: &SubscriptionCache,
167        id: &NodeId,
168        attribute_id: AttributeId,
169        value: Variant,
170    ) -> Result<(), StatusCode> {
171        self.set_attributes(subscriptions, [(id, attribute_id, value)].into_iter())
172    }
173
174    /// Set variable values with updates given by `values`, notifying any
175    /// subscriptions of the changes.
176    pub fn set_values<'a>(
177        &self,
178        subscriptions: &SubscriptionCache,
179        values: impl Iterator<Item = (&'a NodeId, Option<&'a NumericRange>, DataValue)>,
180    ) -> Result<(), StatusCode> {
181        let mut address_space = trace_write_lock!(self.address_space);
182        let now = DateTime::now();
183        let mut output = Vec::new();
184
185        for (id, index_range, value) in values {
186            let Some(node) = address_space.find_mut(id) else {
187                return Err(StatusCode::BadNodeIdUnknown);
188            };
189
190            match node {
191                NodeType::Variable(v) => {
192                    if let Some(range) = index_range {
193                        let status = value.status();
194                        let source_timestamp = value.source_timestamp.unwrap_or(now);
195                        let server_timestamp = value.server_timestamp.unwrap_or(now);
196                        v.set_value_range(
197                            value.value.unwrap_or_default(),
198                            range,
199                            status,
200                            &server_timestamp,
201                            &source_timestamp,
202                        )?
203                    } else {
204                        v.set_data_value(value)
205                    }
206                }
207                NodeType::VariableType(v) => v.set_value(value.value.unwrap_or_default()),
208                _ => return Err(StatusCode::BadAttributeIdInvalid),
209            }
210
211            output.push((id, AttributeId::Value));
212        }
213
214        subscriptions.maybe_notify(
215            output.into_iter(),
216            |node_id, attribute_id, index_range, data_encoding| {
217                let node = address_space.find(node_id)?;
218                let node_ref = node.as_node();
219
220                node_ref.get_attribute(
221                    TimestampsToReturn::Both,
222                    attribute_id,
223                    index_range,
224                    data_encoding,
225                )
226            },
227        );
228
229        Ok(())
230    }
231
232    /// Set the variable value to `value`, using `index_range`, on the
233    /// node with ID `id`.
234    pub fn set_value(
235        &self,
236        subscriptions: &SubscriptionCache,
237        id: &NodeId,
238        index_range: Option<&NumericRange>,
239        value: DataValue,
240    ) -> Result<(), StatusCode> {
241        self.set_values(subscriptions, [(id, index_range, value)].into_iter())
242    }
243
244    fn get_reference(
245        address_space: &AddressSpace,
246        type_tree: &DefaultTypeTree,
247        target_node: &NodeType,
248        result_mask: BrowseDescriptionResultMask,
249    ) -> NodeMetadata {
250        let node_ref = target_node.as_node();
251
252        let target_node_id = node_ref.node_id().clone();
253
254        let type_definition =
255            if result_mask.contains(BrowseDescriptionResultMask::RESULT_MASK_TYPE_DEFINITION) {
256                // Type definition NodeId of the TargetNode. Type definitions are only available
257                // for the NodeClasses Object and Variable. For all other NodeClasses a null NodeId
258                // shall be returned.
259                match node_ref.node_class() {
260                    NodeClass::Object | NodeClass::Variable => {
261                        let mut type_defs = address_space.find_references(
262                            &target_node_id,
263                            Some((ReferenceTypeId::HasTypeDefinition, false)),
264                            type_tree,
265                            BrowseDirection::Forward,
266                        );
267                        if let Some(type_def) = type_defs.next() {
268                            ExpandedNodeId::new(type_def.target_node.clone())
269                        } else {
270                            ExpandedNodeId::null()
271                        }
272                    }
273                    _ => ExpandedNodeId::null(),
274                }
275            } else {
276                ExpandedNodeId::null()
277            };
278
279        NodeMetadata {
280            node_id: ExpandedNodeId::new(target_node_id),
281            browse_name: node_ref.browse_name().clone(),
282            display_name: node_ref.display_name().clone(),
283            node_class: node_ref.node_class(),
284            type_definition,
285        }
286    }
287
288    /// Browses a single node, returns any external references found.
289    fn browse_node(
290        address_space: &AddressSpace,
291        type_tree: &DefaultTypeTree,
292        node: &mut BrowseNode,
293        namespaces: &hashbrown::HashMap<u16, String>,
294    ) {
295        let reference_type_id = if node.reference_type_id().is_null() {
296            None
297        } else if let Ok(reference_type_id) = node.reference_type_id().as_reference_type_id() {
298            Some((reference_type_id, node.include_subtypes()))
299        } else {
300            None
301        };
302
303        let mut cont_point = BrowseContinuationPoint::default();
304
305        let source_node_id = node.node_id().clone();
306
307        for reference in address_space.find_references(
308            &source_node_id,
309            reference_type_id,
310            type_tree,
311            node.browse_direction(),
312        ) {
313            if reference.target_node.is_null() {
314                warn!(
315                    "Target node in reference from {} of type {} is null",
316                    node.node_id(),
317                    reference.reference_type
318                );
319                continue;
320            }
321            let target_node = address_space.find_node(reference.target_node);
322            let Some(target_node) = target_node else {
323                if namespaces.contains_key(&reference.target_node.namespace) {
324                    warn!(
325                        "Target node {} in reference from {} of type {} does not exist",
326                        reference.target_node,
327                        node.node_id(),
328                        reference.reference_type
329                    );
330                } else {
331                    node.push_external_reference(ExternalReference::new(
332                        reference.target_node.into(),
333                        reference.reference_type.clone(),
334                        reference.direction,
335                    ))
336                }
337
338                continue;
339            };
340
341            let r_node =
342                Self::get_reference(address_space, type_tree, target_node, node.result_mask());
343
344            let ref_desc = ReferenceDescription {
345                reference_type_id: reference.reference_type.clone(),
346                is_forward: matches!(reference.direction, ReferenceDirection::Forward),
347                node_id: r_node.node_id,
348                browse_name: r_node.browse_name,
349                display_name: r_node.display_name,
350                node_class: r_node.node_class,
351                type_definition: r_node.type_definition,
352            };
353
354            if let AddReferenceResult::Full(c) = node.add(type_tree, ref_desc) {
355                cont_point.nodes.push_back(c);
356            }
357        }
358
359        if !cont_point.nodes.is_empty() {
360            node.set_next_continuation_point(Box::new(cont_point));
361        }
362    }
363
364    fn translate_browse_paths(
365        address_space: &AddressSpace,
366        type_tree: &DefaultTypeTree,
367        context: &RequestContext,
368        namespaces: &hashbrown::HashMap<u16, String>,
369        item: &mut BrowsePathItem,
370    ) {
371        if let Some(name) = item.unmatched_browse_name() {
372            let is_full_match = address_space
373                .find_node(item.node_id())
374                .is_some_and(|n| name.is_null() || n.as_node().browse_name() == name);
375            if !is_full_match {
376                return;
377            } else {
378                item.set_browse_name_matched(context.current_node_manager_index);
379            }
380        }
381
382        let mut matching_nodes = HashSet::new();
383        matching_nodes.insert(item.node_id());
384        let mut next_matching_nodes = HashSet::new();
385        let mut results = Vec::new();
386
387        let mut depth = 0;
388        for element in item.path() {
389            depth += 1;
390            for node_id in matching_nodes.drain() {
391                let reference_filter = {
392                    if element.reference_type_id.is_null() {
393                        None
394                    } else {
395                        Some((element.reference_type_id.clone(), element.include_subtypes))
396                    }
397                };
398
399                for rf in address_space.find_references(
400                    node_id,
401                    reference_filter,
402                    type_tree,
403                    if element.is_inverse {
404                        BrowseDirection::Inverse
405                    } else {
406                        BrowseDirection::Forward
407                    },
408                ) {
409                    if !next_matching_nodes.contains(rf.target_node) {
410                        let Some(node) = address_space.find_node(rf.target_node) else {
411                            if !namespaces.contains_key(&rf.target_node.namespace) {
412                                results.push((
413                                    rf.target_node,
414                                    depth,
415                                    Some(element.target_name.clone()),
416                                ));
417                            }
418                            continue;
419                        };
420
421                        if element.target_name.is_null()
422                            || node.as_node().browse_name() == &element.target_name
423                        {
424                            next_matching_nodes.insert(rf.target_node);
425                            results.push((rf.target_node, depth, None));
426                        }
427                    }
428                }
429            }
430            std::mem::swap(&mut matching_nodes, &mut next_matching_nodes);
431        }
432
433        for res in results {
434            item.add_element(res.0.clone(), res.1, res.2);
435        }
436    }
437
438    fn validate_history_read_nodes<'a, 'b>(
439        &self,
440        context: &RequestContext,
441        nodes: &'b mut [&'a mut HistoryNode],
442        is_for_events: bool,
443    ) -> Vec<&'b mut &'a mut HistoryNode> {
444        let address_space = trace_read_lock!(self.address_space);
445        let mut valid = Vec::with_capacity(nodes.len());
446
447        for history_node in nodes {
448            let Some(node) = address_space.find(history_node.node_id()) else {
449                history_node.set_status(StatusCode::BadNodeIdUnknown);
450                continue;
451            };
452
453            if is_for_events {
454                let NodeType::Object(object) = node else {
455                    history_node.set_status(StatusCode::BadHistoryOperationUnsupported);
456                    continue;
457                };
458
459                if !object
460                    .event_notifier()
461                    .contains(EventNotifier::HISTORY_READ)
462                {
463                    history_node.set_status(StatusCode::BadHistoryOperationUnsupported);
464                    continue;
465                }
466            } else {
467                let NodeType::Variable(_) = node else {
468                    history_node.set_status(StatusCode::BadHistoryOperationUnsupported);
469                    continue;
470                };
471
472                let user_access_level = user_access_level(context, node);
473
474                if !user_access_level.contains(AccessLevel::HISTORY_READ) {
475                    history_node.set_status(StatusCode::BadUserAccessDenied);
476                    continue;
477                }
478            }
479
480            valid.push(history_node);
481        }
482
483        valid
484    }
485
486    fn validate_history_write_nodes<'a, 'b>(
487        &self,
488        context: &RequestContext,
489        nodes: &'b mut [&'a mut HistoryUpdateNode],
490    ) -> Vec<&'b mut &'a mut HistoryUpdateNode> {
491        let address_space = trace_read_lock!(self.address_space);
492        let mut valid = Vec::with_capacity(nodes.len());
493
494        for history_node in nodes {
495            let Some(node) = address_space.find(history_node.details().node_id()) else {
496                history_node.set_status(StatusCode::BadNodeIdUnknown);
497                continue;
498            };
499
500            let is_for_events = matches!(
501                history_node.details(),
502                HistoryUpdateDetails::DeleteEvent(_) | HistoryUpdateDetails::UpdateEvent(_)
503            );
504
505            if is_for_events {
506                let NodeType::Object(object) = node else {
507                    history_node.set_status(StatusCode::BadHistoryOperationUnsupported);
508                    continue;
509                };
510
511                if !object
512                    .event_notifier()
513                    .contains(EventNotifier::HISTORY_WRITE)
514                {
515                    history_node.set_status(StatusCode::BadHistoryOperationUnsupported);
516                    continue;
517                }
518            } else {
519                let NodeType::Variable(_) = node else {
520                    history_node.set_status(StatusCode::BadHistoryOperationUnsupported);
521                    continue;
522                };
523
524                let user_access_level = user_access_level(context, node);
525
526                if !user_access_level.contains(AccessLevel::HISTORY_WRITE) {
527                    history_node.set_status(StatusCode::BadUserAccessDenied);
528                    continue;
529                }
530            }
531
532            valid.push(history_node);
533        }
534
535        valid
536    }
537
538    fn validate_method_calls<'a, 'b>(
539        &self,
540        context: &RequestContext,
541        methods: &'b mut [&'a mut MethodCall],
542    ) -> Vec<&'b mut &'a mut MethodCall> {
543        let address_space = trace_read_lock!(self.address_space);
544        let type_tree = trace_read_lock!(context.type_tree);
545        let mut valid = Vec::with_capacity(methods.len());
546
547        for method in methods {
548            let Some(method_ref) = address_space
549                .find_references(
550                    method.object_id(),
551                    Some((ReferenceTypeId::HasComponent, false)),
552                    &*type_tree,
553                    BrowseDirection::Forward,
554                )
555                .find(|r| r.target_node == method.method_id())
556            else {
557                method.set_status(StatusCode::BadMethodInvalid);
558                continue;
559            };
560
561            let Some(NodeType::Method(method_node)) = address_space.find(method_ref.target_node)
562            else {
563                method.set_status(StatusCode::BadMethodInvalid);
564                continue;
565            };
566
567            if !method_node.user_executable()
568                || !context
569                    .authenticator
570                    .is_user_executable(&context.token, method.method_id())
571            {
572                method.set_status(StatusCode::BadUserAccessDenied);
573                continue;
574            }
575
576            let input_arguments = address_space.find_node_by_browse_name(
577                method.method_id(),
578                Some((ReferenceTypeId::HasProperty, false)),
579                &*type_tree,
580                BrowseDirection::Forward,
581                "InputArguments",
582            );
583
584            // If there are no input arguments, it means the method takes no inputs.
585            let Some(input_arguments) = input_arguments else {
586                if method.arguments().is_empty() {
587                    valid.push(method);
588                } else {
589                    method.set_status(StatusCode::BadTooManyArguments);
590                }
591                continue;
592            };
593
594            // If the input arguments object is invalid, we pass it along anyway and leave it up to
595            // the implementation to validate.
596            let NodeType::Variable(arg_var) = input_arguments else {
597                warn!(
598                    "InputArguments for method with ID {} has incorrect node class",
599                    method.method_id()
600                );
601                valid.push(method);
602                continue;
603            };
604
605            let Some(Variant::Array(input_arguments_value)) = arg_var
606                .value(
607                    TimestampsToReturn::Neither,
608                    &NumericRange::None,
609                    &DataEncoding::Binary,
610                    0.0,
611                )
612                .value
613            else {
614                warn!(
615                    "InputArguments for method with ID {} has incorrect type",
616                    method.method_id()
617                );
618                valid.push(method);
619                continue;
620            };
621
622            let num_args = input_arguments_value.values.len();
623            let arguments: Vec<_> = input_arguments_value
624                .values
625                .into_iter()
626                .filter_map(|v| match v {
627                    Variant::ExtensionObject(o) => o.into_inner_as::<Argument>(),
628                    _ => None,
629                })
630                .collect();
631            if arguments.len() != num_args {
632                warn!(
633                    "InputArguments for method with ID {} has invalid arguments",
634                    method.method_id()
635                );
636                valid.push(method);
637                continue;
638            };
639
640            if arguments.len() < method.arguments().len() {
641                method.set_status(StatusCode::BadTooManyArguments);
642                continue;
643            }
644
645            valid.push(method);
646        }
647
648        valid
649    }
650}
651
652#[async_trait]
653impl<TImpl: InMemoryNodeManagerImpl> NodeManager for InMemoryNodeManager<TImpl> {
654    fn owns_node(&self, id: &NodeId) -> bool {
655        self.namespaces.contains_key(&id.namespace)
656    }
657
658    fn name(&self) -> &str {
659        self.inner.name()
660    }
661
662    #[allow(clippy::await_holding_lock)]
663    async fn init(&self, type_tree: &mut DefaultTypeTree, context: ServerContext) {
664        // During init we effectively own the address space, so this should be safe.
665        let mut address_space = trace_write_lock!(self.address_space);
666
667        self.inner.init(&mut address_space, context).await;
668
669        address_space.load_into_type_tree(type_tree);
670    }
671
672    fn namespaces_for_user(&self, _context: &RequestContext) -> Vec<NamespaceMetadata> {
673        self.inner.namespaces()
674    }
675
676    fn handle_new_node(&self, parent_id: &ExpandedNodeId) -> bool {
677        self.inner.handle_new_node(parent_id)
678    }
679
680    async fn resolve_external_references(
681        &self,
682        context: &RequestContext,
683        items: &mut [&mut ExternalReferenceRequest],
684    ) {
685        let address_space = trace_read_lock!(self.address_space);
686        let type_tree = trace_read_lock!(context.type_tree);
687
688        for item in items {
689            let target_node = address_space.find_node(item.node_id());
690
691            let Some(target_node) = target_node else {
692                continue;
693            };
694
695            item.set(Self::get_reference(
696                &address_space,
697                &type_tree,
698                target_node,
699                item.result_mask(),
700            ));
701        }
702    }
703
704    async fn browse(
705        &self,
706        context: &RequestContext,
707        nodes_to_browse: &mut [BrowseNode],
708    ) -> Result<(), StatusCode> {
709        let address_space = trace_read_lock!(self.address_space);
710        let type_tree = trace_read_lock!(context.type_tree);
711
712        for node in nodes_to_browse.iter_mut() {
713            if node.node_id().is_null() {
714                continue;
715            }
716
717            node.set_status(StatusCode::Good);
718
719            if let Some(mut point) = node.take_continuation_point::<BrowseContinuationPoint>() {
720                loop {
721                    if node.remaining() == 0 {
722                        break;
723                    }
724                    let Some(ref_desc) = point.nodes.pop_back() else {
725                        break;
726                    };
727                    // Node is already filtered.
728                    node.add_unchecked(ref_desc);
729                }
730                if !point.nodes.is_empty() {
731                    node.set_next_continuation_point(point);
732                }
733            } else {
734                Self::browse_node(&address_space, &type_tree, node, &self.namespaces);
735            }
736        }
737
738        Ok(())
739    }
740
741    async fn read(
742        &self,
743        context: &RequestContext,
744        max_age: f64,
745        timestamps_to_return: TimestampsToReturn,
746        nodes_to_read: &mut [&mut ReadNode],
747    ) -> Result<(), StatusCode> {
748        let mut read_values = Vec::new();
749        {
750            let address_space = trace_read_lock!(self.address_space);
751            for node in nodes_to_read {
752                if node.node().attribute_id == AttributeId::Value {
753                    read_values.push(node);
754                    continue;
755                }
756
757                node.set_result(address_space.read(
758                    context,
759                    node.node(),
760                    max_age,
761                    timestamps_to_return,
762                ));
763            }
764        }
765
766        if !read_values.is_empty() {
767            let ids: Vec<_> = read_values.iter().map(|r| r.node()).collect();
768            let values = self
769                .inner
770                .read_values(
771                    context,
772                    &self.address_space,
773                    &ids,
774                    max_age,
775                    timestamps_to_return,
776                )
777                .await;
778            for (read, value) in read_values.iter_mut().zip(values) {
779                read.set_result(value);
780            }
781        }
782
783        Ok(())
784    }
785
786    async fn translate_browse_paths_to_node_ids(
787        &self,
788        context: &RequestContext,
789        nodes: &mut [&mut BrowsePathItem],
790    ) -> Result<(), StatusCode> {
791        let address_space = trace_read_lock!(self.address_space);
792        let type_tree = trace_read_lock!(context.type_tree);
793
794        for node in nodes {
795            Self::translate_browse_paths(
796                &address_space,
797                &type_tree,
798                context,
799                &self.namespaces,
800                node,
801            );
802        }
803
804        Ok(())
805    }
806
807    async fn register_nodes(
808        &self,
809        context: &RequestContext,
810        nodes: &mut [&mut RegisterNodeItem],
811    ) -> Result<(), StatusCode> {
812        self.inner
813            .register_nodes(context, &self.address_space, nodes)
814            .await
815    }
816
817    async fn unregister_nodes(
818        &self,
819        context: &RequestContext,
820        nodes: &[&NodeId],
821    ) -> Result<(), StatusCode> {
822        self.inner
823            .unregister_nodes(context, &self.address_space, nodes)
824            .await
825    }
826
827    async fn create_monitored_items(
828        &self,
829        context: &RequestContext,
830        items: &mut [&mut CreateMonitoredItem],
831    ) -> Result<(), StatusCode> {
832        let mut value_items = Vec::new();
833        let mut event_items = Vec::new();
834
835        {
836            let address_space = trace_read_lock!(self.address_space);
837            for node in items {
838                if node.item_to_monitor().attribute_id == AttributeId::Value {
839                    value_items.push(node);
840                    continue;
841                }
842
843                let n = match address_space.validate_node_read(context, node.item_to_monitor()) {
844                    Ok(n) => n,
845                    Err(e) => {
846                        node.set_status(e);
847                        continue;
848                    }
849                };
850
851                let read_result = read_node_value(
852                    n,
853                    context,
854                    node.item_to_monitor(),
855                    0.0,
856                    node.timestamps_to_return(),
857                );
858
859                // Event monitored items are global, so all we need to do is to validate that the
860                // node allows subscribing to events.
861                if node.item_to_monitor().attribute_id == AttributeId::EventNotifier {
862                    let Some(Variant::Byte(notifier)) = &read_result.value else {
863                        node.set_status(StatusCode::BadAttributeIdInvalid);
864                        continue;
865                    };
866                    let notifier = EventNotifier::from_bits_truncate(*notifier);
867                    if !notifier.contains(EventNotifier::SUBSCRIBE_TO_EVENTS) {
868                        node.set_status(StatusCode::BadAttributeIdInvalid);
869                        continue;
870                    }
871
872                    // No further action beyond just validation.
873                    node.set_status(StatusCode::Good);
874                    event_items.push(node);
875                    continue;
876                }
877
878                // This specific status code here means that the value does not exist, so it is
879                // more appropriate to not set an initial value.
880                if read_result.status() != StatusCode::BadAttributeIdInvalid {
881                    node.set_initial_value(read_result);
882                }
883
884                node.set_status(StatusCode::Good);
885            }
886        }
887
888        if !value_items.is_empty() {
889            self.inner
890                .create_value_monitored_items(context, &self.address_space, &mut value_items)
891                .await;
892        }
893
894        if !event_items.is_empty() {
895            self.inner
896                .create_event_monitored_items(context, &self.address_space, &mut event_items)
897                .await;
898        }
899
900        Ok(())
901    }
902
903    async fn modify_monitored_items(
904        &self,
905        context: &RequestContext,
906        items: &[&MonitoredItemUpdateRef],
907    ) {
908        let items: Vec<_> = items
909            .iter()
910            .filter(|it| {
911                matches!(
912                    it.attribute(),
913                    AttributeId::Value | AttributeId::EventNotifier
914                )
915            })
916            .copied()
917            .collect();
918        self.inner.modify_monitored_items(context, &items).await;
919    }
920
921    async fn set_monitoring_mode(
922        &self,
923        context: &RequestContext,
924        mode: MonitoringMode,
925        items: &[&MonitoredItemRef],
926    ) {
927        let items: Vec<_> = items
928            .iter()
929            .filter(|it| {
930                matches!(
931                    it.attribute(),
932                    AttributeId::Value | AttributeId::EventNotifier
933                )
934            })
935            .copied()
936            .collect();
937        self.inner.set_monitoring_mode(context, mode, &items).await;
938    }
939
940    async fn delete_monitored_items(&self, context: &RequestContext, items: &[&MonitoredItemRef]) {
941        let items: Vec<_> = items
942            .iter()
943            .filter(|it| {
944                matches!(
945                    it.attribute(),
946                    AttributeId::Value | AttributeId::EventNotifier
947                )
948            })
949            .copied()
950            .collect();
951        self.inner.delete_monitored_items(context, &items).await;
952    }
953
954    async fn history_read_raw_modified(
955        &self,
956        context: &RequestContext,
957        details: &ReadRawModifiedDetails,
958        nodes: &mut [&mut HistoryNode],
959        timestamps_to_return: TimestampsToReturn,
960    ) -> Result<(), StatusCode> {
961        let mut nodes = self.validate_history_read_nodes(context, nodes, false);
962        self.inner
963            .history_read_raw_modified(context, details, &mut nodes, timestamps_to_return)
964            .await
965    }
966
967    async fn history_read_processed(
968        &self,
969        context: &RequestContext,
970        details: &ReadProcessedDetails,
971        nodes: &mut [&mut HistoryNode],
972        timestamps_to_return: TimestampsToReturn,
973    ) -> Result<(), StatusCode> {
974        let mut nodes = self.validate_history_read_nodes(context, nodes, false);
975        self.inner
976            .history_read_processed(context, details, &mut nodes, timestamps_to_return)
977            .await
978    }
979
980    async fn history_read_at_time(
981        &self,
982        context: &RequestContext,
983        details: &ReadAtTimeDetails,
984        nodes: &mut [&mut HistoryNode],
985        timestamps_to_return: TimestampsToReturn,
986    ) -> Result<(), StatusCode> {
987        let mut nodes = self.validate_history_read_nodes(context, nodes, false);
988        self.inner
989            .history_read_at_time(context, details, &mut nodes, timestamps_to_return)
990            .await
991    }
992
993    async fn history_read_events(
994        &self,
995        context: &RequestContext,
996        details: &ReadEventDetails,
997        nodes: &mut [&mut HistoryNode],
998        timestamps_to_return: TimestampsToReturn,
999    ) -> Result<(), StatusCode> {
1000        let mut nodes = self.validate_history_read_nodes(context, nodes, false);
1001        self.inner
1002            .history_read_events(context, details, &mut nodes, timestamps_to_return)
1003            .await
1004    }
1005
1006    async fn history_read_annotations(
1007        &self,
1008        context: &RequestContext,
1009        details: &ReadAnnotationDataDetails,
1010        nodes: &mut [&mut HistoryNode],
1011        timestamps_to_return: TimestampsToReturn,
1012    ) -> Result<(), StatusCode> {
1013        let mut nodes = self.validate_history_read_nodes(context, nodes, false);
1014        self.inner
1015            .history_read_annotations(context, details, &mut nodes, timestamps_to_return)
1016            .await
1017    }
1018
1019    async fn write(
1020        &self,
1021        context: &RequestContext,
1022        nodes_to_write: &mut [&mut WriteNode],
1023    ) -> Result<(), StatusCode> {
1024        self.inner
1025            .write(context, &self.address_space, nodes_to_write)
1026            .await
1027    }
1028
1029    async fn history_update(
1030        &self,
1031        context: &RequestContext,
1032        nodes: &mut [&mut HistoryUpdateNode],
1033    ) -> Result<(), StatusCode> {
1034        let mut nodes = self.validate_history_write_nodes(context, nodes);
1035        self.inner.history_update(context, &mut nodes).await
1036    }
1037
1038    async fn call(
1039        &self,
1040        context: &RequestContext,
1041        methods_to_call: &mut [&mut MethodCall],
1042    ) -> Result<(), StatusCode> {
1043        let mut to_call = self.validate_method_calls(context, methods_to_call);
1044        self.inner
1045            .call(context, &self.address_space, &mut to_call)
1046            .await
1047    }
1048
1049    /// Add a list of nodes.
1050    ///
1051    /// This should create the nodes, or set a failed status as appropriate.
1052    /// If a node was created, the status should be set to Good.
1053    async fn add_nodes(
1054        &self,
1055        context: &RequestContext,
1056        nodes_to_add: &mut [&mut AddNodeItem],
1057    ) -> Result<(), StatusCode> {
1058        self.inner
1059            .add_nodes(context, &self.address_space, nodes_to_add)
1060            .await
1061    }
1062
1063    async fn add_references(
1064        &self,
1065        context: &RequestContext,
1066        references_to_add: &mut [&mut AddReferenceItem],
1067    ) -> Result<(), StatusCode> {
1068        self.inner
1069            .add_references(context, &self.address_space, references_to_add)
1070            .await
1071    }
1072
1073    async fn delete_nodes(
1074        &self,
1075        context: &RequestContext,
1076        nodes_to_delete: &mut [&mut DeleteNodeItem],
1077    ) -> Result<(), StatusCode> {
1078        self.inner
1079            .delete_nodes(context, &self.address_space, nodes_to_delete)
1080            .await
1081    }
1082
1083    async fn delete_node_references(
1084        &self,
1085        context: &RequestContext,
1086        to_delete: &[&DeleteNodeItem],
1087    ) {
1088        self.inner
1089            .delete_node_references(context, &self.address_space, to_delete)
1090            .await
1091    }
1092
1093    async fn delete_references(
1094        &self,
1095        context: &RequestContext,
1096        references_to_delete: &mut [&mut DeleteReferenceItem],
1097    ) -> Result<(), StatusCode> {
1098        self.inner
1099            .delete_references(context, &self.address_space, references_to_delete)
1100            .await
1101    }
1102}