opcua_server/node_manager/
context.rs1use std::{ops::Deref, 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 current_node_manager_index: usize,
91 pub(crate) inner: Arc<RequestContextInner>,
93}
94
95impl Deref for RequestContext {
98 type Target = RequestContextInner;
99
100 fn deref(&self) -> &RequestContextInner {
101 &self.inner
102 }
103}
104
105pub struct RequestContextInner {
107 pub session: Arc<RwLock<Session>>,
109 pub session_id: u32,
111 pub authenticator: Arc<dyn AuthManager>,
113 pub token: UserToken,
115 pub type_tree: Arc<RwLock<DefaultTypeTree>>,
117 pub type_tree_getter: Arc<dyn TypeTreeForUser>,
119 pub subscriptions: Arc<SubscriptionCache>,
121 pub info: Arc<ServerInfo>,
124}
125
126impl RequestContext {
127 pub fn get_type_tree_for_user<'a>(&'a self) -> Box<dyn TypeTreeReadContext + 'a> {
129 self.type_tree_getter.get_type_tree_for_user(self)
130 }
131
132 pub fn session(&self) -> &RwLock<Session> {
134 &self.session
135 }
136
137 pub fn session_id(&self) -> u32 {
139 self.session_id
140 }
141
142 pub fn authenticator(&self) -> &dyn AuthManager {
144 self.authenticator.as_ref()
145 }
146
147 pub fn user_token(&self) -> &UserToken {
149 &self.token
150 }
151
152 pub fn type_tree(&self) -> &RwLock<DefaultTypeTree> {
155 &self.type_tree
156 }
157
158 pub fn subscriptions(&self) -> &SubscriptionCache {
160 &self.subscriptions
161 }
162
163 pub fn info(&self) -> &ServerInfo {
165 &self.info
166 }
167}
168
169pub(crate) async fn resolve_external_references(
171 context: &RequestContext,
172 node_managers: &NodeManagers,
173 references: &[(&NodeId, BrowseDescriptionResultMask)],
174) -> Vec<Option<NodeMetadata>> {
175 let mut res: Vec<_> = references
176 .iter()
177 .map(|(n, mask)| ExternalReferenceRequest::new(n, *mask))
178 .collect();
179
180 for nm in node_managers.iter() {
181 let mut items: Vec<_> = res
182 .iter_mut()
183 .filter(|r| nm.owns_node(r.node_id()))
184 .collect();
185
186 nm.resolve_external_references(context, &mut items)
187 .instrument(debug_span!("resolve external references", node_manager = %nm.name()))
188 .await;
189 }
190
191 res.into_iter().map(|r| r.into_inner()).collect()
192}