opcua_server/node_manager/
query.rs1use crate::session::{
2 continuation_points::{ContinuationPoint, EmptyContinuationPoint},
3 instance::Session,
4};
5use opcua_crypto::random;
6use opcua_nodes::ParsedContentFilter;
7use opcua_types::{
8 AttributeId, ByteString, ExpandedNodeId, NodeTypeDescription, NumericRange, ParsingResult,
9 QueryDataDescription, QueryDataSet, RelativePath, StatusCode,
10};
11
12pub(crate) struct QueryContinuationPoint {
13 pub node_manager_index: usize,
14 pub continuation_point: ContinuationPoint,
15 pub id: ByteString,
16
17 node_types: Vec<ParsedNodeTypeDescription>,
18 filter: ParsedContentFilter,
19 max_data_sets_to_return: usize,
20 max_references_to_return: usize,
21}
22
23#[derive(Debug)]
24pub struct ParsedQueryDataDescription {
26 pub relative_path: RelativePath,
28 pub attribute_id: AttributeId,
30 pub index_range: NumericRange,
32}
33
34impl ParsedQueryDataDescription {
35 pub(crate) fn parse(desc: QueryDataDescription) -> Result<Self, StatusCode> {
36 let attribute_id = AttributeId::from_u32(desc.attribute_id)
37 .map_err(|_| StatusCode::BadAttributeIdInvalid)?;
38
39 Ok(Self {
40 relative_path: desc.relative_path,
41 attribute_id,
42 index_range: desc.index_range,
43 })
44 }
45}
46
47#[derive(Debug)]
48pub struct ParsedNodeTypeDescription {
50 pub type_definition_node: ExpandedNodeId,
52 pub include_sub_types: bool,
54 pub data_to_return: Vec<ParsedQueryDataDescription>,
56}
57
58impl ParsedNodeTypeDescription {
59 pub(crate) fn parse(desc: NodeTypeDescription) -> (ParsingResult, Result<Self, StatusCode>) {
60 let num_descs = desc
61 .data_to_return
62 .as_ref()
63 .map(|d| d.len())
64 .unwrap_or_default();
65 let mut desc_results = Vec::with_capacity(num_descs);
66 let mut final_descs = Vec::with_capacity(num_descs);
67 for child in desc.data_to_return.into_iter().flatten() {
68 match ParsedQueryDataDescription::parse(child) {
69 Ok(c) => {
70 desc_results.push(StatusCode::Good);
71 final_descs.push(c);
72 }
73 Err(e) => desc_results.push(e),
74 }
75 }
76
77 if final_descs.len() < num_descs {
78 return (
79 ParsingResult {
80 status_code: StatusCode::BadInvalidArgument,
81 data_status_codes: Some(desc_results),
82 data_diagnostic_infos: None,
83 },
84 Err(StatusCode::BadInvalidArgument),
85 );
86 }
87
88 (
89 ParsingResult {
90 status_code: StatusCode::Good,
91 data_diagnostic_infos: None,
92 data_status_codes: None,
93 },
94 Ok(ParsedNodeTypeDescription {
95 type_definition_node: desc.type_definition_node,
96 include_sub_types: desc.include_sub_types,
97 data_to_return: final_descs,
98 }),
99 )
100 }
101}
102
103pub struct QueryRequest {
105 node_types: Vec<ParsedNodeTypeDescription>,
106 filter: ParsedContentFilter,
107 max_data_sets_to_return: usize,
108 max_references_to_return: usize,
109 continuation_point: Option<ContinuationPoint>,
110 next_continuation_point: Option<ContinuationPoint>,
111 status: StatusCode,
112 node_manager_index: usize,
113
114 data_sets: Vec<QueryDataSet>,
115}
116
117impl QueryRequest {
118 pub(crate) fn new(
119 node_types: Vec<ParsedNodeTypeDescription>,
120 filter: ParsedContentFilter,
121 max_data_sets_to_return: usize,
122 max_references_to_return: usize,
123 ) -> Self {
124 Self {
125 node_types,
126 filter,
127 max_data_sets_to_return,
128 max_references_to_return,
129 continuation_point: None,
130 next_continuation_point: None,
131 data_sets: Vec::new(),
132 status: StatusCode::Good,
133 node_manager_index: 0,
134 }
135 }
136
137 pub(crate) fn from_continuation_point(point: QueryContinuationPoint) -> Self {
138 Self {
139 node_types: point.node_types,
140 filter: point.filter,
141 max_data_sets_to_return: point.max_data_sets_to_return,
142 max_references_to_return: point.max_references_to_return,
143 continuation_point: Some(point.continuation_point),
144 next_continuation_point: None,
145 status: StatusCode::Good,
146 data_sets: Vec::new(),
147 node_manager_index: point.node_manager_index,
148 }
149 }
150
151 pub fn data_sets(&self) -> &[QueryDataSet] {
153 &self.data_sets
154 }
155
156 pub fn continuation_point(&self) -> Option<&ContinuationPoint> {
158 self.continuation_point.as_ref()
159 }
160
161 pub fn max_references_to_return(&self) -> usize {
163 self.max_references_to_return
164 }
165
166 pub fn max_data_sets_to_return(&self) -> usize {
168 self.max_data_sets_to_return
169 }
170
171 pub fn filter(&self) -> &ParsedContentFilter {
173 &self.filter
174 }
175
176 pub fn node_types(&self) -> &[ParsedNodeTypeDescription] {
178 &self.node_types
179 }
180
181 pub fn remaining_data_sets(&self) -> usize {
183 if self.data_sets.len() >= self.max_data_sets_to_return {
184 0
185 } else {
186 self.max_data_sets_to_return - self.data_sets.len()
187 }
188 }
189
190 pub fn is_completed(&self) -> bool {
192 self.remaining_data_sets() == 0 || self.next_continuation_point.is_some()
193 }
194
195 pub(crate) fn into_result(
196 self,
197 node_manager_index: usize,
198 node_manager_count: usize,
199 session: &mut Session,
200 ) -> (Vec<QueryDataSet>, ByteString, StatusCode) {
201 if self.status.is_bad() {
203 return (Vec::new(), ByteString::null(), self.status);
204 }
205 let inner = self
211 .next_continuation_point
212 .map(|c| (c, node_manager_index))
213 .or_else(|| {
214 if node_manager_index < node_manager_count - 1 {
215 Some((
216 ContinuationPoint::new(Box::new(EmptyContinuationPoint)),
217 node_manager_index + 1,
218 ))
219 } else {
220 None
221 }
222 });
223
224 let continuation_point = inner.map(|(p, node_manager_index)| QueryContinuationPoint {
225 node_manager_index,
226 continuation_point: p,
227 id: random::byte_string(6),
228 node_types: self.node_types,
229 filter: self.filter,
230 max_data_sets_to_return: self.max_data_sets_to_return,
231 max_references_to_return: self.max_references_to_return,
232 });
233
234 let mut status = self.status;
235 let mut cp_id = continuation_point
236 .as_ref()
237 .map(|c| c.id.clone())
238 .unwrap_or_default();
239
240 if let Some(c) = continuation_point {
243 if session.add_query_continuation_point(&cp_id, c).is_err() {
244 status = StatusCode::BadNoContinuationPoints;
245 cp_id = ByteString::null();
246 }
247 }
248
249 (self.data_sets, cp_id, status)
250 }
251
252 pub fn status(&self) -> StatusCode {
254 self.status
255 }
256
257 pub fn set_status(&mut self, status: StatusCode) {
259 self.status = status;
260 }
261
262 pub fn set_next_continuation_point(
264 &mut self,
265 next_continuation_point: Option<ContinuationPoint>,
266 ) {
267 self.next_continuation_point = next_continuation_point;
268 }
269
270 pub(crate) fn node_manager_index(&self) -> usize {
271 self.node_manager_index
272 }
273}