opcua_server/node_manager/
context.rs1use std::sync::Arc;
2
3use crate::{
4 authenticator::{AuthManager, UserToken},
5 info::ServerInfo,
6 session::instance::Session,
7 SubscriptionCache,
8};
9use opcua_core::{sync::RwLock, trace_read_lock};
10use opcua_nodes::TypeTree;
11use opcua_types::{BrowseDescriptionResultMask, NodeId};
12use parking_lot::lock_api::{RawRwLock, RwLockReadGuard};
13use tracing::debug_span;
14use tracing_futures::Instrument;
15
16use super::{
17 view::{ExternalReferenceRequest, NodeMetadata},
18 DefaultTypeTree, NodeManagers,
19};
20
21pub trait TypeTreeForUserStatic: Send + Sync {
24 fn get_type_tree<'a>(&'a self) -> Box<dyn TypeTreeReadContext + 'a>;
26}
27
28impl<T> TypeTreeForUserStatic for RwLock<T>
29where
30 T: TypeTree + Send + Sync + 'static,
31{
32 fn get_type_tree<'a>(&'a self) -> Box<dyn TypeTreeReadContext + 'a> {
33 Box::new(trace_read_lock!(self))
34 }
35}
36
37pub trait TypeTreeForUser: Send + Sync {
42 fn get_type_tree_for_user<'a>(
47 &'a self,
48 ctx: &'a RequestContext,
49 ) -> Box<dyn TypeTreeReadContext + 'a>;
50
51 fn get_type_tree_static(&self, ctx: &RequestContext) -> Arc<dyn TypeTreeForUserStatic>;
55}
56
57pub(crate) struct DefaultTypeTreeGetter;
58
59impl TypeTreeForUser for DefaultTypeTreeGetter {
60 fn get_type_tree_for_user<'a>(
61 &'a self,
62 ctx: &'a RequestContext,
63 ) -> Box<dyn TypeTreeReadContext + 'a> {
64 Box::new(trace_read_lock!(ctx.type_tree))
65 }
66
67 fn get_type_tree_static(&self, ctx: &RequestContext) -> Arc<dyn TypeTreeForUserStatic> {
68 ctx.type_tree.clone()
69 }
70}
71
72pub trait TypeTreeReadContext {
75 fn get(&self) -> &dyn TypeTree;
77}
78
79impl<R: RawRwLock, T: TypeTree> TypeTreeReadContext for RwLockReadGuard<'_, R, T> {
80 fn get(&self) -> &dyn TypeTree {
81 &**self
82 }
83}
84
85#[derive(Clone)]
86pub struct RequestContext {
89 pub session: Arc<RwLock<Session>>,
91 pub session_id: u32,
93 pub authenticator: Arc<dyn AuthManager>,
95 pub token: UserToken,
97 pub current_node_manager_index: usize,
99 pub type_tree: Arc<RwLock<DefaultTypeTree>>,
101 pub type_tree_getter: Arc<dyn TypeTreeForUser>,
103 pub subscriptions: Arc<SubscriptionCache>,
105 pub info: Arc<ServerInfo>,
108}
109
110impl RequestContext {
111 pub fn get_type_tree_for_user<'a>(&'a self) -> Box<dyn TypeTreeReadContext + 'a> {
113 self.type_tree_getter.get_type_tree_for_user(self)
114 }
115}
116
117pub(crate) async fn resolve_external_references(
119 context: &RequestContext,
120 node_managers: &NodeManagers,
121 references: &[(&NodeId, BrowseDescriptionResultMask)],
122) -> Vec<Option<NodeMetadata>> {
123 let mut res: Vec<_> = references
124 .iter()
125 .map(|(n, mask)| ExternalReferenceRequest::new(n, *mask))
126 .collect();
127
128 for nm in node_managers.iter() {
129 let mut items: Vec<_> = res
130 .iter_mut()
131 .filter(|r| nm.owns_node(r.node_id()))
132 .collect();
133
134 nm.resolve_external_references(context, &mut items)
135 .instrument(debug_span!("resolve external references", node_manager = %nm.name()))
136 .await;
137 }
138
139 res.into_iter().map(|r| r.into_inner()).collect()
140}