1mod 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
61pub struct InMemoryNodeManager<TImpl> {
67 address_space: Arc<RwLock<AddressSpace>>,
68 namespaces: HashMap<u16, String>,
69 inner: TImpl,
70}
71
72pub struct InMemoryNodeManagerBuilder<T> {
74 impl_builder: T,
75}
76
77impl<T: InMemoryNodeManagerImplBuilder> InMemoryNodeManagerBuilder<T> {
78 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 pub fn inner(&self) -> &TImpl {
104 &self.inner
105 }
106
107 pub fn address_space(&self) -> &Arc<RwLock<AddressSpace>> {
109 &self.address_space
110 }
111
112 pub fn namespaces(&self) -> &HashMap<u16, String> {
115 &self.namespaces
116 }
117
118 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 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 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 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 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 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 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 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 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 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.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 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 node.set_status(StatusCode::Good);
874 event_items.push(node);
875 continue;
876 }
877
878 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 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}