opcua_types/request_header.rs
1// OPCUA for Rust
2// SPDX-License-Identifier: MPL-2.0
3// Copyright (C) 2017-2022 Adam Lock
4
5use std::{
6 self,
7 io::{Read, Write},
8};
9
10use crate::{
11 data_types::*, date_time::DateTime, diagnostic_info::DiagnosticBits, encoding::*,
12 extension_object::ExtensionObject, node_id::NodeId, string::UAString,
13};
14
15/// The `RequestHeader` contains information common to every request from a client to the server.
16#[derive(Debug, Clone, PartialEq)]
17pub struct RequestHeader {
18 /// The secret Session identifier used to verify that the request is associated with
19 /// the Session. The SessionAuthenticationToken type is defined in 7.31.
20 pub authentication_token: NodeId,
21 /// The time the Client sent the request. The parameter is only used for diagnostic and logging
22 /// purposes in the server.
23 pub timestamp: UtcTime,
24 /// A requestHandle associated with the request. This client defined handle can be
25 /// used to cancel the request. It is also returned in the response.
26 pub request_handle: IntegerId,
27 /// A bit mask that identifies the types of vendor-specific diagnostics to be returned
28 /// in diagnosticInfo response parameters. The value of this parameter may consist of
29 /// zero, one or more of the following values. No value indicates that diagnostics
30 /// are not to be returned.
31 ///
32 /// Bit Value Diagnostics to return
33 /// 0x0000 0001 ServiceLevel / SymbolicId
34 /// 0x0000 0002 ServiceLevel / LocalizedText
35 /// 0x0000 0004 ServiceLevel / AdditionalInfo
36 /// 0x0000 0008 ServiceLevel / Inner StatusCode
37 /// 0x0000 0010 ServiceLevel / Inner Diagnostics
38 /// 0x0000 0020 OperationLevel / SymbolicId
39 /// 0x0000 0040 OperationLevel / LocalizedText
40 /// 0x0000 0080 OperationLevel / AdditionalInfo
41 /// 0x0000 0100 OperationLevel / Inner StatusCode
42 /// 0x0000 0200 OperationLevel / Inner Diagnostics
43 ///
44 /// Each of these values is composed of two components, level and type, as described
45 /// below. If none are requested, as indicated by a 0 value, or if no diagnostic
46 /// information was encountered in processing of the request, then diagnostics information
47 /// is not returned.
48 ///
49 /// Level:
50 /// ServiceLevel return diagnostics in the diagnosticInfo of the Service.
51 /// OperationLevel return diagnostics in the diagnosticInfo defined for individual
52 /// operations requested in the Service.
53 ///
54 /// Type:
55 /// SymbolicId return a namespace-qualified, symbolic identifier for an error
56 /// or condition. The maximum length of this identifier is 32 characters.
57 /// LocalizedText return up to 256 bytes of localized text that describes the
58 /// symbolic id.
59 /// AdditionalInfo return a byte string that contains additional diagnostic
60 /// information, such as a memory image. The format of this byte string is
61 /// vendor-specific, and may depend on the type of error or condition encountered.
62 /// InnerStatusCode return the inner StatusCode associated with the operation or Service.
63 /// InnerDiagnostics return the inner diagnostic info associated with the operation or Service.
64 /// The contents of the inner diagnostic info structure are determined by other bits in the
65 /// mask. Note that setting this bit could cause multiple levels of nested
66 /// diagnostic info structures to be returned.
67 pub return_diagnostics: DiagnosticBits,
68 /// An identifier that identifies the Client’s security audit log entry associated with
69 /// this request. An empty string value means that this parameter is not used. The AuditEntryId
70 /// typically contains who initiated the action and from where it was initiated.
71 /// The AuditEventId is included in the AuditEvent to allow human readers to correlate an Event
72 /// with the initiating action. More details of the Audit mechanisms are defined in 6.2
73 /// and in Part 3.
74 pub audit_entry_id: UAString,
75 /// This timeout in milliseconds is used in the Client side Communication Stack to set the
76 /// timeout on a per-call base. For a Server this timeout is only a hint and can be
77 /// used to cancel long running operations to free resources. If the Server detects a
78 /// timeout, he can cancel the operation by sending the Service result BadTimeout.
79 /// The Server should wait at minimum the timeout after he received the request before
80 /// cancelling the operation. The Server shall check the timeoutHint parameter of a
81 /// PublishRequest before processing a PublishResponse. If the request timed out, a
82 /// BadTimeout Service result is sent and another PublishRequest is used. The
83 /// value of 0 indicates no timeout.
84 pub timeout_hint: u32,
85 /// Reserved for future use. Applications that do not understand the header should ignore it.
86 pub additional_header: ExtensionObject,
87}
88
89impl BinaryEncoder<RequestHeader> for RequestHeader {
90 fn byte_len(&self) -> usize {
91 let mut size: usize = 0;
92 size += self.authentication_token.byte_len();
93 size += self.timestamp.byte_len();
94 size += self.request_handle.byte_len();
95 size += self.return_diagnostics.bits().byte_len();
96 size += self.audit_entry_id.byte_len();
97 size += self.timeout_hint.byte_len();
98 size += self.additional_header.byte_len();
99 size
100 }
101
102 fn encode<S: Write>(&self, stream: &mut S) -> EncodingResult<usize> {
103 let mut size: usize = 0;
104 size += self.authentication_token.encode(stream)?;
105 size += self.timestamp.encode(stream)?;
106 size += self.request_handle.encode(stream)?;
107 size += self.return_diagnostics.bits().encode(stream)?;
108 size += self.audit_entry_id.encode(stream)?;
109 size += self.timeout_hint.encode(stream)?;
110 size += self.additional_header.encode(stream)?;
111 Ok(size)
112 }
113
114 fn decode<S: Read>(stream: &mut S, decoding_options: &DecodingOptions) -> EncodingResult<Self> {
115 let authentication_token = NodeId::decode(stream, decoding_options)?;
116 let timestamp = UtcTime::decode(stream, decoding_options)?;
117 let request_handle = IntegerId::decode(stream, decoding_options)?;
118 let return_diagnostics =
119 DiagnosticBits::from_bits_truncate(u32::decode(stream, decoding_options)?);
120 let audit_entry_id = UAString::decode(stream, decoding_options)?;
121 let timeout_hint = u32::decode(stream, decoding_options)?;
122 let additional_header = ExtensionObject::decode(stream, decoding_options)?;
123 Ok(RequestHeader {
124 authentication_token,
125 timestamp,
126 request_handle,
127 return_diagnostics,
128 audit_entry_id,
129 timeout_hint,
130 additional_header,
131 })
132 }
133}
134
135impl RequestHeader {
136 pub fn new(
137 authentication_token: &NodeId,
138 timestamp: &DateTime,
139 request_handle: IntegerId,
140 ) -> RequestHeader {
141 RequestHeader {
142 authentication_token: authentication_token.clone(),
143 timestamp: *timestamp,
144 request_handle,
145 return_diagnostics: DiagnosticBits::empty(),
146 audit_entry_id: UAString::null(),
147 timeout_hint: 0,
148 additional_header: ExtensionObject::null(),
149 }
150 }
151
152 pub fn dummy() -> RequestHeader {
153 RequestHeader::new(&NodeId::null(), &DateTime::now(), 1)
154 }
155}